Advertisement
Guest User

Untitled

a guest
Oct 27th, 2016
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 49.82 KB | None | 0 0
  1. /*
  2. ===========================================================================
  3.  
  4. Copyright (c) 2010-2015 Darkstar Dev Teams
  5.  
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program.  If not, see http://www.gnu.org/licenses/
  18.  
  19. This file is part of DarkStar-server source code.
  20.  
  21. ===========================================================================
  22. */
  23.  
  24. #include "../common/blowfish.h"
  25. #include "../common/malloc.h"
  26. #include "../common/md52.h"
  27. #include "../common/showmsg.h"
  28. #include "../common/strlib.h"
  29. #include "../common/timer.h"
  30. #include "../common/utils.h"
  31. #include "../common/version.h"
  32. #include "../common/zlib.h"
  33. #include "../common/sql.h"
  34.  
  35. #include <math.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <thread>
  40.  
  41. #include "alliance.h"
  42. #include "ability.h"
  43. #include "utils/battleutils.h"
  44. #include "utils/charutils.h"
  45. #include "utils/fishingutils.h"
  46. #include "utils/guildutils.h"
  47. #include "utils/instanceutils.h"
  48. #include "utils/itemutils.h"
  49. #include "linkshell.h"
  50. #include "map.h"
  51. #include "mob_spell_list.h"
  52. #include "packet_system.h"
  53. #include "party.h"
  54. #include "utils/petutils.h"
  55. #include "spell.h"
  56. #include "time_server.h"
  57. #include "transport.h"
  58. #include "vana_time.h"
  59. #include "status_effect_container.h"
  60. #include "utils/zoneutils.h"
  61. #include "conquest_system.h"
  62. #include "utils/mobutils.h"
  63.  
  64. #include "lua/luautils.h"
  65.  
  66. #include "packets/basic.h"
  67. #include "packets/char_update.h"
  68. #include "message.h"
  69.  
  70.  
  71. const int8* MAP_CONF_FILENAME = nullptr;
  72.  
  73. int8*  g_PBuff = nullptr;                // глобальный буфер обмена пакетами
  74. int8*  PTempBuff = nullptr;                // временный  буфер обмена пакетами
  75.  
  76. thread_local Sql_t* SqlHandle = nullptr;
  77.  
  78. int32  map_fd = 0;                      // main socket
  79. uint32 map_amntplayers = 0;             // map amnt unique players
  80.  
  81. in_addr map_ip;
  82. uint16 map_port = 0;
  83.  
  84. map_config_t map_config;                // map server settings
  85. map_session_list_t map_session_list;
  86. CCommandHandler CmdHandler;
  87.  
  88. std::thread messageThread;
  89.  
  90. /************************************************************************
  91. *                                                                       *
  92. *  mapsession_getbyipp                                                  *
  93. *                                                                       *
  94. ************************************************************************/
  95.  
  96. map_session_data_t* mapsession_getbyipp(uint64 ipp)
  97. {
  98.     map_session_list_t::iterator i = map_session_list.begin();
  99.     while (i != map_session_list.end())
  100.     {
  101.         if ((*i).first == ipp)
  102.             return (*i).second;
  103.         i++;
  104.     }
  105.     return nullptr;
  106. }
  107.  
  108. /************************************************************************
  109. *                                                                       *
  110. *  mapsession_createsession                                             *
  111. *                                                                       *
  112. ************************************************************************/
  113.  
  114. map_session_data_t* mapsession_createsession(uint32 ip, uint16 port)
  115. {
  116.     map_session_data_t* map_session_data = new map_session_data_t;
  117.     memset(map_session_data, 0, sizeof(map_session_data_t));
  118.  
  119.     CREATE(map_session_data->server_packet_data, int8, map_config.buffer_size + 20);
  120.  
  121.     map_session_data->last_update = time(nullptr);
  122.     map_session_data->client_addr = ip;
  123.     map_session_data->client_port = port;
  124.  
  125.     uint64 port64 = port;
  126.     uint64 ipp = ip;
  127.     ipp |= port64 << 32;
  128.     map_session_list[ipp] = map_session_data;
  129.  
  130.     const int8* fmtQuery = "SELECT charid FROM accounts_sessions WHERE inet_ntoa(client_addr) = '%s' LIMIT 1;";
  131.  
  132.     int32 ret = Sql_Query(SqlHandle, fmtQuery, ip2str(map_session_data->client_addr, nullptr));
  133.  
  134.     if (ret == SQL_ERROR ||
  135.         Sql_NumRows(SqlHandle) == 0)
  136.     {
  137.         ShowError(CL_RED"recv_parse: Invalid login attempt from %s\n" CL_RESET, ip2str(map_session_data->client_addr, nullptr));
  138.         return nullptr;
  139.     }
  140.     return map_session_data;
  141. }
  142.  
  143. /************************************************************************
  144. *                                                                       *
  145. *  do_init                                                              *
  146. *                                                                       *
  147. ************************************************************************/
  148.  
  149. int32 do_init(int32 argc, int8** argv)
  150. {
  151.     ShowStatus("do_init: begin server initialization...\n");
  152.     map_ip.s_addr = 0;
  153.  
  154.     for (int i = 1; i < argc; i++)
  155.     {
  156.         if (strcmp(argv[i], "--ip") == 0)
  157.             map_ip.s_addr = inet_addr(argv[i + 1]);
  158.         else if (strcmp(argv[i], "--port") == 0)
  159.             map_port = std::stoi(argv[i + 1]);
  160.     }
  161.  
  162.     MAP_CONF_FILENAME = "./conf/map_darkstar.conf";
  163.  
  164.     srand((uint32)time(nullptr));
  165.     dsprand::seed();
  166.  
  167.     map_config_default();
  168.     map_config_read(MAP_CONF_FILENAME);
  169.     ShowMessage("\t\t\t - " CL_GREEN"[OK]" CL_RESET"\n");
  170.     ShowStatus("do_init: map_config is reading");
  171.     ShowMessage("\t\t - " CL_GREEN"[OK]" CL_RESET"\n");
  172.  
  173.     luautils::init();
  174.     CmdHandler.init(luautils::LuaHandle);
  175.     PacketParserInitialize();
  176.     SqlHandle = Sql_Malloc();
  177.  
  178.     ShowStatus("do_init: sqlhandle is allocating");
  179.     if (Sql_Connect(SqlHandle, map_config.mysql_login,
  180.         map_config.mysql_password,
  181.         map_config.mysql_host,
  182.         map_config.mysql_port,
  183.         map_config.mysql_database) == SQL_ERROR)
  184.     {
  185.         do_final(EXIT_FAILURE);
  186.     }
  187.     Sql_Keepalive(SqlHandle);
  188.  
  189.     // отчищаем таблицу сессий при старте сервера (временное решение, т.к. в кластере это не будет работать)
  190.     Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE IF(%u = 0 AND %u = 0, true, server_addr = %u AND server_port = %u);",
  191.         map_ip, map_port, map_ip, map_port);
  192.  
  193.     ShowMessage("\t\t - " CL_GREEN"[OK]" CL_RESET"\n");
  194.     ShowStatus("do_init: zlib is reading");
  195.     zlib_init();
  196.     ShowMessage("\t\t\t - " CL_GREEN"[OK]" CL_RESET"\n");
  197.  
  198.     messageThread = std::thread(message::init, map_config.msg_server_ip, map_config.msg_server_port);
  199.  
  200.     ShowStatus("do_init: loading items");
  201.     itemutils::Initialize();
  202.     ShowMessage("\t\t\t - " CL_GREEN"[OK]" CL_RESET"\n");
  203.  
  204.     // нужно будет написать один метод для инициализации всех данных в battleutils
  205.     // и один метод для освобождения этих данных
  206.  
  207.     ShowStatus("do_init: loading spells");
  208.     spell::LoadSpellList();
  209.     mobSpellList::LoadMobSpellList();
  210.     ShowMessage("\t\t\t - " CL_GREEN"[OK]" CL_RESET"\n");
  211.  
  212.     guildutils::Initialize();
  213.     charutils::LoadExpTable();
  214.     traits::LoadTraitsList();
  215.     effects::LoadEffectsParameters();
  216.     battleutils::LoadSkillTable();
  217.     meritNameSpace::LoadMeritsList();
  218.     ability::LoadAbilitiesList();
  219.     battleutils::LoadWeaponSkillsList();
  220.     battleutils::LoadMobSkillsList();
  221.     battleutils::LoadSkillChainDamageModifiers();
  222.     petutils::LoadPetList();
  223.     mobutils::LoadCustomMods();
  224.  
  225.     ShowStatus("do_init: loading zones");
  226.     zoneutils::LoadZoneList();
  227.     ShowMessage("\t\t\t - " CL_GREEN"[OK]" CL_RESET"\n");
  228.  
  229.     fishingutils::LoadFishingMessages();
  230.  
  231.     ShowStatus("do_init: server is binding with port %u", map_port == 0 ? map_config.usMapPort : map_port);
  232.     map_fd = makeBind_udp(map_config.uiMapIp, map_port == 0 ? map_config.usMapPort : map_port);
  233.     ShowMessage("\t - " CL_GREEN"[OK]" CL_RESET"\n");
  234.  
  235.     CVanaTime::getInstance()->setCustomOffset(map_config.vanadiel_time_offset);
  236.  
  237.     zoneutils::InitializeWeather(); // Need VanaTime initialized
  238.  
  239.     CTransportHandler::getInstance()->InitializeTransport();
  240.  
  241.     CTaskMgr::getInstance()->AddTask("time_server", server_clock::now(), nullptr, CTaskMgr::TASK_INTERVAL, time_server, 2400ms);
  242.     CTaskMgr::getInstance()->AddTask("map_cleanup", server_clock::now(), nullptr, CTaskMgr::TASK_INTERVAL, map_cleanup, 5s);
  243.     CTaskMgr::getInstance()->AddTask("garbage_collect", server_clock::now(), nullptr, CTaskMgr::TASK_INTERVAL, map_garbage_collect, 15min);
  244.  
  245.     CREATE(g_PBuff, int8, map_config.buffer_size + 20);
  246.     CREATE(PTempBuff, int8, map_config.buffer_size + 20);
  247.  
  248.     ShowStatus("The map-server is " CL_GREEN"ready" CL_RESET" to work...\n");
  249.     ShowMessage("=======================================================================\n");
  250.     return 0;
  251. }
  252.  
  253. /************************************************************************
  254. *                                                                       *
  255. *  do_final                                                             *
  256. *                                                                       *
  257. ************************************************************************/
  258.  
  259. void do_final(int code)
  260. {
  261.     aFree(g_PBuff);
  262.     aFree(PTempBuff);
  263.  
  264.     aFree((void*)map_config.mysql_host);
  265.     aFree((void*)map_config.mysql_database);
  266.  
  267.     itemutils::FreeItemList();
  268.     battleutils::FreeWeaponSkillsList();
  269.     battleutils::FreeMobSkillList();
  270.  
  271.     petutils::FreePetList();
  272.     zoneutils::FreeZoneList();
  273.     luautils::free();
  274.     message::close();
  275.     if (messageThread.joinable())
  276.     {
  277.         messageThread.join();
  278.     }
  279.  
  280.     delete CTaskMgr::getInstance();
  281.     delete CVanaTime::getInstance();
  282.  
  283.     Sql_Free(SqlHandle);
  284.  
  285.     timer_final();
  286.     socket_final();
  287.     malloc_final();
  288.  
  289.     exit(code);
  290. }
  291.  
  292. /************************************************************************
  293. *                                                                       *
  294. *  do_abort                                                             *
  295. *                                                                       *
  296. ************************************************************************/
  297.  
  298. void do_abort(void)
  299. {
  300.     do_final(EXIT_FAILURE);
  301. }
  302.  
  303. /************************************************************************
  304. *                                                                       *
  305. *  set_server_type                                                      *
  306. *                                                                       *
  307. ************************************************************************/
  308.  
  309. void set_server_type()
  310. {
  311.     SERVER_TYPE = DARKSTAR_SERVER_MAP;
  312. }
  313.  
  314. /************************************************************************
  315. *                                                                       *
  316. *  do_sockets                                                           *
  317. *                                                                       *
  318. ************************************************************************/
  319.  
  320. int32 do_sockets(fd_set* rfd, duration next)
  321. {
  322.     struct timeval timeout;
  323.     int32 ret;
  324.     memcpy(rfd, &readfds, sizeof(*rfd));
  325.  
  326.     timeout.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(next).count();
  327.     timeout.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(next - std::chrono::duration_cast<std::chrono::seconds>(next)).count();
  328.  
  329.     ret = sSelect(fd_max, rfd, nullptr, nullptr, &timeout);
  330.  
  331.     if (ret == SOCKET_ERROR)
  332.     {
  333.         if (sErrno != S_EINTR)
  334.         {
  335.             ShowFatalError("do_sockets: select() failed, error code %d!\n", sErrno);
  336.             do_final(EXIT_FAILURE);
  337.         }
  338.         return 0; // interrupted by a signal, just loop and try again
  339.     }
  340.  
  341.     last_tick = time(nullptr);
  342.  
  343.     if (sFD_ISSET(map_fd, rfd))
  344.     {
  345.         struct sockaddr_in from;
  346.         socklen_t fromlen = sizeof(from);
  347.  
  348.         int32 ret = recvudp(map_fd, g_PBuff, map_config.buffer_size, 0, (struct sockaddr*)&from, &fromlen);
  349.         if (ret != -1)
  350.         {
  351.             // find player char
  352. #   ifdef WIN32
  353.             uint32 ip = ntohl(from.sin_addr.S_un.S_addr);
  354. #   else
  355.             uint32 ip = ntohl(from.sin_addr.s_addr);
  356. #   endif
  357.  
  358.             uint64 port = ntohs(from.sin_port);
  359.             uint64 ipp = ip;
  360.             ipp |= port << 32;
  361.             map_session_data_t* map_session_data = mapsession_getbyipp(ipp);
  362.  
  363.             if (map_session_data == nullptr)
  364.             {
  365.                 map_session_data = mapsession_createsession(ip, ntohs(from.sin_port));
  366.                 if (map_session_data == nullptr)
  367.                 {
  368.                     map_session_list.erase(ipp);
  369.                     return -1;
  370.                 }
  371.             }
  372.  
  373.             map_session_data->last_update = time(nullptr);
  374.             size_t size = ret;
  375.  
  376.             if (recv_parse(g_PBuff, &size, &from, map_session_data) != -1)
  377.             {
  378.                 // если предыдущий пакет был потерян, то мы не собираем новый,
  379.                 // а отправляем предыдущий пакет повторно
  380.                 if (!parse(g_PBuff, &size, &from, map_session_data))
  381.                 {
  382.                     send_parse(g_PBuff, &size, &from, map_session_data);
  383.                 }
  384.  
  385.                 ret = sendudp(map_fd, g_PBuff, size, 0, (const struct sockaddr*)&from, fromlen);
  386.  
  387.                 int8* data = g_PBuff;
  388.                 g_PBuff = map_session_data->server_packet_data;
  389.  
  390.                 map_session_data->server_packet_data = data;
  391.                 map_session_data->server_packet_size = size;
  392.             }
  393.             if (map_session_data->shuttingDown > 0)
  394.             {
  395.                 map_close_session(server_clock::now(), map_session_data);
  396.             }
  397.         }
  398.     }
  399.     return 0;
  400. }
  401.  
  402. /************************************************************************
  403. *                                                                       *
  404. *  parse_console                                                        *
  405. *                                                                       *
  406. ************************************************************************/
  407.  
  408. int32 parse_console(int8* buf)
  409. {
  410.     return 0;
  411. }
  412.  
  413. /************************************************************************
  414. *                                                                       *
  415. *  map_decipher_packet                                                  *
  416. *                                                                       *
  417. ************************************************************************/
  418.  
  419. int32 map_decipher_packet(int8* buff, size_t size, sockaddr_in* from, map_session_data_t* map_session_data)
  420. {
  421.     uint16 tmp, i;
  422.  
  423.     // counting blocks whose size = 4 byte
  424.     tmp = (size - FFXI_HEADER_SIZE) / 4;
  425.     tmp -= tmp % 2;
  426.  
  427. #   ifdef WIN32
  428.     uint32 ip = ntohl(from->sin_addr.S_un.S_addr);
  429. #   else
  430.     uint32 ip = ntohl(from->sin_addr.s_addr);
  431. #   endif
  432.  
  433.     blowfish_t *pbfkey = &map_session_data->blowfish;
  434.  
  435.     for (i = 0; i < tmp; i += 2)
  436.     {
  437.         blowfish_decipher((uint32*)buff + i + 7, (uint32*)buff + i + 8, pbfkey->P, pbfkey->S[0]);
  438.     }
  439.  
  440.     if (checksum((uint8*)(buff + FFXI_HEADER_SIZE), size - (FFXI_HEADER_SIZE + 16), buff + size - 16) == 0)
  441.     {
  442.         return 0;
  443.     }
  444.  
  445.     int8 ip_str[16];
  446.     ShowError("map_encipher_packet: bad packet from <%s>\n", ip2str(ip, ip_str));
  447.     return -1;
  448. }
  449.  
  450. /************************************************************************
  451. *                                                                       *
  452. *  main function to parse recv packets                                  *
  453. *                                                                       *
  454. ************************************************************************/
  455.  
  456. int32 recv_parse(int8* buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data)
  457. {
  458.     size_t size = *buffsize;
  459.     int32 checksumResult = -1;
  460.  
  461. #ifdef WIN32
  462.     try
  463.     {
  464.         checksumResult = checksum((uint8*)(buff + FFXI_HEADER_SIZE), size - (FFXI_HEADER_SIZE + 16), buff + size - 16);
  465.     }
  466.     catch (...)
  467.     {
  468.         ShowError(CL_RED"Possible crash attempt from: %s\n" CL_RESET, ip2str(map_session_data->client_addr, nullptr));
  469.         return -1;
  470.     }
  471. #else
  472.     checksumResult = checksum((uint8*)(buff + FFXI_HEADER_SIZE), size - (FFXI_HEADER_SIZE + 16), buff + size - 16);
  473. #endif
  474.  
  475.     if (checksumResult == 0)
  476.     {
  477.         if (map_session_data->PChar == nullptr)
  478.         {
  479.             uint32 CharID = RBUFL(buff, FFXI_HEADER_SIZE + 0x0C);
  480.  
  481.             const int8* fmtQuery = "SELECT charid FROM chars WHERE charid = %u LIMIT 1;";
  482.  
  483.             int32 ret = Sql_Query(SqlHandle, fmtQuery, CharID);
  484.  
  485.             if (ret == SQL_ERROR ||
  486.                 Sql_NumRows(SqlHandle) == 0 ||
  487.                 Sql_NextRow(SqlHandle) != SQL_SUCCESS)
  488.             {
  489.                 ShowError(CL_RED"recv_parse: Cannot load charid %u" CL_RESET, CharID);
  490.                 return -1;
  491.             }
  492.  
  493.             fmtQuery = "SELECT session_key FROM accounts_sessions WHERE charid = %u LIMIT 1;";
  494.  
  495.             ret = Sql_Query(SqlHandle, fmtQuery, CharID);
  496.  
  497.             if (ret == SQL_ERROR ||
  498.                 Sql_NumRows(SqlHandle) == 0 ||
  499.                 Sql_NextRow(SqlHandle) != SQL_SUCCESS)
  500.             {
  501.                 ShowError(CL_RED"recv_parse: Cannot load session_key for charid %u" CL_RESET, CharID);
  502.             }
  503.             else
  504.             {
  505.                 int8* strSessionKey = nullptr;
  506.                 Sql_GetData(SqlHandle, 0, &strSessionKey, nullptr);
  507.  
  508.                 memcpy(map_session_data->blowfish.key, strSessionKey, 20);
  509.             }
  510.  
  511.             // наверное создание персонажа лучше вынести в метод charutils::LoadChar() и загрузку инвентаря туда же сунуть
  512.             CCharEntity* PChar = new CCharEntity();
  513.             PChar->id = CharID;
  514.  
  515.             charutils::LoadChar(PChar);
  516.  
  517.             PChar->status = STATUS_DISAPPEAR;
  518.  
  519.             map_session_data->PChar = PChar;
  520.         }
  521.         map_session_data->client_packet_id = 0;
  522.         map_session_data->server_packet_id = 0;
  523.         return 0;
  524.     }
  525.     else
  526.     {
  527.         //char packets
  528.  
  529.         if (map_decipher_packet(buff, *buffsize, from, map_session_data) == -1)
  530.         {
  531.             *buffsize = 0;
  532.             return -1;
  533.         }
  534.         // reading data size
  535.         uint32 PacketDataSize = RBUFL(buff, *buffsize - sizeof(int32) - 16);
  536.         // creating buffer for decompress data
  537.         int8* PacketDataBuff = nullptr;
  538.         CREATE(PacketDataBuff, int8, map_config.buffer_size);
  539.         // it's decompressing data and getting new size
  540.         PacketDataSize = zlib_decompress(buff + FFXI_HEADER_SIZE,
  541.             PacketDataSize,
  542.             PacketDataBuff,
  543.             map_config.buffer_size);
  544.  
  545.         // it's making result buff
  546.         // don't need memcpy header
  547.         memcpy(buff + FFXI_HEADER_SIZE, PacketDataBuff, PacketDataSize);
  548.         *buffsize = FFXI_HEADER_SIZE + PacketDataSize;
  549.  
  550.         aFree(PacketDataBuff);
  551.         return 0;
  552.     }
  553.     return -1;
  554. }
  555.  
  556. /************************************************************************
  557. *                                                                       *
  558. *  main function parsing the packets                                    *
  559. *                                                                       *
  560. ************************************************************************/
  561.  
  562. int32 parse(int8* buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data)
  563. {
  564.     // начало обработки входящего пакета
  565.  
  566.     int8* PacketData_Begin = &buff[FFXI_HEADER_SIZE];
  567.     int8* PacketData_End = &buff[*buffsize];
  568.  
  569.     CCharEntity *PChar = map_session_data->PChar;
  570.  
  571.     uint16 SmallPD_Size = 0;
  572.     uint16 SmallPD_Type = 0;
  573.     uint16 SmallPD_Code = RBUFW(buff, 0);
  574.  
  575.     for (int8* SmallPD_ptr = PacketData_Begin;
  576.         SmallPD_ptr + (RBUFB(SmallPD_ptr, 1) & 0xFE) * 2 <= PacketData_End && (RBUFB(SmallPD_ptr, 1) & 0xFE);
  577.         SmallPD_ptr = SmallPD_ptr + SmallPD_Size * 2)
  578.     {
  579.         SmallPD_Size = (RBUFB(SmallPD_ptr, 1) & 0x0FE);
  580.         SmallPD_Type = (RBUFW(SmallPD_ptr, 0) & 0x1FF);
  581.  
  582.         if (PacketSize[SmallPD_Type] == SmallPD_Size || PacketSize[SmallPD_Type] == 0) // Tests incoming packets for the correct size prior to processing
  583.         {
  584.             // если код текущего пакета меньше либо равен последнему полученному
  585.             // или больше глобального то игнорируем пакет
  586.  
  587.             if ((RBUFW(SmallPD_ptr, 2) <= map_session_data->client_packet_id) ||
  588.                 (RBUFW(SmallPD_ptr, 2) > SmallPD_Code))
  589.             {
  590.                 continue;
  591.             }
  592.             if (SmallPD_Type != 0x15)
  593.             {
  594.                 ShowInfo("parse: %03hX | %04hX %04hX %02hX from user: %s\n", SmallPD_Type, RBUFW(SmallPD_ptr, 2), RBUFW(buff, 2), SmallPD_Size, PChar->GetName());
  595.             }
  596.             if (PChar->loc.zone == nullptr && SmallPD_Type != 0x0A)
  597.             {
  598.                 ShowWarning("This packet is unexpected from %s - Received %03hX earlier without matching 0x0A\n", PChar->GetName(), SmallPD_Type);
  599.             }
  600.             else
  601.             {
  602.                 PacketParser[SmallPD_Type](map_session_data, PChar, CBasicPacket(reinterpret_cast<uint8*>(SmallPD_ptr)));
  603.             }
  604.         }
  605.         else
  606.         {
  607.             ShowWarning("Bad packet size %03hX | %04hX %04hX %02hX from user: %s\n", SmallPD_Type, RBUFW(SmallPD_ptr, 2), RBUFW(buff, 2), SmallPD_Size, PChar->GetName());
  608.         }
  609.     }
  610.     map_session_data->client_packet_id = SmallPD_Code;
  611.  
  612.     // здесь мы проверяем, получил ли клиент предыдущий пакет
  613.     // если не получил, то мы не создаем новый, а отправляем предыдущий
  614.  
  615.     if (RBUFW(buff, 2) != map_session_data->server_packet_id)
  616.     {
  617.         WBUFW(map_session_data->server_packet_data, 2) = SmallPD_Code;
  618.         WBUFW(map_session_data->server_packet_data, 8) = (uint32)time(nullptr);
  619.  
  620.         g_PBuff = map_session_data->server_packet_data;
  621.         *buffsize = map_session_data->server_packet_size;
  622.  
  623.         map_session_data->server_packet_data = buff;
  624.         return -1;
  625.     }
  626.  
  627.     // увеличиваем номер отправленного пакета только в случае отправки новых данных
  628.  
  629.     map_session_data->server_packet_id += 1;
  630.  
  631.     return 0;
  632. }
  633.  
  634. /************************************************************************
  635. *                                                                       *
  636. *  main function is building big packet                                 *
  637. *                                                                       *
  638. ************************************************************************/
  639.  
  640. int32 send_parse(int8 *buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data)
  641. {
  642.     // Модификация заголовка исходящего пакета
  643.     // Суть преобразований:
  644.     //  - отправить клиенту номер последнего полученного от него пакета
  645.     //  - присвоить исходящему пакету номер последнего отправленного клиенту пакета +1
  646.     //  - записать текущее время отправки пакета
  647.  
  648.     WBUFW(buff, 0) = map_session_data->server_packet_id;
  649.     WBUFW(buff, 2) = map_session_data->client_packet_id;
  650.  
  651.     // сохранение текущего времени (32 BIT!)
  652.     WBUFL(buff, 8) = (uint32)time(nullptr);
  653.  
  654.     // собираем большой пакет, состоящий из нескольких маленьких
  655.     CCharEntity *PChar = map_session_data->PChar;
  656.     CBasicPacket* PSmallPacket;
  657.     uint32 PacketSize = UINT32_MAX;
  658.     uint32 PacketCount = PChar->getPacketCount();
  659.     uint8 packets = 0;
  660.  
  661.     while (PacketSize > 1300 - FFXI_HEADER_SIZE - 16) //max size for client to accept
  662.     {
  663.         *buffsize = FFXI_HEADER_SIZE;
  664.         PacketList_t packetList = PChar->getPacketList();
  665.         packets = 0;
  666.  
  667.         while (!packetList.empty() && *buffsize + packetList.front()->length() < map_config.buffer_size &&
  668.             packets < PacketCount)
  669.         {
  670.             PSmallPacket = packetList.front();
  671.  
  672.             PSmallPacket->sequence(map_session_data->server_packet_id);
  673.             memcpy(buff + *buffsize, *PSmallPacket, PSmallPacket->length());
  674.  
  675.             *buffsize += PSmallPacket->length();
  676.             packetList.pop_front();
  677.             packets++;
  678.         }
  679.         //Сжимаем данные без учета заголовка
  680.         //Возвращаемый размер в 8 раз больше реальных данных
  681.         PacketSize = zlib_compress(buff + FFXI_HEADER_SIZE, *buffsize - FFXI_HEADER_SIZE, PTempBuff, *buffsize);
  682.         WBUFL(PTempBuff, zlib_compressed_size(PacketSize)) = PacketSize;
  683.  
  684.         PacketSize = zlib_compressed_size(PacketSize) + 4;
  685.  
  686.         PacketCount /= 2;
  687.     }
  688.     PChar->erasePackets(packets);
  689.  
  690.     //Запись размера данных без учета заголовка
  691.     uint8 hash[16];
  692.     md5((uint8*)PTempBuff, hash, PacketSize);
  693.     memcpy(PTempBuff + PacketSize, hash, 16);
  694.     PacketSize += 16;
  695.  
  696.     if (PacketSize > map_config.buffer_size + 20)
  697.     {
  698.         ShowFatalError(CL_RED"%Memory manager: PTempBuff is overflowed (%u)\n" CL_RESET, PacketSize);
  699.     }
  700.  
  701.     //making total packet
  702.     memcpy(buff + FFXI_HEADER_SIZE, PTempBuff, PacketSize);
  703.  
  704.     uint32 CypherSize = (PacketSize / 4)&-2;
  705.  
  706.     blowfish_t* pbfkey = &map_session_data->blowfish;
  707.  
  708.     for (uint32 j = 0; j < CypherSize; j += 2)
  709.     {
  710.         blowfish_encipher((uint32*)(buff)+j + 7, (uint32*)(buff)+j + 8, pbfkey->P, pbfkey->S[0]);
  711.     }
  712.  
  713.     // контролируем размер отправляемого пакета. в случае,
  714.     // если его размер превышает 1400 байт (размер данных + 42 байта IP заголовок),
  715.     // то клиент игнорирует пакет и возвращает сообщение о его потере
  716.  
  717.     // в случае возникновения подобной ситуации выводим предупреждующее сообщение и
  718.     // уменьшаем размер BuffMaxSize с шагом в 4 байта до ее устранения (вручную)
  719.  
  720.     *buffsize = PacketSize + FFXI_HEADER_SIZE;
  721.  
  722.     return 0;
  723. }
  724.  
  725. /************************************************************************
  726. *                                                                       *
  727. *  Таймер для завершения сессии (без таймера мы этого сделать не можем, *
  728. *  т.к. сессия продолжает использоваться в do_sockets)                  *
  729. *                                                                       *
  730. ************************************************************************/
  731.  
  732. int32 map_close_session(time_point tick, map_session_data_t* map_session_data)
  733. {
  734.     if (map_session_data != nullptr &&
  735.         map_session_data->server_packet_data != nullptr &&
  736.         map_session_data->PChar != nullptr)
  737.     {
  738.         charutils::SavePlayTime(map_session_data->PChar);
  739.  
  740.         //clear accounts_sessions if character is logging out (not when zoning)
  741.         if (map_session_data->shuttingDown == 1)
  742.         {
  743.             Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE charid = %u", map_session_data->PChar->id);
  744.         }
  745.  
  746.         uint64 port64 = map_session_data->client_port;
  747.         uint64 ipp = map_session_data->client_addr;
  748.         ipp |= port64 << 32;
  749.  
  750.         map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(map_session_data->shuttingDown == 1);
  751.  
  752.         aFree(map_session_data->server_packet_data);
  753.         delete map_session_data->PChar;
  754.         delete map_session_data;
  755.         map_session_data = nullptr;
  756.  
  757.         map_session_list.erase(ipp);
  758.         return 0;
  759.     }
  760.  
  761.     ShowError(CL_RED"map_close_session: cannot close session, session not found\n" CL_RESET);
  762.     return 1;
  763. }
  764.  
  765. /************************************************************************
  766. *                                                                       *
  767. *  Timer function that clenup all timed out players                     *
  768. *                                                                       *
  769. ************************************************************************/
  770.  
  771. int32 map_cleanup(time_point tick, CTaskMgr::CTask* PTask)
  772. {
  773.     map_session_list_t::iterator it = map_session_list.begin();
  774.  
  775.     while (it != map_session_list.end())
  776.     {
  777.         map_session_data_t* map_session_data = it->second;
  778.  
  779.         CCharEntity* PChar = map_session_data->PChar;
  780.  
  781.         if ((time(nullptr) - map_session_data->last_update) > 5)
  782.         {
  783.             if (PChar != nullptr && !(PChar->nameflags.flags & FLAG_DC))
  784.             {
  785.  
  786.                 PChar->nameflags.flags |= FLAG_DC;
  787.                 PChar->updatemask |= UPDATE_HP;
  788.                 if (PChar->status == STATUS_NORMAL)
  789.                 {
  790.                     PChar->loc.zone->SpawnPCs(PChar);
  791.                 }
  792.             }
  793.             if ((time(nullptr) - map_session_data->last_update) > map_config.max_time_lastupdate)
  794.             {
  795.                 if (PChar != nullptr)
  796.                 {
  797.                     if (map_session_data->shuttingDown == 0)
  798.                     {
  799.                         //[Alliance] fix to stop server crashing:
  800.                         //if a party within an alliance only has 1 char (that char will be party leader)
  801.                         //if char then disconnects we need to tell the server about the alliance change
  802.                         if (PChar->PParty != nullptr && PChar->PParty->m_PAlliance != nullptr && PChar->PParty->GetLeader() == PChar)
  803.                         {
  804.                             if (PChar->PParty->members.size() == 1)
  805.                             {
  806.                                 if (PChar->PParty->m_PAlliance->partyList.size() == 1)
  807.                                 {
  808.                                     PChar->PParty->m_PAlliance->dissolveAlliance();
  809.                                 }
  810.                                 else
  811.                                 {
  812.                                     PChar->PParty->m_PAlliance->removeParty(PChar->PParty);
  813.                                 }
  814.                             }
  815.                         }
  816.  
  817.  
  818.                         // uncharm pet if player d/c
  819.                         if (PChar->PPet != nullptr && PChar->PPet->objtype == TYPE_MOB)
  820.                         {
  821.                             petutils::DespawnPet(PChar);
  822.                         }
  823.  
  824.                         PChar->StatusEffectContainer->SaveStatusEffects(true);
  825.                         charutils::SaveCharPosition(PChar);
  826.  
  827.                         ShowDebug(CL_CYAN"map_cleanup: %s timed out, closing session\n" CL_RESET, PChar->GetName());
  828.  
  829.                         PChar->status = STATUS_SHUTDOWN;
  830.                         PacketParser[0x00D](map_session_data, PChar, 0);
  831.                     }
  832.                     else
  833.                     {
  834.                         map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(true);
  835.                         Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE charid = %u;", map_session_data->PChar->id);
  836.  
  837.                         aFree(map_session_data->server_packet_data);
  838.                         delete map_session_data->PChar;
  839.                         delete map_session_data;
  840.                         map_session_data = nullptr;
  841.  
  842.                         map_session_list.erase(it++);
  843.                         continue;
  844.                     }
  845.                 }
  846.                 else if (map_session_data->shuttingDown == 0)
  847.                 {
  848.  
  849.                     ShowWarning(CL_YELLOW"map_cleanup: WHITHOUT CHAR timed out, session closed\n" CL_RESET);
  850.  
  851.                     const int8* Query = "DELETE FROM accounts_sessions WHERE client_addr = %u AND client_port = %u";
  852.                     Sql_Query(SqlHandle, Query, map_session_data->client_addr, map_session_data->client_port);
  853.  
  854.                     aFree(map_session_data->server_packet_data);
  855.                     map_session_list.erase(it++);
  856.                     delete map_session_data;
  857.                     continue;
  858.                 }
  859.             }
  860.         }
  861.         else if (PChar != nullptr && (PChar->nameflags.flags & FLAG_DC))
  862.         {
  863.             PChar->nameflags.flags &= ~FLAG_DC;
  864.             PChar->updatemask |= UPDATE_HP;
  865.  
  866.             if (PChar->status == STATUS_NORMAL)
  867.             {
  868.                 PChar->loc.zone->SpawnPCs(PChar);
  869.             }
  870.             charutils::SaveCharStats(PChar);
  871.         }
  872.         ++it;
  873.     }
  874.     return 0;
  875. }
  876.  
  877. /************************************************************************
  878. *                                                                       *
  879. *  Map-Server Version Screen [venom]                                    *
  880. *                                                                       *
  881. ************************************************************************/
  882.  
  883. void map_helpscreen(int32 flag)
  884. {
  885.     ShowMessage("Usage: map-server [options]\n");
  886.     ShowMessage("Options:\n");
  887.     ShowMessage(CL_WHITE"  Commands\t\t\tDescription\n" CL_RESET);
  888.     ShowMessage("-----------------------------------------------------------------------------\n");
  889.     ShowMessage("  --help, --h, --?, /?     Displays this help screen\n");
  890.     ShowMessage("  --map-config <file>      Load map-server configuration from <file>\n");
  891.     ShowMessage("  --version, --v, -v, /v   Displays the server's version\n");
  892.     ShowMessage("\n");
  893.     if (flag)
  894.     {
  895.         exit(EXIT_FAILURE);
  896.     }
  897. }
  898.  
  899. /************************************************************************
  900. *                                                                       *
  901. *  Map-Server Version Screen [venom]                                    *
  902. *                                                                       *
  903. ************************************************************************/
  904.  
  905. void map_versionscreen(int32 flag)
  906. {
  907.     ShowInfo(CL_WHITE "Darkstar version %d.%02d.%02d" CL_RESET"\n",
  908.         DARKSTAR_MAJOR_VERSION, DARKSTAR_MINOR_VERSION, DARKSTAR_REVISION);
  909.     if (flag)
  910.     {
  911.         exit(EXIT_FAILURE);
  912.     }
  913. }
  914.  
  915. /************************************************************************
  916. *                                                                       *
  917. *  map_config_default                                                   *
  918. *                                                                       *
  919. ************************************************************************/
  920.  
  921. int32 map_config_default()
  922. {
  923.     map_config.uiMapIp = INADDR_ANY;
  924.     map_config.usMapPort = 54230;
  925.     map_config.mysql_host = "127.0.0.1";
  926.     map_config.mysql_login = "root";
  927.     map_config.mysql_password = "root";
  928.     map_config.mysql_database = "dspdb";
  929.     map_config.mysql_port = 3306;
  930.     map_config.server_message = "";
  931.     map_config.server_message_fr = "";
  932.     map_config.buffer_size = 1800;
  933.     map_config.ah_base_fee_single = 1;
  934.     map_config.ah_base_fee_stacks = 4;
  935.     map_config.ah_tax_rate_single = 1.0;
  936.     map_config.ah_tax_rate_stacks = 0.5;
  937.     map_config.ah_max_fee = 10000;
  938.     map_config.exp_rate = 1.0f;
  939.     map_config.exp_loss_rate = 1.0f;
  940.     map_config.exp_retain = 0.0f;
  941.     map_config.exp_loss_level = 4;
  942.     map_config.level_sync_enable = 0;
  943.     map_config.all_jobs_widescan = 1;
  944.     map_config.speed_mod = 0;
  945.     map_config.mob_speed_mod = 0;
  946.     map_config.skillup_chance_multiplier = 2.5f;
  947.     map_config.craft_chance_multiplier = 2.6f;
  948.     map_config.skillup_amount_multiplier = 1;
  949.     map_config.craft_amount_multiplier = 1;
  950.     map_config.craft_day_matters = 1;
  951.     map_config.craft_moonphase_matters = 0;
  952.     map_config.craft_direction_matters = 0;
  953.     map_config.mob_tp_multiplier = 1.0f;
  954.     map_config.player_tp_multiplier = 1.0f;
  955.     map_config.nm_hp_multiplier = 1.0f;
  956.     map_config.mob_hp_multiplier = 1.0f;
  957.     map_config.player_hp_multiplier = 1.0f;
  958.     map_config.nm_mp_multiplier = 1.0f;
  959.     map_config.mob_mp_multiplier = 1.0f;
  960.     map_config.player_mp_multiplier = 1.0f;
  961.     map_config.sj_mp_divisor = 2.0f;
  962.     map_config.nm_stat_multiplier = 1.0f;
  963.     map_config.mob_stat_multiplier = 1.0f;
  964.     map_config.player_stat_multiplier = 1.0f;
  965.     map_config.vanadiel_time_offset = 0;
  966.     map_config.lightluggage_block = 4;
  967.     map_config.max_time_lastupdate = 60000;
  968.     map_config.newstyle_skillups = 7;
  969.     map_config.drop_rate_multiplier = 1.0f;
  970.     map_config.all_mobs_gil_bonus = 0;
  971.     map_config.max_gil_bonus = 9999;
  972.     map_config.Battle_cap_tweak = 0;
  973.     map_config.CoP_Battle_cap = 1;
  974.     map_config.max_merit_points = 30;
  975.     map_config.yell_cooldown = 30;
  976.     map_config.audit_chat = 0;
  977.     map_config.audit_say = 0;
  978.     map_config.audit_shout = 0;
  979.     map_config.audit_tell = 0;
  980.     map_config.audit_yell = 0;
  981.     map_config.audit_party = 0;
  982.     map_config.audit_linkshell = 0;
  983.     map_config.msg_server_port = 54003;
  984.     map_config.msg_server_ip = "127.0.0.1";
  985.     map_config.healing_tick_delay = 10;
  986.     return 0;
  987. }
  988.  
  989. /************************************************************************
  990. *                                                                       *
  991. *  Map-Server Config [venom]                                            *
  992. *                                                                       *
  993. ************************************************************************/
  994.  
  995. int32 map_config_read(const int8* cfgName)
  996. {
  997.     int8 line[1024], w1[1024], w2[1024];
  998.     FILE* fp;
  999.  
  1000.     fp = fopen(cfgName, "r");
  1001.     if (fp == nullptr)
  1002.     {
  1003.         ShowError("Map configuration file not found at: %s\n", cfgName);
  1004.         return 1;
  1005.     }
  1006.  
  1007.     while (fgets(line, sizeof(line), fp))
  1008.     {
  1009.         int8* ptr;
  1010.  
  1011.         if (line[0] == '#')
  1012.         {
  1013.             continue;
  1014.         }
  1015.         if (sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2)
  1016.         {
  1017.             continue;
  1018.         }
  1019.  
  1020.         //Strip trailing spaces
  1021.         ptr = w2 + strlen(w2);
  1022.         while (--ptr >= w2 && *ptr == ' ');
  1023.         ptr++;
  1024.         *ptr = '\0';
  1025.  
  1026.         if (strcmpi(w1, "timestamp_format") == 0)
  1027.         {
  1028.             strncpy(timestamp_format, w2, 20);
  1029.         }
  1030.         else if (strcmpi(w1, "stdout_with_ansisequence") == 0)
  1031.         {
  1032.             stdout_with_ansisequence = config_switch(w2);
  1033.         }
  1034.         else if (strcmpi(w1, "console_silent") == 0)
  1035.         {
  1036.             ShowInfo("Console Silent Setting: %d", atoi(w2));
  1037.             msg_silent = atoi(w2);
  1038.         }
  1039.         else if (strcmpi(w1, "map_port") == 0)
  1040.         {
  1041.             map_config.usMapPort = (atoi(w2));
  1042.         }
  1043.         else if (strcmp(w1, "buff_maxsize") == 0)
  1044.         {
  1045.             map_config.buffer_size = atoi(w2);
  1046.         }
  1047.         else if (strcmp(w1, "max_time_lastupdate") == 0)
  1048.         {
  1049.             map_config.max_time_lastupdate = atoi(w2);
  1050.         }
  1051.         else if (strcmp(w1, "vanadiel_time_offset") == 0)
  1052.         {
  1053.             map_config.vanadiel_time_offset = atoi(w2);
  1054.         }
  1055.         else if (strcmp(w1, "fame_multiplier") == 0)
  1056.         {
  1057.             map_config.fame_multiplier = atof(w2);
  1058.         }
  1059.         else if (strcmp(w1, "lightluggage_block") == 0)
  1060.         {
  1061.             map_config.lightluggage_block = atoi(w2);
  1062.         }
  1063.         else if (strcmp(w1, "ah_base_fee_single") == 0)
  1064.         {
  1065.             map_config.ah_base_fee_single = atoi(w2);
  1066.         }
  1067.         else if (strcmp(w1, "ah_base_fee_stacks") == 0)
  1068.         {
  1069.             map_config.ah_base_fee_stacks = atoi(w2);
  1070.         }
  1071.         else if (strcmp(w1, "ah_tax_rate_single") == 0)
  1072.         {
  1073.             map_config.ah_tax_rate_single = atof(w2);
  1074.         }
  1075.         else if (strcmp(w1, "ah_tax_rate_stacks") == 0)
  1076.         {
  1077.             map_config.ah_tax_rate_stacks = atof(w2);
  1078.         }
  1079.         else if (strcmp(w1, "ah_max_fee") == 0)
  1080.         {
  1081.             map_config.ah_max_fee = atoi(w2);
  1082.         }
  1083.         else if (strcmp(w1, "exp_rate") == 0)
  1084.         {
  1085.             map_config.exp_rate = atof(w2);
  1086.         }
  1087.         else if (strcmp(w1, "exp_loss_rate") == 0)
  1088.         {
  1089.             map_config.exp_loss_rate = atof(w2);
  1090.         }
  1091.         else if (strcmp(w1, "exp_party_gap_penalties") == 0)
  1092.         {
  1093.             map_config.exp_party_gap_penalties = atof(w2);
  1094.         }
  1095.         else if (strcmp(w1, "fov_party_gap_penalties") == 0)
  1096.         {
  1097.             map_config.fov_party_gap_penalties = atof(w2);
  1098.         }
  1099.         else if (strcmp(w1, "fov_allow_alliance") == 0)
  1100.         {
  1101.             map_config.fov_allow_alliance = atof(w2);
  1102.         }
  1103.         else if (strcmp(w1, "mob_tp_multiplier") == 0)
  1104.         {
  1105.             map_config.mob_tp_multiplier = atof(w2);
  1106.         }
  1107.         else if (strcmp(w1, "player_tp_multiplier") == 0)
  1108.         {
  1109.             map_config.player_tp_multiplier = atof(w2);
  1110.         }
  1111.         else if (strcmp(w1, "nm_hp_multiplier") == 0)
  1112.         {
  1113.             map_config.nm_hp_multiplier = atof(w2);
  1114.         }
  1115.         else if (strcmp(w1, "mob_hp_multiplier") == 0)
  1116.         {
  1117.             map_config.mob_hp_multiplier = atof(w2);
  1118.         }
  1119.         else if (strcmp(w1, "player_hp_multiplier") == 0)
  1120.         {
  1121.             map_config.player_hp_multiplier = atof(w2);
  1122.         }
  1123.         else if (strcmp(w1, "nm_mp_multiplier") == 0)
  1124.         {
  1125.             map_config.nm_mp_multiplier = atof(w2);
  1126.         }
  1127.         else if (strcmp(w1, "mob_mp_multiplier") == 0)
  1128.         {
  1129.             map_config.mob_mp_multiplier = atof(w2);
  1130.         }
  1131.         else if (strcmp(w1, "player_mp_multiplier") == 0)
  1132.         {
  1133.             map_config.player_mp_multiplier = atof(w2);
  1134.         }
  1135.         else if (strcmp(w1, "sj_mp_divisor") == 0)
  1136.         {
  1137.             map_config.sj_mp_divisor = atof(w2);
  1138.         }
  1139.         else if (strcmp(w1, "nm_stat_multiplier") == 0)
  1140.         {
  1141.             map_config.nm_stat_multiplier = atof(w2);
  1142.         }
  1143.         else if (strcmp(w1, "mob_stat_multiplier") == 0)
  1144.         {
  1145.             map_config.mob_stat_multiplier = atof(w2);
  1146.         }
  1147.         else if (strcmp(w1, "player_stat_multiplier") == 0)
  1148.         {
  1149.             map_config.player_stat_multiplier = atof(w2);
  1150.         }
  1151.         else if (strcmp(w1, "drop_rate_multiplier") == 0)
  1152.         {
  1153.             map_config.drop_rate_multiplier = atof(w2);
  1154.         }
  1155.         else if (strcmp(w1, "all_mobs_gil_bonus") == 0)
  1156.         {
  1157.             map_config.all_mobs_gil_bonus = atoi(w2);
  1158.         }
  1159.         else if (strcmp(w1, "max_gil_bonus") == 0)
  1160.         {
  1161.             map_config.max_gil_bonus = atoi(w2);
  1162.         }
  1163.         else if (strcmp(w1, "exp_retain") == 0)
  1164.         {
  1165.             map_config.exp_retain = dsp_cap(atof(w2), 0.0f, 1.0f);
  1166.         }
  1167.         else if (strcmp(w1, "exp_loss_level") == 0)
  1168.         {
  1169.             map_config.exp_loss_level = atoi(w2);
  1170.         }
  1171.         else if (strcmp(w1, "level_sync_enable") == 0)
  1172.         {
  1173.             map_config.level_sync_enable = atoi(w2);
  1174.         }
  1175.         else if (strcmp(w1, "all_jobs_widescan") == 0)
  1176.         {
  1177.             map_config.all_jobs_widescan = atoi(w2);
  1178.         }
  1179.         else if (strcmp(w1, "speed_mod") == 0)
  1180.         {
  1181.             map_config.speed_mod = atoi(w2);
  1182.         }
  1183.         else if (strcmp(w1, "mob_speed_mod") == 0)
  1184.         {
  1185.             map_config.mob_speed_mod = atoi(w2);
  1186.         }
  1187.         else if (strcmp(w1, "skillup_chance_multiplier") == 0)
  1188.         {
  1189.             map_config.skillup_chance_multiplier = atof(w2);
  1190.         }
  1191.         else if (strcmp(w1, "craft_chance_multiplier") == 0)
  1192.         {
  1193.             map_config.craft_chance_multiplier = atof(w2);
  1194.         }
  1195.         else if (strcmp(w1, "skillup_amount_multiplier") == 0)
  1196.         {
  1197.             map_config.skillup_amount_multiplier = atof(w2);
  1198.         }
  1199.         else if (strcmp(w1, "craft_amount_multiplier") == 0)
  1200.         {
  1201.             map_config.craft_amount_multiplier = atof(w2);
  1202.         }
  1203.         else if (strcmp(w1, "craft_day_matters") == 0)
  1204.         {
  1205.             map_config.craft_day_matters = atof(w2);
  1206.         }
  1207.         else if (strcmp(w1, "craft_moonphase_matters") == 0)
  1208.         {
  1209.             map_config.craft_moonphase_matters = atof(w2);
  1210.         }
  1211.         else if (strcmp(w1, "craft_direction_matters") == 0)
  1212.         {
  1213.             map_config.craft_direction_matters = atof(w2);
  1214.         }
  1215.         else if (strcmp(w1, "mysql_host") == 0)
  1216.         {
  1217.             map_config.mysql_host = aStrdup(w2);
  1218.         }
  1219.         else if (strcmp(w1, "mysql_login") == 0)
  1220.         {
  1221.             map_config.mysql_login = aStrdup(w2);
  1222.         }
  1223.         else if (strcmp(w1, "mysql_password") == 0)
  1224.         {
  1225.             map_config.mysql_password = aStrdup(w2);
  1226.         }
  1227.         else if (strcmp(w1, "mysql_port") == 0)
  1228.         {
  1229.             map_config.mysql_port = atoi(w2);
  1230.         }
  1231.         else if (strcmp(w1, "mysql_database") == 0)
  1232.         {
  1233.             map_config.mysql_database = aStrdup(w2);
  1234.         }
  1235.         else if (strcmpi(w1, "import") == 0)
  1236.         {
  1237.             map_config_read(w2);
  1238.         }
  1239.         else if (strcmpi(w1, "newstyle_skillups") == 0)
  1240.         {
  1241.             map_config.newstyle_skillups = atoi(w2);
  1242.         }
  1243.         else if (strcmp(w1, "Battle_cap_tweak") == 0)
  1244.         {
  1245.             map_config.Battle_cap_tweak = atoi(w2);
  1246.         }
  1247.         else if (strcmp(w1, "CoP_Battle_cap") == 0)
  1248.         {
  1249.             map_config.CoP_Battle_cap = atoi(w2);
  1250.         }
  1251.         else if (strcmp(w1, "max_merit_points") == 0)
  1252.         {
  1253.             map_config.max_merit_points = atoi(w2);
  1254.         }
  1255.         else if (strcmp(w1, "yell_cooldown") == 0)
  1256.         {
  1257.             map_config.yell_cooldown = atoi(w2);
  1258.         }
  1259.         else if (strcmp(w1, "audit_chat") == 0)
  1260.         {
  1261.             map_config.audit_chat = atoi(w2);
  1262.         }
  1263.         else if (strcmp(w1, "audit_say") == 0)
  1264.         {
  1265.             map_config.audit_say = atoi(w2);
  1266.         }
  1267.         else if (strcmp(w1, "audit_shout") == 0)
  1268.         {
  1269.             map_config.audit_shout = atoi(w2);
  1270.         }
  1271.         else if (strcmp(w1, "audit_tell") == 0)
  1272.         {
  1273.             map_config.audit_tell = atoi(w2);
  1274.         }
  1275.         else if (strcmp(w1, "audit_yell") == 0)
  1276.         {
  1277.             map_config.audit_yell = atoi(w2);
  1278.         }
  1279.         else if (strcmp(w1, "audit_linkshell") == 0)
  1280.         {
  1281.             map_config.audit_linkshell = atoi(w2);
  1282.         }
  1283.         else if (strcmp(w1, "audit_party") == 0)
  1284.         {
  1285.             map_config.audit_party = atoi(w2);
  1286.         }
  1287.         else if (strcmp(w1, "msg_server_port") == 0)
  1288.         {
  1289.             map_config.msg_server_port = atoi(w2);
  1290.         }
  1291.         else if (strcmp(w1, "msg_server_ip") == 0)
  1292.         {
  1293.             map_config.msg_server_ip = aStrdup(w2);
  1294.         }
  1295.         else if (strcmp(w1, "mob_no_despawn") == 0)
  1296.         {
  1297.             map_config.mob_no_despawn = atoi(w2);
  1298.         }
  1299.         else if (strcmp(w1, "healing_tick_delay") == 0)
  1300.         {
  1301.             map_config.healing_tick_delay = atoi(w2);
  1302.         }
  1303.         else
  1304.         {
  1305.             ShowWarning(CL_YELLOW"Unknown setting '%s' in file %s\n" CL_RESET, w1, cfgName);
  1306.         }
  1307.     }
  1308.  
  1309.     fclose(fp);
  1310.  
  1311.     // Load the English server message..
  1312.     fp = fopen("./conf/server_message.conf", "rb");
  1313.     if (fp == nullptr)
  1314.     {
  1315.         ShowError("Could not read English server message from: ./conf/server_message.conf\n");
  1316.         return 1;
  1317.     }
  1318.  
  1319.     while (fgets(line, sizeof(line), fp))
  1320.     {
  1321.         string_t sline(line);
  1322.         map_config.server_message += sline;
  1323.     }
  1324.  
  1325.     fclose(fp);
  1326.  
  1327.     // Load the French server message..
  1328.     fp = fopen("./conf/server_message_fr.conf", "rb");
  1329.     if (fp == nullptr)
  1330.     {
  1331.         ShowError("Could not read English server message from: ./conf/server_message_fr.conf\n");
  1332.         return 1;
  1333.     }
  1334.  
  1335.     while (fgets(line, sizeof(line), fp))
  1336.     {
  1337.         string_t sline(line);
  1338.         map_config.server_message_fr += sline;
  1339.     }
  1340.  
  1341.     fclose(fp);
  1342.  
  1343.     // Ensure both messages have nullptr terminates..
  1344.     if (map_config.server_message.at(map_config.server_message.length() - 1) != 0x00)
  1345.     {
  1346.         map_config.server_message += (char)0x00;
  1347.     }
  1348.     if (map_config.server_message_fr.at(map_config.server_message_fr.length() - 1) != 0x00)
  1349.     {
  1350.         map_config.server_message_fr += (char)0x00;
  1351.     }
  1352.  
  1353.     return 0;
  1354. }
  1355.  
  1356. int32 map_garbage_collect(time_point tick, CTaskMgr::CTask* PTask)
  1357. {
  1358.     luautils::garbageCollect();
  1359.     return 0;
  1360. }
  1361.  
  1362. void log_init(int argc, char** argv)
  1363. {
  1364.     std::string logFile;
  1365. #ifdef DEBUGLOGMAP
  1366. #ifdef WIN32
  1367.     logFile = "log\\map-server.log";
  1368. #else
  1369.     logFile = "log/map-server.log";
  1370. #endif
  1371. #endif
  1372.     bool defaultname = true;
  1373.     for (int i = 1; i < argc; i++)
  1374.     {
  1375.         if (strcmp(argv[i], "--ip") == 0 && defaultname)
  1376.         {
  1377.             logFile = argv[i + 1];
  1378.         }
  1379.         else if (strcmp(argv[i], "--port") == 0 && defaultname)
  1380.         {
  1381.             logFile.append(argv[i + 1]);
  1382.         }
  1383.         else if (strcmp(argv[i], "--log") == 0)
  1384.         {
  1385.             defaultname = false;
  1386.             logFile = argv[i + 1];
  1387.         }
  1388.     }
  1389.     InitializeLog(logFile);
  1390. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement