Advertisement
Guest User

config.cpp

a guest
Jul 18th, 2019
35
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 30.61 KB | None
  1. #include "stdafx.h"
  2. #include <sstream>
  3. #ifndef __WIN32__
  4. #include <ifaddrs.h>
  5. #endif
  6.  
  7. #include "constants.h"
  8. #include "utils.h"
  9. #include "log.h"
  10. #include "desc.h"
  11. #include "desc_manager.h"
  12. #include "item_manager.h"
  13. #include "p2p.h"
  14. #include "char.h"
  15. #include "ip_ban.h"
  16. #include "war_map.h"
  17. #include "locale_service.h"
  18. #include "config.h"
  19. #include "dev_log.h"
  20. #include "db.h"
  21. #include "skill_power.h"
  22.  
  23. using std::string;
  24.  
  25. BYTE    g_bChannel = 0;
  26. WORD    mother_port = 50080;
  27. int     passes_per_sec = 25;
  28. WORD    db_port = 0;
  29. WORD    p2p_port = 50900;
  30. char    db_addr[ADDRESS_MAX_LEN + 1];
  31. int     save_event_second_cycle = passes_per_sec * 120; // 3분
  32. int     ping_event_second_cycle = passes_per_sec * 60;
  33. bool    g_bNoMoreClient = false;
  34. bool    g_bNoRegen = false;
  35. bool    g_bNoPasspod = false;
  36. bool    g_bEmpireShopPriceTrippleDisable = false;
  37. bool    g_bShoutAddonEnable = false;
  38. bool    g_bGlobalShoutEnable = false;
  39. bool    g_bDisablePrismNeed = false;
  40. bool    g_bDisableEmotionMask = false;
  41. bool    g_bDisableItemBonusChangeTime = false;
  42. bool    g_bAllMountAttack = false;
  43. BYTE    g_bItemCountLimit = 200;
  44.  
  45. // TRAFFIC_PROFILER
  46. bool        g_bTrafficProfileOn = false;
  47. DWORD       g_dwTrafficProfileFlushCycle = 3600;
  48. // END_OF_TRAFFIC_PROFILER
  49.  
  50. int         test_server = 0;
  51. int         speed_server = 0;
  52. #ifdef __AUCTION__
  53. int         auction_server = 0;
  54. #endif
  55. bool        distribution_test_server = false;
  56. bool        china_event_server = false;
  57. bool        guild_mark_server = true;
  58. BYTE        guild_mark_min_level = 3;
  59. bool        no_wander = false;
  60. int         g_iUserLimit = 32768;
  61.  
  62. char        g_szPublicIP[16] = "0";
  63. char        g_szInternalIP[16] = "0";
  64. #ifdef FIX_LOGIN
  65. char        g_szExternPublicIP[16] = "0";
  66. #endif
  67. bool        g_bSkillDisable = false;
  68. int         g_iFullUserCount = 1200;
  69. int         g_iBusyUserCount = 650;
  70. //Canada
  71. //int           g_iFullUserCount = 600;
  72. //int           g_iBusyUserCount = 350;
  73. //Brazil
  74. //int           g_iFullUserCount = 650;
  75. //int           g_iBusyUserCount = 450;
  76. bool        g_bEmpireWhisper = true;
  77. BYTE        g_bAuthServer = false;
  78.  
  79. bool        g_bCheckClientVersion = true;
  80. string  g_stClientVersion = "1215955205";
  81.  
  82. BYTE        g_bBilling = false;
  83.  
  84. string  g_stAuthMasterIP;
  85. WORD        g_wAuthMasterPort = 0;
  86.  
  87. static std::set<DWORD> s_set_dwFileCRC;
  88. static std::set<DWORD> s_set_dwProcessCRC;
  89.  
  90. string g_stHostname = "";
  91. string g_table_postfix = "";
  92.  
  93. string g_stQuestDir = "./quest";
  94. //string g_stQuestObjectDir = "./quest/object";
  95. string g_stDefaultQuestObjectDir = "./quest/object";
  96. std::set<string> g_setQuestObjectDir;
  97.  
  98. std::vector<std::string>    g_stAdminPageIP;
  99. std::string g_stAdminPagePassword = "DasKr@SSeP@sswort";
  100.  
  101. string g_stBlockDate = "30000705";
  102.  
  103. extern string g_stLocale;
  104.  
  105. char    teen_addr[ADDRESS_MAX_LEN + 1] = {0};
  106. WORD    teen_port   = 0;
  107.  
  108. int SPEEDHACK_LIMIT_COUNT   = 50;
  109. int SPEEDHACK_LIMIT_BONUS   = 80;
  110. int g_iSyncHackLimitCount = 10;
  111.  
  112. //시야 = VIEW_RANGE + VIEW_BONUS_RANGE
  113. //VIEW_BONUSE_RANGE : 클라이언트와 시야 처리에서너무 딱 떨어질경우 문제가 발생할수있어 500CM의 여분을 항상준다.
  114. int VIEW_RANGE = 5000;
  115. int VIEW_BONUS_RANGE = 500;
  116.  
  117. int g_server_id = 0;
  118. string g_strWebMallURL = "www.metin2.de";
  119.  
  120. unsigned int g_uiSpamBlockDuration = 60 * 15; // 기본 15분
  121. unsigned int g_uiSpamBlockScore = 100; // 기본 100점
  122. unsigned int g_uiSpamReloadCycle = 60 * 10; // 기본 10분
  123.  
  124. bool        g_bCheckMultiHack = true;
  125.  
  126. int         g_iSpamBlockMaxLevel = 10;
  127.  
  128. void        LoadStateUserCount();
  129. void        LoadValidCRCList();
  130. bool        LoadClientVersion();
  131. bool            g_protectNormalPlayer   = false;        // 범법자가 "평화모드" 인 일반유저를 공격하지 못함
  132. bool            g_noticeBattleZone      = false;        // 중립지대에 입장하면 안내메세지를 알려줌
  133.  
  134. bool        isHackShieldEnable = false;
  135. int         HackShield_FirstCheckWaitTime = passes_per_sec * 30;
  136. int         HackShield_CheckCycleTime = passes_per_sec * 180;
  137.  
  138. bool        bXTrapEnabled = false;
  139.  
  140. int gPlayerMaxLevel = 99;
  141. int gShutdownAge = 0;
  142. int gShutdownEnable = 0;
  143.  
  144. /*
  145.  * NOTE : 핵 체크 On/Off. CheckIn할때 false로 수정했으면 반드시 확인하고 고쳐놓을것!
  146.  * 이걸로 생길수있는 똥은 책임안짐 ~ ity ~
  147.  */
  148. bool gHackCheckEnable = false;
  149.  
  150. bool g_BlockCharCreation = false;
  151.  
  152.  
  153. //OPENID
  154. int     openid_server = 0;
  155. char    openid_host[256];
  156. char    openid_uri[256];
  157.  
  158. bool is_string_true(const char * string)
  159. {
  160.     bool    result = 0;
  161.     if (isnhdigit(*string))
  162.     {
  163.         str_to_number(result, string);
  164.         return result > 0 ? true : false;
  165.     }
  166.     else if (LOWER(*string) == 't')
  167.         return true;
  168.     else
  169.         return false;
  170. }
  171.  
  172. static std::set<int> s_set_map_allows;
  173.  
  174. bool map_allow_find(int index)
  175. {
  176.     if (g_bAuthServer)
  177.         return false;
  178.  
  179.     if (s_set_map_allows.find(index) == s_set_map_allows.end())
  180.         return false;
  181.  
  182.     return true;
  183. }
  184.  
  185. void map_allow_log()
  186. {
  187.     std::set<int>::iterator i;
  188.  
  189.     for (i = s_set_map_allows.begin(); i != s_set_map_allows.end(); ++i)
  190.         sys_log(0, "MAP_ALLOW: %d", *i);
  191. }
  192.  
  193. void map_allow_add(int index)
  194. {
  195.     if (map_allow_find(index) == true)
  196.     {
  197.         fprintf(stdout, "!!! FATAL ERROR !!! multiple MAP_ALLOW setting!!\n");
  198.         exit(1);
  199.     }
  200.  
  201.     fprintf(stdout, "MAP ALLOW %d\n", index);
  202.     s_set_map_allows.insert(index);
  203. }
  204.  
  205. void map_allow_copy(long * pl, int size)
  206. {
  207.     int iCount = 0;
  208.     std::set<int>::iterator it = s_set_map_allows.begin();
  209.  
  210.     while (it != s_set_map_allows.end())
  211.     {
  212.         int i = *(it++);
  213.         *(pl++) = i;
  214.  
  215.         if (++iCount > size)
  216.             break;
  217.     }
  218. }
  219.  
  220. static void FN_add_adminpageIP(char *line)
  221. {
  222.     char    *last;
  223.     const char *delim = " \t\r\n";
  224.     char *v = strtok_r(line, delim, &last);
  225.  
  226.     while (v)
  227.     {
  228.         g_stAdminPageIP.push_back(v);
  229.         v = strtok_r(NULL, delim, &last);
  230.     }
  231. }
  232.  
  233. static void FN_log_adminpage()
  234. {
  235.     itertype(g_stAdminPageIP) iter = g_stAdminPageIP.begin();
  236.  
  237.     while (iter != g_stAdminPageIP.end())
  238.     {
  239.         dev_log(LOG_DEB0, "ADMIN_PAGE_IP = %s", (*iter).c_str());
  240.         ++iter;
  241.     }
  242.  
  243.     dev_log(LOG_DEB0, "ADMIN_PAGE_PASSWORD = %s", g_stAdminPagePassword.c_str());
  244. }
  245.  
  246.  
  247. bool GetIPInfo()
  248. {
  249.     struct ifaddrs* ifaddrp = NULL;
  250.  
  251.     if (0 != getifaddrs(&ifaddrp))
  252.         return false;
  253.  
  254.     for( struct ifaddrs* ifap=ifaddrp ; NULL != ifap ; ifap = ifap->ifa_next )
  255.     {
  256.         struct sockaddr_in * sai = (struct sockaddr_in *) ifap->ifa_addr;
  257.  
  258.         if (!ifap->ifa_netmask ||  // ignore if no netmask
  259.                 sai->sin_addr.s_addr == 0 || // ignore if address is 0.0.0.0
  260.                 sai->sin_addr.s_addr == 16777343) // ignore if address is 127.0.0.1
  261.             continue;
  262.  
  263.         char * netip = inet_ntoa(sai->sin_addr);
  264.  
  265.         if (g_szPublicIP[0] == '0')
  266.         {
  267.             strlcpy(g_szPublicIP, netip, sizeof(g_szPublicIP));
  268.             fprintf(stderr, "PUBLIC_IP: %s interface %s\n", netip, ifap->ifa_name);
  269.         }
  270.        
  271.     #ifdef FIX_LOGIN
  272.         FILE *fp;
  273.         fp = popen("/usr/local/bin/curl ipinfo.io/ip", "r");
  274.         fgets(g_szExternPublicIP, sizeof(g_szExternPublicIP), fp);
  275.         pclose(fp);
  276.         sys_log(0, "EXTERN_NAT_IP : %s for nat fix. \n", g_szExternPublicIP);
  277.     #endif
  278.     }
  279.  
  280.     freeifaddrs( ifaddrp );
  281.  
  282.     if (g_szPublicIP[0] != '0')
  283.         return true;
  284.     else
  285.         return false;
  286. }
  287.  
  288. void config_init(const string& st_localeServiceName)
  289. {
  290.     FILE    *fp;
  291.  
  292.     char    buf[256];
  293.     char    token_string[256];
  294.     char    value_string[256];
  295.  
  296.     // LOCALE_SERVICE
  297.     string  st_configFileName;
  298.  
  299.     st_configFileName.reserve(32);
  300.     st_configFileName = "CONFIG";
  301.  
  302.     if (!st_localeServiceName.empty())
  303.     {
  304.         st_configFileName += ".";
  305.         st_configFileName += st_localeServiceName;
  306.     }
  307.     // END_OF_LOCALE_SERVICE
  308.  
  309.     if (!(fp = fopen(st_configFileName.c_str(), "r")))
  310.     {
  311.         fprintf(stderr, "Can not open [%s]\n", st_configFileName.c_str());
  312.         exit(1);
  313.     }
  314.  
  315.     // public ip가 없어도 BIND_IP하면 게임 돌아가는데에는 아무런 지장이 없기 때문에
  316.     // 주석처리 함.
  317.     if (!GetIPInfo())
  318.     {
  319.     //  fprintf(stderr, "Can not get public ip address\n");
  320.     //  exit(1);
  321.     }
  322.  
  323.     char db_host[2][64], db_user[2][64], db_pwd[2][64], db_db[2][64];
  324.     // ... 아... db_port는 이미 있는데... 네이밍 어찌해야함...
  325.     int mysql_db_port[2];
  326.  
  327.     for (int n = 0; n < 2; ++n)
  328.     {
  329.         *db_host[n] = '\0';
  330.         *db_user[n] = '\0';
  331.         *db_pwd[n]= '\0';
  332.         *db_db[n]= '\0';
  333.         mysql_db_port[n] = 0;
  334.     }
  335.  
  336.     char log_host[64], log_user[64], log_pwd[64], log_db[64];
  337.     int log_port = 0;
  338.  
  339.     *log_host = '\0';
  340.     *log_user = '\0';
  341.     *log_pwd = '\0';
  342.     *log_db = '\0';
  343.  
  344.  
  345.     // DB에서 로케일정보를 세팅하기위해서는 다른 세팅값보다 선행되어서
  346.     // DB정보만 읽어와 로케일 세팅을 한후 다른 세팅을 적용시켜야한다.
  347.     // 이유는 로케일관련된 초기화 루틴이 곳곳에 존재하기 때문.
  348.  
  349.     bool isCommonSQL = false;  
  350.     bool isPlayerSQL = false;
  351.  
  352.     FILE* fpOnlyForDB;
  353.  
  354.     if (!(fpOnlyForDB = fopen(st_configFileName.c_str(), "r")))
  355.     {
  356.         fprintf(stderr, "Can not open [%s]\n", st_configFileName.c_str());
  357.         exit(1);
  358.     }
  359.  
  360.     while (fgets(buf, 256, fpOnlyForDB))
  361.     {
  362.         parse_token(buf, token_string, value_string);
  363.  
  364.         TOKEN("BLOCK_LOGIN")
  365.         {
  366.             g_stBlockDate = value_string;
  367.         }
  368.  
  369.         TOKEN("adminpage_ip")
  370.         {
  371.             FN_add_adminpageIP(value_string);
  372.             //g_stAdminPageIP[0] = value_string;
  373.         }
  374.  
  375.         TOKEN("adminpage_ip1")
  376.         {
  377.             FN_add_adminpageIP(value_string);
  378.             //g_stAdminPageIP[0] = value_string;
  379.         }
  380.  
  381.         TOKEN("adminpage_ip2")
  382.         {
  383.             FN_add_adminpageIP(value_string);
  384.             //g_stAdminPageIP[1] = value_string;
  385.         }
  386.  
  387.         TOKEN("adminpage_ip3")
  388.         {
  389.             FN_add_adminpageIP(value_string);
  390.             //g_stAdminPageIP[2] = value_string;
  391.         }
  392.  
  393.         TOKEN("adminpage_password")
  394.         {
  395.             g_stAdminPagePassword = value_string;
  396.         }
  397.  
  398.         TOKEN("hostname")
  399.         {
  400.             g_stHostname = value_string;
  401.             fprintf(stdout, "HOSTNAME: %s\n", g_stHostname.c_str());
  402.             continue;
  403.         }
  404.  
  405.         TOKEN("channel")
  406.         {
  407.             str_to_number(g_bChannel, value_string);
  408.             continue;
  409.         }
  410.  
  411.         TOKEN("player_sql")
  412.         {
  413.             const char * line = two_arguments(value_string, db_host[0], sizeof(db_host[0]), db_user[0], sizeof(db_user[0]));
  414.             line = two_arguments(line, db_pwd[0], sizeof(db_pwd[0]), db_db[0], sizeof(db_db[0]));
  415.  
  416.             if (NULL != line[0])
  417.             {
  418.                 char buf[256];
  419.                 one_argument(line, buf, sizeof(buf));
  420.                 str_to_number(mysql_db_port[0], buf);
  421.             }
  422.  
  423.             if (!*db_host[0] || !*db_user[0] || !*db_pwd[0] || !*db_db[0])
  424.             {
  425.                 fprintf(stderr, "PLAYER_SQL syntax: logsql <host user password db>\n");
  426.                 exit(1);
  427.             }
  428.  
  429.             char buf[1024];
  430.             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]);
  431.             isPlayerSQL = true;
  432.             continue;
  433.         }
  434.  
  435.         TOKEN("common_sql")
  436.         {
  437.             const char * line = two_arguments(value_string, db_host[1], sizeof(db_host[1]), db_user[1], sizeof(db_user[1]));
  438.             line = two_arguments(line, db_pwd[1], sizeof(db_pwd[1]), db_db[1], sizeof(db_db[1]));
  439.  
  440.             if (NULL != line[0])
  441.             {
  442.                 char buf[256];
  443.                 one_argument(line, buf, sizeof(buf));
  444.                 str_to_number(mysql_db_port[1], buf);
  445.             }
  446.  
  447.             if (!*db_host[1] || !*db_user[1] || !*db_pwd[1] || !*db_db[1])
  448.             {
  449.                 fprintf(stderr, "COMMON_SQL syntax: logsql <host user password db>\n");
  450.                 exit(1);
  451.             }
  452.  
  453.             char buf[1024];
  454.             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]);
  455.             isCommonSQL = true;
  456.             continue;
  457.         }
  458.  
  459.         TOKEN("log_sql")
  460.         {
  461.             const char * line = two_arguments(value_string, log_host, sizeof(log_host), log_user, sizeof(log_user));
  462.             line = two_arguments(line, log_pwd, sizeof(log_pwd), log_db, sizeof(log_db));
  463.  
  464.             if (NULL != line[0])
  465.             {
  466.                 char buf[256];
  467.                 one_argument(line, buf, sizeof(buf));
  468.                 str_to_number(log_port, buf);
  469.             }
  470.  
  471.             if (!*log_host || !*log_user || !*log_pwd || !*log_db)
  472.             {
  473.                 fprintf(stderr, "LOG_SQL syntax: logsql <host user password db>\n");
  474.                 exit(1);
  475.             }
  476.  
  477.             char buf[1024];
  478.             snprintf(buf, sizeof(buf), "LOG_SQL: %s %s %s %s %d", log_host, log_user, log_pwd, log_db, log_port);
  479.             continue;
  480.         }
  481.  
  482.        
  483.         //OPENID       
  484.         TOKEN("WEB_AUTH")
  485.         {
  486.             const char * line = two_arguments(value_string, openid_host, sizeof(openid_host), openid_uri, sizeof(openid_uri));
  487.  
  488.             if (!*openid_host || !*openid_uri)
  489.             {
  490.                 fprintf(stderr, "WEB_AUTH syntax error (ex: WEB_AUTH <host(metin2.co.kr) uri(/kyw/gameauth.php)>\n");
  491.                 exit(1);
  492.             }
  493.  
  494.             char buf[1024];
  495.             openid_server = 1;
  496.             snprintf(buf, sizeof(buf), "WEB_AUTH: %s %s", openid_host, openid_uri);
  497.             continue;
  498.         }
  499.     }
  500.  
  501.     //처리가 끝났으니 파일을 닫자.
  502.     fclose(fpOnlyForDB);
  503.  
  504.     // CONFIG_SQL_INFO_ERROR
  505.     if (!isCommonSQL)
  506.     {
  507.         puts("LOAD_COMMON_SQL_INFO_FAILURE:");
  508.         puts("");
  509.         puts("CONFIG:");
  510.         puts("------------------------------------------------");
  511.         puts("COMMON_SQL: HOST USER PASSWORD DATABASE");
  512.         puts("");
  513.         exit(1);
  514.     }
  515.  
  516.     if (!isPlayerSQL)
  517.     {
  518.         puts("LOAD_PLAYER_SQL_INFO_FAILURE:");
  519.         puts("");
  520.         puts("CONFIG:");
  521.         puts("------------------------------------------------");
  522.         puts("PLAYER_SQL: HOST USER PASSWORD DATABASE");
  523.         puts("");
  524.         exit(1);
  525.     }
  526.  
  527.     // Common DB 가 Locale 정보를 가지고 있기 때문에 가장 먼저 접속해야 한다.
  528.     AccountDB::instance().Connect(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1]);
  529.  
  530.     if (false == AccountDB::instance().IsConnected())
  531.     {
  532.         fprintf(stderr, "cannot start server while no common sql connected\n");
  533.         exit(1);
  534.     }
  535.  
  536.     fprintf(stdout, "CommonSQL connected\n");
  537.  
  538.     // 로케일 정보를 가져오자
  539.     // <경고> 쿼리문에 절대 조건문(WHERE) 달지 마세요. (다른 지역에서 문제가 생길수 있습니다)
  540.     {
  541.         char szQuery[512];
  542.         snprintf(szQuery, sizeof(szQuery), "SELECT mKey, mValue FROM locale");
  543.  
  544.         std::auto_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
  545.  
  546.         if (pMsg->Get()->uiNumRows == 0)
  547.         {
  548.             fprintf(stderr, "COMMON_SQL: DirectQuery failed : %s\n", szQuery);
  549.             exit(1);
  550.         }
  551.  
  552.         MYSQL_ROW row;
  553.  
  554.         while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
  555.         {
  556.             // 로케일 세팅
  557.             if (strcasecmp(row[0], "LOCALE") == 0)
  558.             {
  559.                 if (LocaleService_Init(row[1]) == false)
  560.                 {
  561.                     fprintf(stderr, "COMMON_SQL: invalid locale key %s\n", row[1]);
  562.                     exit(1);
  563.                 }
  564.             }
  565.         }
  566.     }
  567.  
  568.     // 로케일 정보를 COMMON SQL에 세팅해준다.
  569.     // 참고로 g_stLocale 정보는 LocaleService_Init() 내부에서 세팅된다.
  570.     fprintf(stdout, "Setting DB to locale %s\n", g_stLocale.c_str());
  571.  
  572.     AccountDB::instance().SetLocale(g_stLocale);
  573.  
  574.     AccountDB::instance().ConnectAsync(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1], g_stLocale.c_str());
  575.  
  576.     // Player DB 접속
  577.     DBManager::instance().Connect(db_host[0], mysql_db_port[0], db_user[0], db_pwd[0], db_db[0]);
  578.  
  579.     if (!DBManager::instance().IsConnected())
  580.     {
  581.         fprintf(stderr, "PlayerSQL.ConnectError\n");
  582.         exit(1);
  583.     }
  584.  
  585.     fprintf(stdout, "PlayerSQL connected\n");
  586.  
  587.     if (false == g_bAuthServer) // 인증 서버가 아닐 경우
  588.     {
  589.         // Log DB 접속
  590.         LogManager::instance().Connect(log_host, log_port, log_user, log_pwd, log_db);
  591.  
  592.         if (!LogManager::instance().IsConnected())
  593.         {
  594.             fprintf(stderr, "LogSQL.ConnectError\n");
  595.             exit(1);
  596.         }
  597.  
  598.         fprintf(stdout, "LogSQL connected\n");
  599.  
  600.         LogManager::instance().BootLog(g_stHostname.c_str(), g_bChannel);
  601.     }
  602.  
  603.     // SKILL_POWER_BY_LEVEL
  604.     // 스트링 비교의 문제로 인해서 AccountDB::instance().SetLocale(g_stLocale) 후부터 한다.
  605.     // 물론 국내는 별로 문제가 안된다(해외가 문제)
  606.     {
  607.         char szQuery[256];
  608.         snprintf(szQuery, sizeof(szQuery), "SELECT mValue FROM locale WHERE mKey='SKILL_POWER_BY_LEVEL'");
  609.         std::auto_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
  610.  
  611.         if (pMsg->Get()->uiNumRows == 0)
  612.         {
  613.             fprintf(stderr, "[SKILL_PERCENT] Query failed: %s", szQuery);
  614.             exit(1);
  615.         }
  616.  
  617.         MYSQL_ROW row;
  618.  
  619.         row = mysql_fetch_row(pMsg->Get()->pSQLResult);
  620.  
  621.         const char * p = row[0];
  622.         int cnt = 0;
  623.         char num[128];
  624.         int aiBaseSkillPowerByLevelTable[SKILL_MAX_LEVEL+1];
  625.  
  626.         fprintf(stdout, "SKILL_POWER_BY_LEVEL %s\n", p);
  627.         while (*p != '\0' && cnt < (SKILL_MAX_LEVEL + 1))
  628.         {
  629.             p = one_argument(p, num, sizeof(num));
  630.             aiBaseSkillPowerByLevelTable[cnt++] = atoi(num);
  631.  
  632.             //fprintf(stdout, "%d %d\n", cnt - 1, aiBaseSkillPowerByLevelTable[cnt - 1]);
  633.             if (*p == '\0')
  634.             {
  635.                 if (cnt != (SKILL_MAX_LEVEL + 1))
  636.                 {
  637.                     fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
  638.                     exit(1);
  639.                 }
  640.  
  641.                 fprintf(stdout, "SKILL_POWER_BY_LEVEL: Done! (count %d)\n", cnt);
  642.                 break;
  643.             }
  644.         }
  645.  
  646.         // 종족별 스킬 세팅
  647.         for (int job = 0; job < JOB_MAX_NUM * 2; ++job)
  648.         {
  649.             snprintf(szQuery, sizeof(szQuery), "SELECT mValue from locale where mKey='SKILL_POWER_BY_LEVEL_TYPE%d' ORDER BY CAST(mValue AS unsigned)", job);
  650.             std::auto_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
  651.  
  652.             // 세팅이 안되어있으면 기본테이블을 사용한다.
  653.             if (pMsg->Get()->uiNumRows == 0)
  654.             {
  655.                 CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiBaseSkillPowerByLevelTable);
  656.                 continue;
  657.             }
  658.  
  659.             row = mysql_fetch_row(pMsg->Get()->pSQLResult);
  660.             cnt = 0;
  661.             p = row[0];
  662.             int aiSkillTable[SKILL_MAX_LEVEL + 1];
  663.  
  664.             fprintf(stdout, "SKILL_POWER_BY_JOB %d %s\n", job, p);
  665.             while (*p != '\0' && cnt < (SKILL_MAX_LEVEL + 1))
  666.             {          
  667.                 p = one_argument(p, num, sizeof(num));
  668.                 aiSkillTable[cnt++] = atoi(num);
  669.  
  670.                 //fprintf(stdout, "%d %d\n", cnt - 1, aiBaseSkillPowerByLevelTable[cnt - 1]);
  671.                 if (*p == '\0')
  672.                 {
  673.                     if (cnt != (SKILL_MAX_LEVEL + 1))
  674.                     {
  675.                         fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
  676.                         exit(1);
  677.                     }
  678.  
  679.                     fprintf(stdout, "SKILL_POWER_BY_JOB: Done! (job: %d count: %d)\n", job, cnt);
  680.                     break;
  681.                 }
  682.             }
  683.  
  684.             CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiSkillTable);
  685.         }      
  686.     }
  687.     // END_SKILL_POWER_BY_LEVEL
  688.  
  689.     // LOG_KEEP_DAYS_EXTEND
  690.     log_set_expiration_days(2);
  691.     // END_OF_LOG_KEEP_DAYS_EXTEND
  692.  
  693.     while (fgets(buf, 256, fp))
  694.     {
  695.         parse_token(buf, token_string, value_string);
  696.  
  697.         TOKEN("empire_whisper")
  698.         {
  699.             bool b_value = 0;
  700.             str_to_number(b_value, value_string);
  701.             g_bEmpireWhisper = !!b_value;
  702.             continue;
  703.         }
  704.  
  705.         TOKEN("mark_server")
  706.         {
  707.             guild_mark_server = is_string_true(value_string);
  708.             continue;
  709.         }
  710.  
  711.         TOKEN("mark_min_level")
  712.         {
  713.             str_to_number(guild_mark_min_level, value_string);
  714.             guild_mark_min_level = MINMAX(0, guild_mark_min_level, GUILD_MAX_LEVEL);
  715.             continue;
  716.         }
  717.  
  718.         TOKEN("port")
  719.         {
  720.             str_to_number(mother_port, value_string);
  721.             continue;
  722.         }
  723.  
  724.         TOKEN("log_keep_days")
  725.         {
  726.             int i = 0;
  727.             str_to_number(i, value_string);
  728.             log_set_expiration_days(MINMAX(1, i, 90));
  729.             continue;
  730.         }
  731.  
  732.         TOKEN("passes_per_sec")
  733.         {
  734.             str_to_number(passes_per_sec, value_string);
  735.             continue;
  736.         }
  737.  
  738.         TOKEN("p2p_port")
  739.         {
  740.             str_to_number(p2p_port, value_string);
  741.             continue;
  742.         }
  743.  
  744.         TOKEN("db_port")
  745.         {
  746.             str_to_number(db_port, value_string);
  747.             continue;
  748.         }
  749.  
  750.         TOKEN("db_addr")
  751.         {
  752.             strlcpy(db_addr, value_string, sizeof(db_addr));
  753.  
  754.             for (int n =0; n < ADDRESS_MAX_LEN; ++n)
  755.             {
  756.                 if (db_addr[n] == ' ')
  757.                     db_addr[n] = '\0';
  758.             }
  759.  
  760.             continue;
  761.         }
  762.  
  763.         TOKEN("save_event_second_cycle")
  764.         {
  765.             int cycle = 0;
  766.             str_to_number(cycle, value_string);
  767.             save_event_second_cycle = cycle * passes_per_sec;
  768.             continue;
  769.         }
  770.  
  771.         TOKEN("ping_event_second_cycle")
  772.         {
  773.             int cycle = 0;
  774.             str_to_number(cycle, value_string);
  775.             ping_event_second_cycle = cycle * passes_per_sec;
  776.             continue;
  777.         }
  778.  
  779.         TOKEN("table_postfix")
  780.         {
  781.             g_table_postfix = value_string;
  782.             continue;
  783.         }
  784.  
  785.         TOKEN("test_server")
  786.         {
  787.             printf("-----------------------------------------------\n");
  788.             printf("TEST_SERVER\n");
  789.             printf("-----------------------------------------------\n");
  790.             str_to_number(test_server, value_string);
  791.             continue;
  792.         }
  793.  
  794.         TOKEN("speed_server")
  795.         {
  796.             printf("-----------------------------------------------\n");
  797.             printf("SPEED_SERVER\n");
  798.             printf("-----------------------------------------------\n");
  799.             str_to_number(speed_server, value_string);
  800.             continue;
  801.         }
  802. #ifdef __AUCTION__
  803.         TOKEN("auction_server")
  804.         {
  805.             printf("-----------------------------------------------\n");
  806.             printf("AUCTION_SERVER\n");
  807.             printf("-----------------------------------------------\n");
  808.             str_to_number(auction_server, value_string);
  809.             continue;
  810.         }
  811. #endif
  812.         TOKEN("distribution_test_server")
  813.         {
  814.             str_to_number(distribution_test_server, value_string);
  815.             continue;
  816.         }
  817.  
  818.         TOKEN("china_event_server")
  819.         {
  820.             str_to_number(china_event_server, value_string);
  821.             continue;
  822.         }
  823.  
  824.         TOKEN("item_count_limit")
  825.         {
  826.             str_to_number(g_bItemCountLimit, value_string);
  827.             continue;
  828.         }
  829.        
  830.         TOKEN("shutdowned")
  831.         {
  832.             g_bNoMoreClient = true;
  833.             continue;
  834.         }
  835.  
  836.         TOKEN("no_regen")
  837.         {
  838.             g_bNoRegen = true;
  839.             continue;
  840.         }
  841.        
  842.         TOKEN("shop_price_3x_disable")
  843.         {
  844.             g_bEmpireShopPriceTrippleDisable = true;
  845.             continue;
  846.         }
  847.  
  848.         TOKEN("shout_addon")
  849.         {
  850.             g_bShoutAddonEnable = true;
  851.             continue;
  852.         }
  853.        
  854.         TOKEN("enable_all_mount_attack")
  855.         {
  856.             g_bAllMountAttack = true;
  857.             continue;
  858.         }      
  859.        
  860.         TOKEN("disable_change_attr_time")
  861.         {
  862.             g_bDisableItemBonusChangeTime = true;
  863.             continue;
  864.         }
  865.        
  866.         TOKEN("disable_prism_item")
  867.         {
  868.             g_bDisablePrismNeed = true;
  869.             continue;
  870.         }
  871.        
  872.         TOKEN("global_shout")
  873.         {
  874.             g_bGlobalShoutEnable = true;
  875.             continue;
  876.         }
  877.                
  878.         TOKEN("disable_emotion_mask")
  879.         {
  880.             g_bDisableEmotionMask = true;
  881.             continue;
  882.         }
  883.        
  884.         TOKEN("traffic_profile")
  885.         {
  886.             g_bTrafficProfileOn = true;
  887.             continue;
  888.         }
  889.  
  890.  
  891.         TOKEN("map_allow")
  892.         {
  893.             char * p = value_string;
  894.             string stNum;
  895.  
  896.             for (; *p; p++)
  897.             {  
  898.                 if (isnhspace(*p))
  899.                 {
  900.                     if (stNum.length())
  901.                     {
  902.                         int index = 0;
  903.                         str_to_number(index, stNum.c_str());
  904.                         map_allow_add(index);
  905.                         stNum.clear();
  906.                     }
  907.                 }
  908.                 else
  909.                     stNum += *p;
  910.             }
  911.  
  912.             if (stNum.length())
  913.             {
  914.                 int index = 0;
  915.                 str_to_number(index, stNum.c_str());
  916.                 map_allow_add(index);
  917.             }
  918.  
  919.             continue;
  920.         }
  921.  
  922.         TOKEN("no_wander")
  923.         {
  924.             no_wander = true;
  925.             continue;
  926.         }
  927.  
  928.         TOKEN("user_limit")
  929.         {
  930.             str_to_number(g_iUserLimit, value_string);
  931.             continue;
  932.         }
  933.  
  934.         TOKEN("skill_disable")
  935.         {
  936.             str_to_number(g_bSkillDisable, value_string);
  937.             continue;
  938.         }
  939.  
  940.         TOKEN("auth_server")
  941.         {
  942.             char szIP[32];
  943.             char szPort[32];
  944.  
  945.             two_arguments(value_string, szIP, sizeof(szIP), szPort, sizeof(szPort));
  946.  
  947.             if (!*szIP || (!*szPort && strcasecmp(szIP, "master")))
  948.             {
  949.                 fprintf(stderr, "AUTH_SERVER: syntax error: <ip|master> <port>\n");
  950.                 exit(1);
  951.             }
  952.  
  953.             g_bAuthServer = true;
  954.  
  955.             LoadBanIP("BANIP");
  956.  
  957.             if (!strcasecmp(szIP, "master"))
  958.                 fprintf(stdout, "AUTH_SERVER: I am the master\n");
  959.             else
  960.             {
  961.                 g_stAuthMasterIP = szIP;
  962.                 str_to_number(g_wAuthMasterPort, szPort);
  963.  
  964.                 fprintf(stdout, "AUTH_SERVER: master %s %u\n", g_stAuthMasterIP.c_str(), g_wAuthMasterPort);
  965.             }
  966.             continue;
  967.         }
  968.  
  969.         TOKEN("billing")
  970.         {
  971.             g_bBilling = true;
  972.         }
  973.  
  974.         TOKEN("quest_dir")
  975.         {
  976.             sys_log(0, "QUEST_DIR SETTING : %s", value_string);
  977.             g_stQuestDir = value_string;
  978.         }
  979.  
  980.         TOKEN("quest_object_dir")
  981.         {
  982.             //g_stQuestObjectDir = value_string;
  983.             std::istringstream is(value_string);
  984.             sys_log(0, "QUEST_OBJECT_DIR SETTING : %s", value_string);
  985.             string dir;
  986.             while (!is.eof())
  987.             {
  988.                 is >> dir;
  989.                 if (is.fail())
  990.                     break;
  991.                 g_setQuestObjectDir.insert(dir);
  992.                 sys_log(0, "QUEST_OBJECT_DIR INSERT : %s", dir .c_str());
  993.             }
  994.         }
  995.  
  996.         TOKEN("teen_addr")
  997.         {
  998.             strlcpy(teen_addr, value_string, sizeof(teen_addr));
  999.  
  1000.             for (int n =0; n < ADDRESS_MAX_LEN; ++n)
  1001.             {
  1002.                 if (teen_addr[n] == ' ')
  1003.                     teen_addr[n] = '\0';
  1004.             }
  1005.  
  1006.             continue;
  1007.         }
  1008.  
  1009.         TOKEN("teen_port")
  1010.         {
  1011.             str_to_number(teen_port, value_string);
  1012.         }
  1013.  
  1014.         TOKEN("synchack_limit_count")
  1015.         {
  1016.             str_to_number(g_iSyncHackLimitCount, value_string);
  1017.         }
  1018.  
  1019.         TOKEN("speedhack_limit_count")
  1020.         {
  1021.             str_to_number(SPEEDHACK_LIMIT_COUNT, value_string);
  1022.         }
  1023.  
  1024.         TOKEN("speedhack_limit_bonus")
  1025.         {
  1026.             str_to_number(SPEEDHACK_LIMIT_BONUS, value_string);
  1027.         }
  1028.  
  1029.         TOKEN("server_id")
  1030.         {
  1031.             str_to_number(g_server_id, value_string);
  1032.         }
  1033.  
  1034.         TOKEN("mall_url")
  1035.         {
  1036.             g_strWebMallURL = value_string;
  1037.         }
  1038.  
  1039.         TOKEN("bind_ip")
  1040.         {
  1041.             strlcpy(g_szPublicIP, value_string, sizeof(g_szPublicIP));
  1042.         }
  1043.  
  1044.         TOKEN("view_range")
  1045.         {
  1046.             str_to_number(VIEW_RANGE, value_string);
  1047.         }
  1048.  
  1049.         TOKEN("spam_block_duration")
  1050.         {
  1051.             str_to_number(g_uiSpamBlockDuration, value_string);
  1052.         }
  1053.  
  1054.         TOKEN("spam_block_score")
  1055.         {
  1056.             str_to_number(g_uiSpamBlockScore, value_string);
  1057.             g_uiSpamBlockScore = MAX(1, g_uiSpamBlockScore);
  1058.         }
  1059.  
  1060.         TOKEN("spam_block_reload_cycle")
  1061.         {
  1062.             str_to_number(g_uiSpamReloadCycle, value_string);
  1063.             g_uiSpamReloadCycle = MAX(60, g_uiSpamReloadCycle); // 최소 1분
  1064.         }
  1065.  
  1066.         TOKEN("check_multihack")
  1067.         {
  1068.             str_to_number(g_bCheckMultiHack, value_string);
  1069.         }
  1070.  
  1071.         TOKEN("spam_block_max_level")
  1072.         {
  1073.             str_to_number(g_iSpamBlockMaxLevel, value_string);
  1074.         }
  1075.         TOKEN("protect_normal_player")
  1076.         {
  1077.             str_to_number(g_protectNormalPlayer, value_string);
  1078.         }
  1079.         TOKEN("notice_battle_zone")
  1080.         {
  1081.             str_to_number(g_noticeBattleZone, value_string);
  1082.         }
  1083.  
  1084.         TOKEN("hackshield_enable")
  1085.         {
  1086.             int flag = 0;
  1087.  
  1088.             str_to_number(flag, value_string);
  1089.  
  1090.             //if (1 == flag && LC_IsEurope() )
  1091.             if (1 == flag)
  1092.             {
  1093.                 isHackShieldEnable = true;
  1094.             }
  1095.         }
  1096.  
  1097.         TOKEN("hackshield_first_check_time")
  1098.         {
  1099.             int secs = 30;
  1100.             str_to_number(secs, value_string);
  1101.  
  1102.             HackShield_FirstCheckWaitTime = passes_per_sec * secs;
  1103.         }
  1104.  
  1105.         TOKEN("hackshield_check_cycle_time")
  1106.         {
  1107.             int secs = 180;
  1108.             str_to_number(secs, value_string);
  1109.  
  1110.             HackShield_CheckCycleTime = passes_per_sec * secs;
  1111.         }
  1112.  
  1113.         TOKEN("xtrap_enable")
  1114.         {
  1115.             int flag = 0;
  1116.             str_to_number(flag, value_string);
  1117.  
  1118.             if (1 == flag )
  1119.             {
  1120.                 bXTrapEnabled = true;
  1121.             }
  1122.         }
  1123.  
  1124.         TOKEN("pk_protect_level")
  1125.         {
  1126.             str_to_number(PK_PROTECT_LEVEL, value_string);
  1127.             fprintf(stderr, "PK_PROTECT_LEVEL: %d", PK_PROTECT_LEVEL);
  1128.         }
  1129.  
  1130.         TOKEN("max_level")
  1131.         {
  1132.             str_to_number(gPlayerMaxLevel, value_string);
  1133.  
  1134.             gPlayerMaxLevel = MINMAX(1, gPlayerMaxLevel, PLAYER_MAX_LEVEL_CONST);
  1135.  
  1136.             fprintf(stderr, "PLAYER_MAX_LEVEL: %d\n", gPlayerMaxLevel);
  1137.         }
  1138.         TOKEN("shutdown_age")
  1139.         {
  1140.             str_to_number(gShutdownAge, value_string);
  1141.             fprintf(stderr, "SHUTDOWN_AGE: %d\n", gShutdownAge);
  1142.  
  1143.         }
  1144.         TOKEN("shutdown_enable")
  1145.         {
  1146.             str_to_number(gShutdownEnable, value_string);
  1147.             fprintf(stderr, "SHUTDOWN_ENABLE: %d\n", gShutdownEnable);
  1148.         }
  1149.         TOKEN("block_char_creation")
  1150.         {
  1151.             int tmp = 0;
  1152.  
  1153.             str_to_number(tmp, value_string);
  1154.  
  1155.             if (0 == tmp)
  1156.                 g_BlockCharCreation = false;
  1157.             else
  1158.                 g_BlockCharCreation = true;
  1159.  
  1160.             continue;
  1161.         }
  1162.     }
  1163.  
  1164.     if (g_setQuestObjectDir.empty())
  1165.         g_setQuestObjectDir.insert(g_stDefaultQuestObjectDir);
  1166.  
  1167.     if (0 == db_port)
  1168.     {
  1169.         fprintf(stderr, "DB_PORT not configured\n");
  1170.         exit(1);
  1171.     }
  1172.  
  1173.     if (0 == g_bChannel)
  1174.     {
  1175.         fprintf(stderr, "CHANNEL not configured\n");
  1176.         exit(1);
  1177.     }
  1178.  
  1179.     if (g_stHostname.empty())
  1180.     {
  1181.         fprintf(stderr, "HOSTNAME must be configured.\n");
  1182.         exit(1);
  1183.     }
  1184.  
  1185.     // LOCALE_SERVICE
  1186.     LocaleService_LoadLocaleStringFile();
  1187.     LocaleService_TransferDefaultSetting();
  1188.     LocaleService_LoadEmpireTextConvertTables();
  1189.     // END_OF_LOCALE_SERVICE
  1190.  
  1191.     fclose(fp);
  1192.  
  1193.     if ((fp = fopen("CMD", "r")))
  1194.     {
  1195.         while (fgets(buf, 256, fp))
  1196.         {
  1197.             char cmd[32], levelname[32];
  1198.             int level;
  1199.  
  1200.             two_arguments(buf, cmd, sizeof(cmd), levelname, sizeof(levelname));
  1201.  
  1202.             if (!*cmd || !*levelname)
  1203.             {
  1204.                 fprintf(stderr, "CMD syntax error: <cmd> <DISABLE | LOW_WIZARD | WIZARD | HIGH_WIZARD | GOD>\n");
  1205.                 exit(1);
  1206.             }
  1207.  
  1208.             if (!strcasecmp(levelname, "LOW_WIZARD"))
  1209.                 level = GM_LOW_WIZARD;
  1210.             else if (!strcasecmp(levelname, "WIZARD"))
  1211.                 level = GM_WIZARD;
  1212.             else if (!strcasecmp(levelname, "HIGH_WIZARD"))
  1213.                 level = GM_HIGH_WIZARD;
  1214.             else if (!strcasecmp(levelname, "GOD"))
  1215.                 level = GM_GOD;
  1216.             else if (!strcasecmp(levelname, "IMPLEMENTOR"))
  1217.                 level = GM_IMPLEMENTOR;
  1218.             else if (!strcasecmp(levelname, "DISABLE"))
  1219.                 level = GM_IMPLEMENTOR + 1;
  1220.             else
  1221.             {
  1222.                 fprintf(stderr, "CMD syntax error: <cmd> <DISABLE | LOW_WIZARD | WIZARD | HIGH_WIZARD | GOD>\n");
  1223.                 exit(1);
  1224.             }
  1225.  
  1226.             interpreter_set_privilege(cmd, level);
  1227.         }
  1228.  
  1229.         fclose(fp);
  1230.     }
  1231.  
  1232.     if(!gHackCheckEnable)   // Hack 체크가 비활성화인 경우
  1233.     {
  1234.         assert(test_server);    // 테스트 서버가 아니라면 assert
  1235.     }
  1236.  
  1237.     LoadValidCRCList();
  1238.     LoadStateUserCount();
  1239.  
  1240.     CWarMapManager::instance().LoadWarMapInfo(NULL);
  1241.  
  1242.     FN_log_adminpage();
  1243.     if (g_szPublicIP[0] == '0')
  1244.     {
  1245.         fprintf(stderr, "Can not get public ip address\n");
  1246.         exit(1);
  1247.     }
  1248. }
  1249.  
  1250. const char* get_table_postfix()
  1251. {
  1252.     return g_table_postfix.c_str();
  1253. }
  1254.  
  1255. void LoadValidCRCList()
  1256. {
  1257.     s_set_dwProcessCRC.clear();
  1258.     s_set_dwFileCRC.clear();
  1259.  
  1260.     FILE * fp;
  1261.     char buf[256];
  1262.  
  1263.     if ((fp = fopen("CRC", "r")))
  1264.     {
  1265.         while (fgets(buf, 256, fp))
  1266.         {
  1267.             if (!*buf)
  1268.                 continue;
  1269.  
  1270.             DWORD dwValidClientProcessCRC;
  1271.             DWORD dwValidClientFileCRC;
  1272.  
  1273.             sscanf(buf, " %u %u ", &dwValidClientProcessCRC, &dwValidClientFileCRC);
  1274.  
  1275.             s_set_dwProcessCRC.insert(dwValidClientProcessCRC);
  1276.             s_set_dwFileCRC.insert(dwValidClientFileCRC);
  1277.  
  1278.             fprintf(stderr, "CLIENT_CRC: %u %u\n", dwValidClientProcessCRC, dwValidClientFileCRC);
  1279.         }
  1280.  
  1281.         fclose(fp);
  1282.     }
  1283. }
  1284.  
  1285. bool LoadClientVersion()
  1286. {
  1287.     FILE * fp = fopen("VERSION", "r");
  1288.  
  1289.     if (!fp)
  1290.         return false;
  1291.  
  1292.     char buf[256];
  1293.     fgets(buf, 256, fp);
  1294.  
  1295.     char * p = strchr(buf, '\n');
  1296.     if (p) *p = '\0';
  1297.  
  1298.     fprintf(stderr, "VERSION: \"%s\"\n", buf);
  1299.  
  1300.     g_stClientVersion = buf;
  1301.     fclose(fp);
  1302.     return true;
  1303. }
  1304.  
  1305. void CheckClientVersion()
  1306. {
  1307.     if (LC_IsEurope())
  1308.     {
  1309.         g_bCheckClientVersion = true;
  1310.     }
  1311.     else
  1312.     {
  1313.         g_bCheckClientVersion = false;
  1314.     }
  1315.  
  1316.     const DESC_MANAGER::DESC_SET & set = DESC_MANAGER::instance().GetClientSet();
  1317.     DESC_MANAGER::DESC_SET::const_iterator it = set.begin();
  1318.  
  1319.     while (it != set.end())
  1320.     {
  1321.         LPDESC d = *(it++);
  1322.  
  1323.         if (!d->GetCharacter())
  1324.             continue;
  1325.  
  1326.  
  1327.         int version = atoi(g_stClientVersion.c_str());
  1328.         int date    = atoi(d->GetClientVersion() );
  1329.  
  1330.         //if (0 != g_stClientVersion.compare(d->GetClientVersion()) )
  1331.         if (version > date)
  1332.         {
  1333.             d->GetCharacter()->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("클라이언트 버전이 틀려 로그아웃 됩니다. 정상적으로 패치 후 접속하세요."));
  1334.             d->DelayedDisconnect(10);
  1335.         }
  1336.     }
  1337. }
  1338.  
  1339. void LoadStateUserCount()
  1340. {
  1341.     FILE * fp = fopen("state_user_count", "r");
  1342.  
  1343.     if (!fp)
  1344.         return;
  1345.  
  1346.     if (!LC_IsHongKong())
  1347.         fscanf(fp, " %d %d ", &g_iFullUserCount, &g_iBusyUserCount);
  1348.  
  1349.     fclose(fp);
  1350. }
  1351.  
  1352. bool IsValidProcessCRC(DWORD dwCRC)
  1353. {
  1354.     return s_set_dwProcessCRC.find(dwCRC) != s_set_dwProcessCRC.end();
  1355. }
  1356.  
  1357. bool IsValidFileCRC(DWORD dwCRC)
  1358. {
  1359.     return s_set_dwFileCRC.find(dwCRC) != s_set_dwFileCRC.end();
  1360. }
Advertisement
RAW Paste Data Copied
Advertisement