From 170be95dc53612428ad9e58e114f67e9ea7d9c6f Mon Sep 17 00:00:00 2001 From: Exynox Date: Sun, 2 Jun 2024 21:45:51 +0300 Subject: [PATCH] Configuration files are automatically generated based on env variables in the Docker image --- Dockerfile | 11 ++++++++- README.md | 6 ++--- docker/conf/db.conf.tmpl | 18 ++++++++++++++ docker/conf/game.conf.tmpl | 41 +++++++++++++++++++++++++++++++ docker/docker-entrypoint.sh | 9 +++++++ gamefiles/data/quest/questing.lua | 2 +- src/db/src/Main.cpp | 4 +-- src/game/src/config.cpp | 28 +++++++++++++++------ 8 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 docker/conf/db.conf.tmpl create mode 100644 docker/conf/game.conf.tmpl create mode 100644 docker/docker-entrypoint.sh diff --git a/Dockerfile b/Dockerfile index c8f6c5e..8c970af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ RUN cd build && make -j $(nproc) FROM ubuntu:22.04 as app WORKDIR /app -RUN apt-get update && apt-get install -y python2 libdevil-dev libbsd-dev && apt-get clean +RUN apt-get update && apt-get install -y gettext python2 libdevil-dev libbsd-dev && apt-get clean # Copy the binaries from the build stage COPY --from=build /app/build/src/db/db /bin/db @@ -39,6 +39,9 @@ COPY --from=build /app/build/src/quest/qc /bin/qc # Copy the game files COPY ./gamefiles/ . +# Copy the auxiliary files +COPY ./docker/ . + # Compile the quests RUN cd /app/data/quest && python2 make.py @@ -48,3 +51,9 @@ RUN ln -s ./conf/item_names_en.txt item_names.txt RUN ln -s ./conf/item_proto.txt item_proto.txt RUN ln -s ./conf/mob_names_en.txt mob_names.txt RUN ln -s ./conf/mob_proto.txt mob_proto.txt + +# Set up default environment variables +ENV PUBLIC_BIND_IP 0.0.0.0 +ENV INTERNAL_BIND_IP 0.0.0.0 + +ENTRYPOINT ["/usr/bin/bash", "docker-entrypoint.sh"] diff --git a/README.md b/README.md index 1aac98a..f07e890 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Also install DevIL (1.7.8) and the BSD compatibility library: apt-get install -y libdevil-dev libbsd-dev ``` -Install `vcpkg` according to the [lastest instructions](https://vcpkg.io/en/getting-started.html). +Install `vcpkg` according to the [latest instructions](https://vcpkg.io/en/getting-started.html). Build and install the required libraries: ```shell @@ -79,7 +79,7 @@ goodies you wish. Also, a lot of time. - Removed unused functionalities (time bombs, activation servers, other Korean stuff) - Switched to the [effolkronium/random PRNG](https://github.com/effolkronium/random) instead of the standard C functions. - Refactored macros to modern C++ functions. -- Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `CONFIG` file. (Might need further work) +- Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `game.conf` file. (Might need further work) - Refactored logging to use [spdlog](https://github.com/gabime/spdlog) for more consistent function calls. - Refactored login code to use Argon2ID. @@ -102,7 +102,7 @@ This is a very serious security risk and one of the reasons this project is stil - Fixed buffer overruns and integer overflows in SQL queries. ## 5. Further plans -- Migrate `conf.txt` and `CONFIG` to a modern dotenv-like format, which would enable pretty nice Docker images. +- Migrate `db.conf` and `game.conf` to a modern dotenv-like format, which would enable pretty nice Docker images. - Add a health check to the Docker image. - Use the [fmt](https://fmt.dev/latest/index.html) library for safe and modern string formatting. - Handle kernel signals (SIGTERM, SIGHUP etc.) for gracefully shutting down the game server. diff --git a/docker/conf/db.conf.tmpl b/docker/conf/db.conf.tmpl new file mode 100644 index 0000000..3f9493b --- /dev/null +++ b/docker/conf/db.conf.tmpl @@ -0,0 +1,18 @@ +WELCOME_MSG = "DB Server has been started" + +SQL_ACCOUNT = "${MYSQL_HOST} ${MYSQL_DB_ACCOUNT} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}" +SQL_COMMON = "${MYSQL_HOST} ${MYSQL_DB_COMMON} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}" +SQL_PLAYER = "${MYSQL_HOST} ${MYSQL_DB_PLAYER} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}" + +TABLE_POSTFIX = "" + +BIND_PORT = ${DB_PORT} +DB_SLEEP_MSEC = 10 +CLIENT_HEART_FPS = 10 +HASH_PLAYER_LIFE_SEC = 600 +BACKUP_LIMIT_SEC = 3600 +PLAYER_ID_START = 100 +PLAYER_DELETE_LEVEL_LIMIT = 70 + +ITEM_ID_RANGE = 10000001 20000000 +TEST_SERVER = ${TEST_SERVER} diff --git a/docker/conf/game.conf.tmpl b/docker/conf/game.conf.tmpl new file mode 100644 index 0000000..dbf8e37 --- /dev/null +++ b/docker/conf/game.conf.tmpl @@ -0,0 +1,41 @@ +HOSTNAME: ${GAME_HOSTNAME} +CHANNEL: ${GAME_CHANNEL} + +PUBLIC_IP: ${PUBLIC_IP} +PUBLIC_BIND_IP: ${PUBLIC_BIND_IP} +INTERNAL_IP: ${INTERNAL_IP} +INTERNAL_BIND_IP: ${INTERNAL_BIND_IP} +PORT: ${GAME_PORT} +P2P_PORT: ${GAME_P2P_PORT} + +DB_ADDR: ${DB_ADDR} +DB_PORT: ${DB_PORT} + +COMMON_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_COMMON} ${MYSQL_PORT} +LOG_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_LOG} ${MYSQL_PORT} +PLAYER_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_PLAYER} ${MYSQL_PORT} +TABLE_POSTFIX: + +AUTH_SERVER: ${GAME_AUTH_SERVER} +MARK_SERVER: ${GAME_MARK_SERVER} + +MAP_ALLOW: ${GAME_MAP_ALLOW} +MAX_LEVEL: ${GAME_MAX_LEVEL} +PK_PROTECT_LEVEL: 15 +SPAM_BLOCK_MAX_LEVEL: 90 +GOLD_DROP_LIMIT_TIME: 10 +MALL_URL: ${GAME_MALL_URL} + +CHECK_MULTIHACK: 0 +SPEEDHACK_LIMIT_COUNT: 300 +SPEEDHACK_LIMIT_BONUS: 80 + +ADMINPAGE_IP: 127.0.0.1 +ADMINPAGE_PASSWORD: metin2adminpass + +PASSES_PER_SEC: 25 +SAVE_EVENT_SECOND_CYCLE: 180 +PING_EVENT_SECOND_CYCLE: 180 +VIEW_RANGE: 8000 + +TEST_SERVER: ${TEST_SERVER} diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100644 index 0000000..ba8200b --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# docker-entrypoint.sh + +# Generate configuration files based on environment variables +envsubst <"/app/conf/db.conf.tmpl" >"/app/db.conf" +envsubst <"/app/conf/game.conf.tmpl" >"/app/game.conf" + +# Run the standard container command. +exec "$@" diff --git a/gamefiles/data/quest/questing.lua b/gamefiles/data/quest/questing.lua index c7663d8..f366a82 100644 --- a/gamefiles/data/quest/questing.lua +++ b/gamefiles/data/quest/questing.lua @@ -46,7 +46,7 @@ Mysql-Funktion der neuesten Generation. --]] mysql_query = function(query) if not pre then - local rt = io.open('CONFIG','r'):read('*all') + local rt = io.open('game.conf','r'):read('*all') pre,_= string.gsub(rt,'.+PLAYER_SQL:%s(%S+)%s(%S+)%s(%S+)%s(%S+).+','-h%1 -u%2 -p%3 -D%4') end math.randomseed(os.time()) diff --git a/src/db/src/Main.cpp b/src/db/src/Main.cpp index 3fdf6d2..add0cba 100644 --- a/src/db/src/Main.cpp +++ b/src/db/src/Main.cpp @@ -126,9 +126,9 @@ void emptybeat(LPHEART heart, int pulse) // int Start() { - if (!CConfig::instance().LoadFile("conf.txt")) + if (!CConfig::instance().LoadFile("db.conf")) { - SPDLOG_ERROR("Loading conf.txt failed."); + SPDLOG_ERROR("Loading db.conf failed."); return false; } diff --git a/src/game/src/config.cpp b/src/game/src/config.cpp index aedf8b6..b30bd97 100644 --- a/src/game/src/config.cpp +++ b/src/game/src/config.cpp @@ -292,7 +292,7 @@ void config_init(const string& st_localeServiceName) string st_configFileName; st_configFileName.reserve(32); - st_configFileName = "CONFIG"; + st_configFileName = "game.conf"; if (!st_localeServiceName.empty()) { @@ -775,19 +775,27 @@ void config_init(const string& st_localeServiceName) TOKEN("test_server") { - printf("-----------------------------------------------\n"); - printf("TEST_SERVER\n"); - printf("-----------------------------------------------\n"); str_to_number(test_server, value_string); + + if (test_server) { + printf("-----------------------------------------------\n"); + printf("TEST_SERVER\n"); + printf("-----------------------------------------------\n"); + } + continue; } TOKEN("speed_server") { - printf("-----------------------------------------------\n"); - printf("SPEED_SERVER\n"); - printf("-----------------------------------------------\n"); str_to_number(speed_server, value_string); + + if (speed_server) { + printf("-----------------------------------------------\n"); + printf("SPEED_SERVER\n"); + printf("-----------------------------------------------\n"); + } + continue; } #ifdef __AUCTION__ @@ -887,7 +895,11 @@ void config_init(const string& st_localeServiceName) two_arguments(value_string, szIP, sizeof(szIP), szPort, sizeof(szPort)); - if (!*szIP || (!*szPort && strcasecmp(szIP, "master"))) + // Skip if arguments are empty + if (!*szIP) + continue; + + if (!*szPort && strcasecmp(szIP, "master")) { SPDLOG_CRITICAL("AUTH_SERVER: syntax error: "); exit(EXIT_FAILURE);