server/game/src/config.cpp

1237 lines
26 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include <sstream>
#ifndef __WIN32__
#include <ifaddrs.h>
#endif
#include "constants.h"
#include "utils.h"
#include "log.h"
#include "desc.h"
#include "desc_manager.h"
#include "item_manager.h"
#include "p2p.h"
#include "char.h"
#include "war_map.h"
#include "locale_service.h"
#include "config.h"
#include "dev_log.h"
#include "db.h"
#include "skill_power.h"
using std::string;
BYTE g_bChannel = 0;
WORD mother_port = 50080;
int passes_per_sec = 25;
WORD db_port = 0;
WORD p2p_port = 50900;
char db_addr[ADDRESS_MAX_LEN + 1];
int save_event_second_cycle = passes_per_sec * 120; // 3ºÐ
int ping_event_second_cycle = passes_per_sec * 60;
bool g_bNoMoreClient = false;
bool g_bNoRegen = false;
// TRAFFIC_PROFILER
bool g_bTrafficProfileOn = false;
DWORD g_dwTrafficProfileFlushCycle = 3600;
// END_OF_TRAFFIC_PROFILER
int test_server = 0;
int speed_server = 0;
#ifdef __AUCTION__
int auction_server = 0;
#endif
bool distribution_test_server = false;
bool china_event_server = false;
bool guild_mark_server = true;
BYTE guild_mark_min_level = 3;
bool no_wander = false;
int g_iUserLimit = 32768;
char g_szPublicIP[16] = "0";
char g_szInternalIP[16] = "0";
bool g_bSkillDisable = false;
int g_iFullUserCount = 1200;
int g_iBusyUserCount = 650;
//Canada
//int g_iFullUserCount = 600;
//int g_iBusyUserCount = 350;
//Brazil
//int g_iFullUserCount = 650;
//int g_iBusyUserCount = 450;
bool g_bEmpireWhisper = true;
BYTE g_bAuthServer = false;
bool g_bCheckClientVersion = true;
string g_stClientVersion = "1215955205";
BYTE g_bBilling = false;
string g_stAuthMasterIP;
WORD g_wAuthMasterPort = 0;
static std::set<DWORD> s_set_dwFileCRC;
static std::set<DWORD> s_set_dwProcessCRC;
string g_stHostname = "";
string g_table_postfix = "";
string g_stQuestDir = "./quest";
//string g_stQuestObjectDir = "./quest/object";
string g_stDefaultQuestObjectDir = "./quest/object";
std::set<string> g_setQuestObjectDir;
std::vector<std::string> g_stAdminPageIP;
std::string g_stAdminPagePassword = "SHOWMETHEMONEY";
string g_stBlockDate = "30000705";
extern string g_stLocale;
char teen_addr[ADDRESS_MAX_LEN + 1] = {0};
WORD teen_port = 0;
int SPEEDHACK_LIMIT_COUNT = 50;
int SPEEDHACK_LIMIT_BONUS = 80;
int g_iSyncHackLimitCount = 20; // 10 -> 20 2013 09 11 CYH
//½Ã¾ß = VIEW_RANGE + VIEW_BONUS_RANGE
//VIEW_BONUSE_RANGE : Ŭ¶óÀ̾ðÆ®¿Í ½Ã¾ß 󸮿¡¼­³Ê¹« µü ¶³¾îÁú°æ¿ì ¹®Á¦°¡ ¹ß»ýÇÒ¼öÀÖ¾î 500CMÀÇ ¿©ºÐÀ» Ç×»óÁØ´Ù.
int VIEW_RANGE = 5000;
int VIEW_BONUS_RANGE = 500;
int g_server_id = 0;
string g_strWebMallURL = "www.metin2.de";
unsigned int g_uiSpamBlockDuration = 60 * 15; // ±âº» 15ºÐ
unsigned int g_uiSpamBlockScore = 100; // ±âº» 100Á¡
unsigned int g_uiSpamReloadCycle = 60 * 10; // ±âº» 10ºÐ
bool g_bCheckMultiHack = true;
int g_iSpamBlockMaxLevel = 10;
void LoadStateUserCount();
void LoadValidCRCList();
bool LoadClientVersion();
bool g_protectNormalPlayer = false; // ¹ü¹ýÀÚ°¡ "ÆòÈ­¸ðµå" ÀÎ ÀϹÝÀ¯Àú¸¦ °ø°ÝÇÏÁö ¸øÇÔ
bool g_noticeBattleZone = false; // Á߸³Áö´ë¿¡ ÀÔÀåÇÏ¸é ¾È³»¸Þ¼¼Áö¸¦ ¾Ë·ÁÁÜ
int gPlayerMaxLevel = 99;
bool g_BlockCharCreation = false;
bool is_string_true(const char * string)
{
bool result = 0;
if (isdigit(*string))
{
str_to_number(result, string);
return result > 0 ? true : false;
}
else if (LOWER(*string) == 't')
return true;
else
return false;
}
static std::set<int> s_set_map_allows;
bool map_allow_find(int index)
{
if (g_bAuthServer)
return false;
if (s_set_map_allows.find(index) == s_set_map_allows.end())
return false;
return true;
}
void map_allow_log()
{
std::set<int>::iterator i;
for (i = s_set_map_allows.begin(); i != s_set_map_allows.end(); ++i)
sys_log(0, "MAP_ALLOW: %d", *i);
}
void map_allow_add(int index)
{
if (map_allow_find(index) == true)
{
fprintf(stdout, "!!! FATAL ERROR !!! multiple MAP_ALLOW setting!!\n");
exit(1);
}
fprintf(stdout, "MAP ALLOW %d\n", index);
s_set_map_allows.insert(index);
}
void map_allow_copy(int * pl, int size)
{
int iCount = 0;
for (auto mapId: s_set_map_allows)
{
if (iCount >= size)
break;
pl[iCount++] = mapId;
}
}
static void FN_add_adminpageIP(char *line)
{
char *last;
const char *delim = " \t\r\n";
char *v = strtok_r(line, delim, &last);
while (v)
{
g_stAdminPageIP.push_back(v);
v = strtok_r(NULL, delim, &last);
}
}
static void FN_log_adminpage()
{
itertype(g_stAdminPageIP) iter = g_stAdminPageIP.begin();
while (iter != g_stAdminPageIP.end())
{
dev_log(LOG_DEB0, "ADMIN_PAGE_IP = %s", (*iter).c_str());
++iter;
}
dev_log(LOG_DEB0, "ADMIN_PAGE_PASSWORD = %s", g_stAdminPagePassword.c_str());
}
bool GetIPInfo()
{
#ifndef __WIN32__
struct ifaddrs* ifaddrp = NULL;
if (0 != getifaddrs(&ifaddrp))
return false;
for( struct ifaddrs* ifap=ifaddrp ; NULL != ifap ; ifap = ifap->ifa_next )
{
struct sockaddr_in * sai = (struct sockaddr_in *) ifap->ifa_addr;
if (!ifap->ifa_netmask || // ignore if no netmask
sai->sin_addr.s_addr == 0 || // ignore if address is 0.0.0.0
sai->sin_addr.s_addr == 16777343) // ignore if address is 127.0.0.1
continue;
#else
WSADATA wsa_data;
char host_name[100];
HOSTENT* host_ent;
int n = 0;
if (WSAStartup(0x0101, &wsa_data)) {
return false;
}
gethostname(host_name, sizeof(host_name));
host_ent = gethostbyname(host_name);
if (host_ent == NULL) {
return false;
}
for ( ; host_ent->h_addr_list[n] != NULL; ++n) {
struct sockaddr_in addr;
struct sockaddr_in* sai = &addr;
memcpy(&sai->sin_addr.s_addr, host_ent->h_addr_list[n], host_ent->h_length);
#endif
char * netip = inet_ntoa(sai->sin_addr);
if (!strncmp(netip, "192.168", 7)) // ignore if address is starting with 192
{
strncpy(g_szInternalIP, netip, sizeof(g_szInternalIP));
#ifndef __WIN32__
fprintf(stderr, "INTERNAL_IP: %s interface %s\n", netip, ifap->ifa_name);
#else
fprintf(stderr, "INTERNAL_IP: %s\n", netip);
#endif
}
else if (!strncmp(netip, "10.", 3))
{
strncpy(g_szInternalIP, netip, sizeof(g_szInternalIP));
#ifndef __WIN32__
fprintf(stderr, "INTERNAL_IP: %s interface %s\n", netip, ifap->ifa_name);
#else
fprintf(stderr, "INTERNAL_IP: %s\n", netip);
#endif
}
else if (g_szPublicIP[0] == '0')
{
strncpy(g_szPublicIP, netip, sizeof(g_szPublicIP));
#ifndef __WIN32__
fprintf(stderr, "PUBLIC_IP: %s interface %s\n", netip, ifap->ifa_name);
#else
fprintf(stderr, "PUBLIC_IP: %s\n", netip);
#endif
}
}
#ifndef __WIN32__
freeifaddrs( ifaddrp );
#else
WSACleanup();
#endif
if (g_szPublicIP[0] != '0')
return true;
else
return false;
}
void config_init(const string& st_localeServiceName)
{
FILE *fp;
char buf[256];
char token_string[256];
char value_string[256];
// LOCALE_SERVICE
string st_configFileName;
st_configFileName.reserve(32);
st_configFileName = "CONFIG";
if (!st_localeServiceName.empty())
{
st_configFileName += ".";
st_configFileName += st_localeServiceName;
}
// END_OF_LOCALE_SERVICE
if (!(fp = fopen(st_configFileName.c_str(), "r")))
{
fprintf(stderr, "Can not open [%s]\n", st_configFileName.c_str());
exit(1);
}
if (!GetIPInfo())
{
fprintf(stderr, "Can not get public ip address\n");
exit(1);
}
char db_host[2][64], db_user[2][64], db_pwd[2][64], db_db[2][64];
// ... ¾Æ... db_port´Â ÀÌ¹Ì Àִµ¥... ³×ÀÌ¹Ö ¾îÂîÇؾßÇÔ...
int mysql_db_port[2];
for (int n = 0; n < 2; ++n)
{
*db_host[n] = '\0';
*db_user[n] = '\0';
*db_pwd[n]= '\0';
*db_db[n]= '\0';
mysql_db_port[n] = 0;
}
char log_host[64], log_user[64], log_pwd[64], log_db[64];
int log_port = 0;
*log_host = '\0';
*log_user = '\0';
*log_pwd = '\0';
*log_db = '\0';
// DB¿¡¼­ ·ÎÄÉÀÏÁ¤º¸¸¦ ¼¼ÆÃÇϱâÀ§Çؼ­´Â ´Ù¸¥ ¼¼Æ𪺸´Ù ¼±ÇàµÇ¾î¼­
// DBÁ¤º¸¸¸ Àоî¿Í ·ÎÄÉÀÏ ¼¼ÆÃÀ» ÇÑÈÄ ´Ù¸¥ ¼¼ÆÃÀ» Àû¿ë½ÃÄѾßÇÑ´Ù.
// ÀÌÀ¯´Â ·ÎÄÉÀÏ°ü·ÃµÈ ÃʱâÈ­ ·çƾÀÌ °÷°÷¿¡ Á¸ÀçÇϱ⠶§¹®.
bool isCommonSQL = false;
bool isPlayerSQL = false;
FILE* fpOnlyForDB;
if (!(fpOnlyForDB = fopen(st_configFileName.c_str(), "r")))
{
fprintf(stderr, "Can not open [%s]\n", st_configFileName.c_str());
exit(1);
}
while (fgets(buf, 256, fpOnlyForDB))
{
parse_token(buf, token_string, value_string);
TOKEN("BLOCK_LOGIN")
{
g_stBlockDate = value_string;
}
TOKEN("adminpage_ip")
{
FN_add_adminpageIP(value_string);
//g_stAdminPageIP[0] = value_string;
}
TOKEN("adminpage_ip1")
{
FN_add_adminpageIP(value_string);
//g_stAdminPageIP[0] = value_string;
}
TOKEN("adminpage_ip2")
{
FN_add_adminpageIP(value_string);
//g_stAdminPageIP[1] = value_string;
}
TOKEN("adminpage_ip3")
{
FN_add_adminpageIP(value_string);
//g_stAdminPageIP[2] = value_string;
}
TOKEN("adminpage_password")
{
g_stAdminPagePassword = value_string;
}
TOKEN("hostname")
{
g_stHostname = value_string;
fprintf(stdout, "HOSTNAME: %s\n", g_stHostname.c_str());
continue;
}
TOKEN("channel")
{
str_to_number(g_bChannel, value_string);
continue;
}
TOKEN("player_sql")
{
const char * line = two_arguments(value_string, db_host[0], sizeof(db_host[0]), db_user[0], sizeof(db_user[0]));
line = two_arguments(line, db_pwd[0], sizeof(db_pwd[0]), db_db[0], sizeof(db_db[0]));
if ('\0' != line[0])
{
char buf[256];
one_argument(line, buf, sizeof(buf));
str_to_number(mysql_db_port[0], buf);
}
if (!*db_host[0] || !*db_user[0] || !*db_pwd[0] || !*db_db[0])
{
fprintf(stderr, "PLAYER_SQL syntax: logsql <host user password db>\n");
exit(1);
}
char buf[1024];
snprintf(buf, sizeof(buf), "PLAYER_SQL: %s %s %s %s %d", db_host[0], db_user[0], db_pwd[0], db_db[0], mysql_db_port[0]);
isPlayerSQL = true;
continue;
}
TOKEN("common_sql")
{
const char * line = two_arguments(value_string, db_host[1], sizeof(db_host[1]), db_user[1], sizeof(db_user[1]));
line = two_arguments(line, db_pwd[1], sizeof(db_pwd[1]), db_db[1], sizeof(db_db[1]));
if ('\0' != line[0])
{
char buf[256];
one_argument(line, buf, sizeof(buf));
str_to_number(mysql_db_port[1], buf);
}
if (!*db_host[1] || !*db_user[1] || !*db_pwd[1] || !*db_db[1])
{
fprintf(stderr, "COMMON_SQL syntax: logsql <host user password db>\n");
exit(1);
}
char buf[1024];
snprintf(buf, sizeof(buf), "COMMON_SQL: %s %s %s %s %d", db_host[1], db_user[1], db_pwd[1], db_db[1], mysql_db_port[1]);
isCommonSQL = true;
continue;
}
TOKEN("log_sql")
{
const char * line = two_arguments(value_string, log_host, sizeof(log_host), log_user, sizeof(log_user));
line = two_arguments(line, log_pwd, sizeof(log_pwd), log_db, sizeof(log_db));
if ('\0' != line[0])
{
char buf[256];
one_argument(line, buf, sizeof(buf));
str_to_number(log_port, buf);
}
if (!*log_host || !*log_user || !*log_pwd || !*log_db)
{
fprintf(stderr, "LOG_SQL syntax: logsql <host user password db>\n");
exit(1);
}
char buf[1024];
snprintf(buf, sizeof(buf), "LOG_SQL: %s %s %s %s %d", log_host, log_user, log_pwd, log_db, log_port);
continue;
}
}
//󸮰¡ ³¡³µÀ¸´Ï ÆÄÀÏÀ» ´ÝÀÚ.
fclose(fpOnlyForDB);
// CONFIG_SQL_INFO_ERROR
if (!isCommonSQL)
{
puts("LOAD_COMMON_SQL_INFO_FAILURE:");
puts("");
puts("CONFIG:");
puts("------------------------------------------------");
puts("COMMON_SQL: HOST USER PASSWORD DATABASE");
puts("");
exit(1);
}
if (!isPlayerSQL)
{
puts("LOAD_PLAYER_SQL_INFO_FAILURE:");
puts("");
puts("CONFIG:");
puts("------------------------------------------------");
puts("PLAYER_SQL: HOST USER PASSWORD DATABASE");
puts("");
exit(1);
}
// Common DB °¡ Locale Á¤º¸¸¦ °¡Áö°í Àֱ⠶§¹®¿¡ °¡Àå ¸ÕÀú Á¢¼ÓÇØ¾ß ÇÑ´Ù.
AccountDB::instance().Connect(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1]);
if (false == AccountDB::instance().IsConnected())
{
fprintf(stderr, "cannot start server while no common sql connected\n");
exit(1);
}
fprintf(stdout, "CommonSQL connected\n");
// ·ÎÄÉÀÏ Á¤º¸¸¦ °¡Á®¿ÀÀÚ
// <°æ°í> Äõ¸®¹®¿¡ Àý´ë Á¶°Ç¹®(WHERE) ´ÞÁö ¸¶¼¼¿ä. (´Ù¸¥ Áö¿ª¿¡¼­ ¹®Á¦°¡ »ý±æ¼ö ÀÖ½À´Ï´Ù)
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "SELECT mKey, mValue FROM locale");
std::unique_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
if (pMsg->Get()->uiNumRows == 0)
{
fprintf(stderr, "COMMON_SQL: DirectQuery failed : %s\n", szQuery);
exit(1);
}
MYSQL_ROW row;
while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
{
// ·ÎÄÉÀÏ ¼¼ÆÃ
if (strcasecmp(row[0], "LOCALE") == 0)
{
if (LocaleService_Init(row[1]) == false)
{
fprintf(stderr, "COMMON_SQL: invalid locale key %s\n", row[1]);
exit(1);
}
}
}
}
// ·ÎÄÉÀÏ Á¤º¸¸¦ COMMON SQL¿¡ ¼¼ÆÃÇØÁØ´Ù.
// Âü°í·Î g_stLocale Á¤º¸´Â LocaleService_Init() ³»ºÎ¿¡¼­ ¼¼ÆõȴÙ.
fprintf(stdout, "Setting DB to locale %s\n", g_stLocale.c_str());
AccountDB::instance().SetLocale(g_stLocale);
AccountDB::instance().ConnectAsync(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1], g_stLocale.c_str());
// Player DB Á¢¼Ó
DBManager::instance().Connect(db_host[0], mysql_db_port[0], db_user[0], db_pwd[0], db_db[0]);
if (!DBManager::instance().IsConnected())
{
fprintf(stderr, "PlayerSQL.ConnectError\n");
exit(1);
}
fprintf(stdout, "PlayerSQL connected\n");
if (false == g_bAuthServer) // ÀÎÁõ ¼­¹ö°¡ ¾Æ´Ò °æ¿ì
{
// Log DB Á¢¼Ó
LogManager::instance().Connect(log_host, log_port, log_user, log_pwd, log_db);
if (!LogManager::instance().IsConnected())
{
fprintf(stderr, "LogSQL.ConnectError\n");
exit(1);
}
fprintf(stdout, "LogSQL connected\n");
LogManager::instance().BootLog(g_stHostname.c_str(), g_bChannel);
}
// SKILL_POWER_BY_LEVEL
// ½ºÆ®¸µ ºñ±³ÀÇ ¹®Á¦·Î ÀÎÇؼ­ AccountDB::instance().SetLocale(g_stLocale) ÈĺÎÅÍ ÇÑ´Ù.
// ¹°·Ð ±¹³»´Â º°·Î ¹®Á¦°¡ ¾ÈµÈ´Ù(ÇØ¿Ü°¡ ¹®Á¦)
{
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "SELECT mValue FROM locale WHERE mKey='SKILL_POWER_BY_LEVEL'");
std::unique_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
if (pMsg->Get()->uiNumRows == 0)
{
fprintf(stderr, "[SKILL_PERCENT] Query failed: %s", szQuery);
exit(1);
}
MYSQL_ROW row;
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
const char * p = row[0];
int cnt = 0;
char num[128];
int aiBaseSkillPowerByLevelTable[SKILL_MAX_LEVEL+1];
fprintf(stdout, "SKILL_POWER_BY_LEVEL %s\n", p);
while (*p != '\0' && cnt < (SKILL_MAX_LEVEL + 1))
{
p = one_argument(p, num, sizeof(num));
aiBaseSkillPowerByLevelTable[cnt++] = atoi(num);
//fprintf(stdout, "%d %d\n", cnt - 1, aiBaseSkillPowerByLevelTable[cnt - 1]);
if (*p == '\0')
{
if (cnt != (SKILL_MAX_LEVEL + 1))
{
fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
exit(1);
}
fprintf(stdout, "SKILL_POWER_BY_LEVEL: Done! (count %d)\n", cnt);
break;
}
}
// Á¾Á·º° ½ºÅ³ ¼¼ÆÃ
for (int job = 0; job < JOB_MAX_NUM * 2; ++job)
{
snprintf(szQuery, sizeof(szQuery), "SELECT mValue from locale where mKey='SKILL_POWER_BY_LEVEL_TYPE%d' ORDER BY CAST(mValue AS unsigned)", job);
std::unique_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
// ¼¼ÆÃÀÌ ¾ÈµÇ¾îÀÖÀ¸¸é ±âº»Å×À̺íÀ» »ç¿ëÇÑ´Ù.
if (pMsg->Get()->uiNumRows == 0)
{
CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiBaseSkillPowerByLevelTable);
continue;
}
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
cnt = 0;
p = row[0];
int aiSkillTable[SKILL_MAX_LEVEL + 1];
fprintf(stdout, "SKILL_POWER_BY_JOB %d %s\n", job, p);
while (*p != '\0' && cnt < (SKILL_MAX_LEVEL + 1))
{
p = one_argument(p, num, sizeof(num));
aiSkillTable[cnt++] = atoi(num);
//fprintf(stdout, "%d %d\n", cnt - 1, aiBaseSkillPowerByLevelTable[cnt - 1]);
if (*p == '\0')
{
if (cnt != (SKILL_MAX_LEVEL + 1))
{
fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
exit(1);
}
fprintf(stdout, "SKILL_POWER_BY_JOB: Done! (job: %d count: %d)\n", job, cnt);
break;
}
}
CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiSkillTable);
}
}
// END_SKILL_POWER_BY_LEVEL
// LOG_KEEP_DAYS_EXTEND
log_set_expiration_days(2);
// END_OF_LOG_KEEP_DAYS_EXTEND
while (fgets(buf, 256, fp))
{
parse_token(buf, token_string, value_string);
TOKEN("empire_whisper")
{
bool b_value = 0;
str_to_number(b_value, value_string);
g_bEmpireWhisper = !!b_value;
continue;
}
TOKEN("mark_server")
{
guild_mark_server = is_string_true(value_string);
continue;
}
TOKEN("mark_min_level")
{
str_to_number(guild_mark_min_level, value_string);
guild_mark_min_level = std::clamp<BYTE>(guild_mark_min_level, 0, GUILD_MAX_LEVEL);
continue;
}
TOKEN("port")
{
str_to_number(mother_port, value_string);
continue;
}
TOKEN("log_keep_days")
{
int i = 0;
str_to_number(i, value_string);
log_set_expiration_days(std::clamp(i, 1, 90));
continue;
}
TOKEN("passes_per_sec")
{
str_to_number(passes_per_sec, value_string);
continue;
}
TOKEN("p2p_port")
{
str_to_number(p2p_port, value_string);
continue;
}
TOKEN("db_port")
{
str_to_number(db_port, value_string);
continue;
}
TOKEN("db_addr")
{
strncpy(db_addr, value_string, sizeof(db_addr));
for (int n =0; n < ADDRESS_MAX_LEN; ++n)
{
if (db_addr[n] == ' ')
db_addr[n] = '\0';
}
continue;
}
TOKEN("save_event_second_cycle")
{
int cycle = 0;
str_to_number(cycle, value_string);
save_event_second_cycle = cycle * passes_per_sec;
continue;
}
TOKEN("ping_event_second_cycle")
{
int cycle = 0;
str_to_number(cycle, value_string);
ping_event_second_cycle = cycle * passes_per_sec;
continue;
}
TOKEN("table_postfix")
{
g_table_postfix = value_string;
continue;
}
TOKEN("test_server")
{
printf("-----------------------------------------------\n");
printf("TEST_SERVER\n");
printf("-----------------------------------------------\n");
str_to_number(test_server, value_string);
continue;
}
TOKEN("speed_server")
{
printf("-----------------------------------------------\n");
printf("SPEED_SERVER\n");
printf("-----------------------------------------------\n");
str_to_number(speed_server, value_string);
continue;
}
#ifdef __AUCTION__
TOKEN("auction_server")
{
printf("-----------------------------------------------\n");
printf("AUCTION_SERVER\n");
printf("-----------------------------------------------\n");
str_to_number(auction_server, value_string);
continue;
}
#endif
TOKEN("distribution_test_server")
{
str_to_number(distribution_test_server, value_string);
continue;
}
TOKEN("china_event_server")
{
str_to_number(china_event_server, value_string);
continue;
}
TOKEN("shutdowned")
{
g_bNoMoreClient = true;
continue;
}
TOKEN("no_regen")
{
g_bNoRegen = true;
continue;
}
TOKEN("traffic_profile")
{
g_bTrafficProfileOn = true;
continue;
}
TOKEN("map_allow")
{
char * p = value_string;
string stNum;
for (; *p; p++)
{
if (isspace(*p))
{
if (stNum.length())
{
int index = 0;
str_to_number(index, stNum.c_str());
map_allow_add(index);
stNum.clear();
}
}
else
stNum += *p;
}
if (stNum.length())
{
int index = 0;
str_to_number(index, stNum.c_str());
map_allow_add(index);
}
continue;
}
TOKEN("no_wander")
{
no_wander = true;
continue;
}
TOKEN("user_limit")
{
str_to_number(g_iUserLimit, value_string);
continue;
}
TOKEN("skill_disable")
{
str_to_number(g_bSkillDisable, value_string);
continue;
}
TOKEN("auth_server")
{
char szIP[32];
char szPort[32];
two_arguments(value_string, szIP, sizeof(szIP), szPort, sizeof(szPort));
if (!*szIP || (!*szPort && strcasecmp(szIP, "master")))
{
fprintf(stderr, "AUTH_SERVER: syntax error: <ip|master> <port>\n");
exit(1);
}
g_bAuthServer = true;
if (!strcasecmp(szIP, "master"))
fprintf(stdout, "AUTH_SERVER: I am the master\n");
else
{
g_stAuthMasterIP = szIP;
str_to_number(g_wAuthMasterPort, szPort);
fprintf(stdout, "AUTH_SERVER: master %s %u\n", g_stAuthMasterIP.c_str(), g_wAuthMasterPort);
}
continue;
}
TOKEN("billing")
{
g_bBilling = true;
}
TOKEN("quest_dir")
{
sys_log(0, "QUEST_DIR SETTING : %s", value_string);
g_stQuestDir = value_string;
}
TOKEN("quest_object_dir")
{
//g_stQuestObjectDir = value_string;
std::istringstream is(value_string);
sys_log(0, "QUEST_OBJECT_DIR SETTING : %s", value_string);
string dir;
while (!is.eof())
{
is >> dir;
if (is.fail())
break;
g_setQuestObjectDir.insert(dir);
sys_log(0, "QUEST_OBJECT_DIR INSERT : %s", dir .c_str());
}
}
TOKEN("teen_addr")
{
strncpy(teen_addr, value_string, sizeof(teen_addr));
for (int n =0; n < ADDRESS_MAX_LEN; ++n)
{
if (teen_addr[n] == ' ')
teen_addr[n] = '\0';
}
continue;
}
TOKEN("teen_port")
{
str_to_number(teen_port, value_string);
}
TOKEN("synchack_limit_count")
{
str_to_number(g_iSyncHackLimitCount, value_string);
}
TOKEN("speedhack_limit_count")
{
str_to_number(SPEEDHACK_LIMIT_COUNT, value_string);
}
TOKEN("speedhack_limit_bonus")
{
str_to_number(SPEEDHACK_LIMIT_BONUS, value_string);
}
TOKEN("server_id")
{
str_to_number(g_server_id, value_string);
}
TOKEN("mall_url")
{
g_strWebMallURL = value_string;
}
TOKEN("bind_ip")
{
strncpy(g_szPublicIP, value_string, sizeof(g_szPublicIP));
}
TOKEN("view_range")
{
str_to_number(VIEW_RANGE, value_string);
}
TOKEN("spam_block_duration")
{
str_to_number(g_uiSpamBlockDuration, value_string);
}
TOKEN("spam_block_score")
{
str_to_number(g_uiSpamBlockScore, value_string);
g_uiSpamBlockScore = std::max<int>(1, g_uiSpamBlockScore);
}
TOKEN("spam_block_reload_cycle")
{
str_to_number(g_uiSpamReloadCycle, value_string);
g_uiSpamReloadCycle = std::max<int>(60, g_uiSpamReloadCycle); // ÃÖ¼Ò 1ºÐ
}
TOKEN("check_multihack")
{
str_to_number(g_bCheckMultiHack, value_string);
}
TOKEN("spam_block_max_level")
{
str_to_number(g_iSpamBlockMaxLevel, value_string);
}
TOKEN("protect_normal_player")
{
str_to_number(g_protectNormalPlayer, value_string);
}
TOKEN("notice_battle_zone")
{
str_to_number(g_noticeBattleZone, value_string);
}
TOKEN("pk_protect_level")
{
str_to_number(PK_PROTECT_LEVEL, value_string);
fprintf(stderr, "PK_PROTECT_LEVEL: %d", PK_PROTECT_LEVEL);
}
TOKEN("max_level")
{
str_to_number(gPlayerMaxLevel, value_string);
gPlayerMaxLevel = std::clamp<int>(gPlayerMaxLevel, 1, PLAYER_MAX_LEVEL_CONST);
fprintf(stderr, "PLAYER_MAX_LEVEL: %d\n", gPlayerMaxLevel);
}
TOKEN("block_char_creation")
{
int tmp = 0;
str_to_number(tmp, value_string);
if (0 == tmp)
g_BlockCharCreation = false;
else
g_BlockCharCreation = true;
continue;
}
}
if (g_setQuestObjectDir.empty())
g_setQuestObjectDir.insert(g_stDefaultQuestObjectDir);
if (0 == db_port)
{
fprintf(stderr, "DB_PORT not configured\n");
exit(1);
}
if (0 == g_bChannel)
{
fprintf(stderr, "CHANNEL not configured\n");
exit(1);
}
if (g_stHostname.empty())
{
fprintf(stderr, "HOSTNAME must be configured.\n");
exit(1);
}
// LOCALE_SERVICE
LocaleService_LoadLocaleStringFile();
LocaleService_TransferDefaultSetting();
LocaleService_LoadEmpireTextConvertTables();
// END_OF_LOCALE_SERVICE
fclose(fp);
if ((fp = fopen("CMD", "r")))
{
while (fgets(buf, 256, fp))
{
char cmd[32], levelname[32];
int level;
two_arguments(buf, cmd, sizeof(cmd), levelname, sizeof(levelname));
if (!*cmd || !*levelname)
{
fprintf(stderr, "CMD syntax error: <cmd> <DISABLE | LOW_WIZARD | WIZARD | HIGH_WIZARD | GOD>\n");
exit(1);
}
if (!strcasecmp(levelname, "LOW_WIZARD"))
level = GM_LOW_WIZARD;
else if (!strcasecmp(levelname, "WIZARD"))
level = GM_WIZARD;
else if (!strcasecmp(levelname, "HIGH_WIZARD"))
level = GM_HIGH_WIZARD;
else if (!strcasecmp(levelname, "GOD"))
level = GM_GOD;
else if (!strcasecmp(levelname, "IMPLEMENTOR"))
level = GM_IMPLEMENTOR;
else if (!strcasecmp(levelname, "DISABLE"))
level = GM_IMPLEMENTOR + 1;
else
{
fprintf(stderr, "CMD syntax error: <cmd> <DISABLE | LOW_WIZARD | WIZARD | HIGH_WIZARD | GOD>\n");
exit(1);
}
interpreter_set_privilege(cmd, level);
}
fclose(fp);
}
LoadValidCRCList();
LoadStateUserCount();
CWarMapManager::instance().LoadWarMapInfo(NULL);
FN_log_adminpage();
}
const char* get_table_postfix()
{
return g_table_postfix.c_str();
}
void LoadValidCRCList()
{
s_set_dwProcessCRC.clear();
s_set_dwFileCRC.clear();
FILE * fp;
char buf[256];
if ((fp = fopen("CRC", "r")))
{
while (fgets(buf, 256, fp))
{
if (!*buf)
continue;
DWORD dwValidClientProcessCRC;
DWORD dwValidClientFileCRC;
sscanf(buf, " %u %u ", &dwValidClientProcessCRC, &dwValidClientFileCRC);
s_set_dwProcessCRC.insert(dwValidClientProcessCRC);
s_set_dwFileCRC.insert(dwValidClientFileCRC);
fprintf(stderr, "CLIENT_CRC: %u %u\n", dwValidClientProcessCRC, dwValidClientFileCRC);
}
fclose(fp);
}
}
bool LoadClientVersion()
{
FILE * fp = fopen("VERSION", "r");
if (!fp)
return false;
char buf[256];
fgets(buf, 256, fp);
char * p = strchr(buf, '\n');
if (p) *p = '\0';
fprintf(stderr, "VERSION: \"%s\"\n", buf);
g_stClientVersion = buf;
fclose(fp);
return true;
}
void CheckClientVersion()
{
if (LC_IsEurope())
{
g_bCheckClientVersion = true;
}
else
{
g_bCheckClientVersion = false;
}
const DESC_MANAGER::DESC_SET & set = DESC_MANAGER::instance().GetClientSet();
DESC_MANAGER::DESC_SET::const_iterator it = set.begin();
while (it != set.end())
{
LPDESC d = *(it++);
if (!d->GetCharacter())
continue;
int version = atoi(g_stClientVersion.c_str());
int date = atoi(d->GetClientVersion() );
//if (0 != g_stClientVersion.compare(d->GetClientVersion()) )
if (version > date)
{
d->GetCharacter()->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("Ŭ¶óÀ̾ðÆ® ¹öÀüÀÌ Æ²·Á ·Î±×¾Æ¿ô µË´Ï´Ù. Á¤»óÀûÀ¸·Î ÆÐÄ¡ ÈÄ Á¢¼ÓÇϼ¼¿ä."));
d->DelayedDisconnect(10);
}
}
}
void LoadStateUserCount()
{
FILE * fp = fopen("state_user_count", "r");
if (!fp)
return;
if (!LC_IsHongKong())
fscanf(fp, " %d %d ", &g_iFullUserCount, &g_iBusyUserCount);
fclose(fp);
}
bool IsValidProcessCRC(DWORD dwCRC)
{
return s_set_dwProcessCRC.find(dwCRC) != s_set_dwProcessCRC.end();
}
bool IsValidFileCRC(DWORD dwCRC)
{
return s_set_dwFileCRC.find(dwCRC) != s_set_dwFileCRC.end();
}