configmanager.cpp

main 243 lines · 9.6 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "otpch.h"
21
22#if defined(_MSC_VER)
23extern "C"
24{
25#include <luajit/lua.h>
26#include <luajit/lualib.h>
27#include <luajit/lauxlib.h>
28}
29#else
30#include <lua.hpp>
31#endif
32
33#include "configmanager.h"
34#include "game.h"
35
36#if LUA_VERSION_NUM >= 502
37#undef lua_strlen
38#define lua_strlen lua_rawlen
39#endif
40
41extern Game g_game;
42
43namespace {
44
45std::string getGlobalString(lua_State* L, const char* identifier, const char* defaultValue)
46{
47 lua_getglobal(L, identifier);
48 if (!lua_isstring(L, -1)) {
49 lua_pop(L, 1);
50 return defaultValue;
51 }
52
53 size_t len = lua_strlen(L, -1);
54 std::string ret(lua_tostring(L, -1), len);
55 lua_pop(L, 1);
56 return ret;
57}
58
59int32_t getGlobalNumber(lua_State* L, const char* identifier, const int32_t defaultValue = 0)
60{
61 lua_getglobal(L, identifier);
62 if (!lua_isnumber(L, -1)) {
63 lua_pop(L, 1);
64 return defaultValue;
65 }
66
67 int32_t val = lua_tonumber(L, -1);
68 lua_pop(L, 1);
69 return val;
70}
71
72bool getGlobalBoolean(lua_State* L, const char* identifier, const bool defaultValue)
73{
74 lua_getglobal(L, identifier);
75 if (!lua_isboolean(L, -1)) {
76 if (!lua_isstring(L, -1)) {
77 lua_pop(L, 1);
78 return defaultValue;
79 }
80
81 size_t len = lua_strlen(L, -1);
82 std::string ret(lua_tostring(L, -1), len);
83 lua_pop(L, 1);
84 return booleanString(ret);
85 }
86
87 int val = lua_toboolean(L, -1);
88 lua_pop(L, 1);
89 return val != 0;
90}
91
92}
93
94bool ConfigManager::load()
95{
96 lua_State* L = luaL_newstate();
97 if (!L) {
98 throw std::runtime_error("Failed to allocate memory");
99 }
100
101 luaL_openlibs(L);
102
103 if (luaL_dofile(L, "config.lua")) {
104 std::cout << "[Error - ConfigManager::load] " << lua_tostring(L, -1) << std::endl;
105 lua_close(L);
106 return false;
107 }
108
109 //parse config
110 if (!loaded) { //info that must be loaded one time (unless we reset the modules involved)
111 boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false);
112 boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true);
113
114 string[IP] = getGlobalString(L, "ip", "127.0.0.1");
115 string[MAP_NAME] = getGlobalString(L, "mapName", "forgotten");
116 string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Unknown");
117 string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never");
118 string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1");
119 string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "forgottenserver");
120 string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", "");
121 string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "forgottenserver");
122 string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", "");
123
124 integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306);
125 integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172);
126 integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171);
127 integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171);
128
129 integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60);
130 }
131
132 boolean[ALLOW_CHANGEOUTFIT] = getGlobalBoolean(L, "allowChangeOutfit", true);
133 boolean[ONE_PLAYER_ON_ACCOUNT] = getGlobalBoolean(L, "onePlayerOnlinePerAccount", true);
134 boolean[AIMBOT_HOTKEY_ENABLED] = getGlobalBoolean(L, "hotkeyAimbotEnabled", true);
135 boolean[REMOVE_RUNE_CHARGES] = getGlobalBoolean(L, "removeChargesFromRunes", true);
136 boolean[REMOVE_WEAPON_AMMO] = getGlobalBoolean(L, "removeWeaponAmmunition", true);
137 boolean[REMOVE_WEAPON_CHARGES] = getGlobalBoolean(L, "removeWeaponCharges", true);
138 boolean[REMOVE_POTION_CHARGES] = getGlobalBoolean(L, "removeChargesFromPotions", true);
139 boolean[EXPERIENCE_FROM_PLAYERS] = getGlobalBoolean(L, "experienceByKillingPlayers", false);
140 boolean[FREE_PREMIUM] = getGlobalBoolean(L, "freePremium", false);
141 boolean[REPLACE_KICK_ON_LOGIN] = getGlobalBoolean(L, "replaceKickOnLogin", true);
142 boolean[ALLOW_CLONES] = getGlobalBoolean(L, "allowClones", false);
143 boolean[MARKET_PREMIUM] = getGlobalBoolean(L, "premiumToCreateMarketOffer", true);
144 boolean[EMOTE_SPELLS] = getGlobalBoolean(L, "emoteSpells", false);
145 boolean[STAMINA_SYSTEM] = getGlobalBoolean(L, "staminaSystem", true);
146 boolean[WARN_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "warnUnsafeScripts", true);
147 boolean[CONVERT_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "convertUnsafeScripts", true);
148 boolean[CLASSIC_EQUIPMENT_SLOTS] = getGlobalBoolean(L, "classicEquipmentSlots", false);
149 boolean[CLASSIC_ATTACK_SPEED] = getGlobalBoolean(L, "classicAttackSpeed", false);
150 boolean[SCRIPTS_CONSOLE_LOGS] = getGlobalBoolean(L, "showScriptsLogInConsole", true);
151 boolean[SERVER_SAVE_NOTIFY_MESSAGE] = getGlobalBoolean(L, "serverSaveNotifyMessage", true);
152 boolean[SERVER_SAVE_CLEAN_MAP] = getGlobalBoolean(L, "serverSaveCleanMap", false);
153 boolean[SERVER_SAVE_CLOSE] = getGlobalBoolean(L, "serverSaveClose", false);
154 boolean[SERVER_SAVE_SHUTDOWN] = getGlobalBoolean(L, "serverSaveShutdown", true);
155 boolean[ONLINE_OFFLINE_CHARLIST] = getGlobalBoolean(L, "showOnlineStatusInCharlist", false);
156 boolean[YELL_ALLOW_PREMIUM] = getGlobalBoolean(L, "yellAlwaysAllowPremium", false);
157 boolean[FORCE_MONSTERTYPE_LOAD] = getGlobalBoolean(L, "forceMonsterTypesOnLoad", true);
158 boolean[HOUSE_OWNED_BY_ACCOUNT] = getGlobalBoolean(L, "houseOwnedByAccount", false);
159 boolean[CLEAN_PROTECTION_ZONES] = getGlobalBoolean(L, "cleanProtectionZones", false);
160 boolean[HOUSE_DOOR_SHOW_PRICE] = getGlobalBoolean(L, "houseDoorShowPrice", true);
161 boolean[PACKET_COMPRESSION] = getGlobalBoolean(L, "packetCompression", true);
162
163 string[DEFAULT_PRIORITY] = getGlobalString(L, "defaultPriority", "high");
164 string[SERVER_NAME] = getGlobalString(L, "serverName", "");
165 string[OWNER_NAME] = getGlobalString(L, "ownerName", "");
166 string[OWNER_EMAIL] = getGlobalString(L, "ownerEmail", "");
167 string[URL] = getGlobalString(L, "url", "");
168 string[LOCATION] = getGlobalString(L, "location", "");
169 string[MOTD] = getGlobalString(L, "motd", "");
170 string[WORLD_TYPE] = getGlobalString(L, "worldType", "pvp");
171
172 integer[MAX_PLAYERS] = getGlobalNumber(L, "maxPlayers");
173 integer[PZ_LOCKED] = getGlobalNumber(L, "pzLocked", 60000);
174 integer[DEFAULT_DESPAWNRANGE] = getGlobalNumber(L, "deSpawnRange", 2);
175 integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50);
176 integer[RATE_EXPERIENCE] = getGlobalNumber(L, "rateExp", 5);
177 integer[RATE_SKILL] = getGlobalNumber(L, "rateSkill", 3);
178 integer[RATE_LOOT] = getGlobalNumber(L, "rateLoot", 2);
179 integer[RATE_MAGIC] = getGlobalNumber(L, "rateMagic", 3);
180 integer[RATE_SPAWN] = getGlobalNumber(L, "rateSpawn", 1);
181 integer[HOUSE_PRICE] = getGlobalNumber(L, "housePriceEachSQM", 1000);
182 integer[KILLS_TO_RED] = getGlobalNumber(L, "killsToRedSkull", 3);
183 integer[KILLS_TO_BLACK] = getGlobalNumber(L, "killsToBlackSkull", 6);
184 integer[ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenActions", 200);
185 integer[EX_ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenExActions", 1000);
186 integer[MAX_MESSAGEBUFFER] = getGlobalNumber(L, "maxMessageBuffer", 4);
187 integer[KICK_AFTER_MINUTES] = getGlobalNumber(L, "kickIdlePlayerAfterMinutes", 15);
188 integer[PROTECTION_LEVEL] = getGlobalNumber(L, "protectionLevel", 1);
189 integer[DEATH_LOSE_PERCENT] = getGlobalNumber(L, "deathLosePercent", -1);
190 integer[STATUSQUERY_TIMEOUT] = getGlobalNumber(L, "statusTimeout", 5000);
191 integer[FRAG_TIME] = getGlobalNumber(L, "timeToDecreaseFrags", 24 * 60 * 60);
192 integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60);
193 integer[STAIRHOP_DELAY] = getGlobalNumber(L, "stairJumpExhaustion", 2000);
194 integer[EXP_FROM_PLAYERS_LEVEL_RANGE] = getGlobalNumber(L, "expFromPlayersLevelRange", 75);
195 integer[CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES] = getGlobalNumber(L, "checkExpiredMarketOffersEachMinutes", 60);
196 integer[MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER] = getGlobalNumber(L, "maxMarketOffersAtATimePerPlayer", 100);
197 integer[MAX_PACKETS_PER_SECOND] = getGlobalNumber(L, "maxPacketsPerSecond", 25);
198 integer[SERVER_SAVE_NOTIFY_DURATION] = getGlobalNumber(L, "serverSaveNotifyDuration", 5);
199 integer[YELL_MINIMUM_LEVEL] = getGlobalNumber(L, "yellMinimumLevel", 2);
200
201 loaded = true;
202 lua_close(L);
203 return true;
204}
205
206bool ConfigManager::reload()
207{
208 bool result = load();
209 if (transformToSHA1(getString(ConfigManager::MOTD)) != g_game.getMotdHash()) {
210 g_game.incrementMotdNum();
211 }
212 return result;
213}
214
215static std::string dummyStr;
216
217const std::string& ConfigManager::getString(string_config_t what) const
218{
219 if (what >= LAST_STRING_CONFIG) {
220 std::cout << "[Warning - ConfigManager::getString] Accessing invalid index: " << what << std::endl;
221 return dummyStr;
222 }
223 return string[what];
224}
225
226int32_t ConfigManager::getNumber(integer_config_t what) const
227{
228 if (what >= LAST_INTEGER_CONFIG) {
229 std::cout << "[Warning - ConfigManager::getNumber] Accessing invalid index: " << what << std::endl;
230 return 0;
231 }
232 return integer[what];
233}
234
235bool ConfigManager::getBoolean(boolean_config_t what) const
236{
237 if (what >= LAST_BOOLEAN_CONFIG) {
238 std::cout << "[Warning - ConfigManager::getBoolean] Accessing invalid index: " << what << std::endl;
239 return false;
240 }
241 return boolean[what];
242}
243
Top