Guest User

Untitled

a guest
Jan 2nd, 2017
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 51.83 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. ////////////////////////////////////////////////////////////////////////
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ////////////////////////////////////////////////////////////////////////
  17.  
  18. #include "otpch.h"
  19. #include "otsystem.h"
  20. #include <signal.h>
  21.  
  22. #include <iostream>
  23. #include <fstream>
  24. #include <iomanip>
  25.  
  26. #if defined(WINDOWS) && !defined(_CONSOLE)
  27. #include "shellapi.h"
  28. #include "gui.h"
  29. #include "inputbox.h"
  30. #include "commctrl.h"
  31. #else
  32. #include "resources.h"
  33. #endif
  34.  
  35. #ifndef WINDOWS
  36. #include <unistd.h>
  37. #include <termios.h>
  38. #else
  39. #include <conio.h>
  40. #endif
  41.  
  42. #include <boost/config.hpp>
  43. #ifdef _MULTIPLATFORM77
  44. #include <openssl/rsa.h>
  45. #include <openssl/bn.h>
  46. #include <openssl/err.h>
  47. #endif
  48. #include "server.h"
  49. #ifdef __LOGIN_SERVER__
  50. #include "gameservers.h"
  51. #endif
  52. #include "networkmessage.h"
  53.  
  54. #include "game.h"
  55. #include "chat.h"
  56. #include "tools.h"
  57.  
  58. #include "protocollogin.h"
  59. #include "protocolgame.h"
  60.  
  61. #include "status.h"
  62.  
  63. #include "configmanager.h"
  64. #include "scriptmanager.h"
  65. #include "databasemanager.h"
  66.  
  67. #include "iologindata.h"
  68. #include "ioban.h"
  69.  
  70. #include "outfit.h"
  71. #include "vocation.h"
  72. #include "group.h"
  73.  
  74. #include "raids.h"
  75.  
  76. #include "monsters.h"
  77. #ifdef __EXCEPTION_TRACER__
  78. #include "exception.h"
  79. #endif
  80. #include "textlogger.h"
  81.  
  82. #ifdef __NO_BOOST_EXCEPTIONS__
  83. #include <exception>
  84.  
  85. inline void boost::throw_exception(std::exception const & e)
  86. {
  87. std::clog << "Boost exception: " << e.what() << std::endl;
  88. }
  89. #endif
  90. #ifdef _MULTIPLATFORM77
  91. RSA* g_RSA;
  92. #endif
  93. ConfigManager g_config;
  94. Game g_game;
  95. Chat g_chat;
  96.  
  97. #if defined(WINDOWS) && !defined(_CONSOLE)
  98. GUILogger g_logger;
  99. NOTIFYICONDATA NID;
  100. #endif
  101.  
  102. Monsters g_monsters;
  103. Npcs g_npcs;
  104.  
  105. boost::mutex g_loaderLock;
  106. boost::condition_variable g_loaderSignal;
  107. boost::unique_lock<boost::mutex> g_loaderUniqueLock(g_loaderLock);
  108. std::list<std::pair<uint32_t, uint32_t> > serverIps;
  109.  
  110. #if !defined(WINDOWS) || defined(_CONSOLE)
  111. bool argumentsHandler(StringVec args)
  112. {
  113. StringVec tmp;
  114. for(StringVec::iterator it = args.begin(); it != args.end(); ++it)
  115. {
  116. if((*it) == "--help")
  117. {
  118. std::clog << "Usage:\n"
  119. "\n"
  120. "\t--config=$1\t\tAlternate configuration file path.\n"
  121. "\t--data-directory=$1\tAlternate data directory path.\n"
  122. "\t--ip=$1\t\t\tIP address of the server.\n"
  123. "\t\t\t\tShould be equal to the global IP.\n"
  124. "\t--login-port=$1\tPort for login server to listen on.\n"
  125. "\t--game-port=$1\tPort for game server to listen on.\n"
  126. "\t--admin-port=$1\tPort for admin server to listen on.\n"
  127. "\t--manager-port=$1\tPort for manager server to listen on.\n"
  128. "\t--status-port=$1\tPort for status server to listen on.\n";
  129. #ifndef WINDOWS
  130. std::clog << "\t--runfile=$1\t\tSpecifies run file. Will contain the pid\n"
  131. "\t\t\t\tof the server process as long as run status.\n";
  132. #endif
  133. std::clog << "\t--log=$1\t\tWhole standard output will be logged to\n"
  134. "\t\t\t\tthis file.\n"
  135. "\t--closed\t\t\tStarts the server as closed.\n"
  136. "\t--no-script\t\t\tStarts the server without script system.\n";
  137. return false;
  138. }
  139.  
  140. if((*it) == "--version" || (*it) == "-v")
  141. {
  142. std::clog << "The " << SOFTWARE_NAME << " Version: (" << SOFTWARE_VERSION << "." << MINOR_VERSION << ") - Codename: (" << SOFTWARE_CODENAME << ")\n"
  143. "Compiled with " << BOOST_COMPILER << " for arch "
  144. #if defined(__amd64__) || defined(_M_X64)
  145. "64 Bits"
  146. #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_)
  147. "32 Bits"
  148. #else
  149. "unk"
  150. #endif
  151. " at " << __DATE__ << " " << __TIME__ << "\n"
  152.  
  153. "\n"
  154. "A server developed by: " SOFTWARE_DEVELOPERS ".\n"
  155. "Visit for updates, support, and resources: " GIT_REPO "\n";
  156. return false;
  157. }
  158.  
  159. tmp = explodeString((*it), "=");
  160. if(tmp[0] == "--config")
  161. g_config.setString(ConfigManager::CONFIG_FILE, tmp[1]);
  162. else if(tmp[0] == "--data-directory")
  163. g_config.setString(ConfigManager::DATA_DIRECTORY, tmp[1]);
  164. else if(tmp[0] == "--logs-directory")
  165. g_config.setString(ConfigManager::LOGS_DIRECTORY, tmp[1]);
  166. else if(tmp[0] == "--ip")
  167. g_config.setString(ConfigManager::IP, tmp[1]);
  168. else if(tmp[0] == "--login-port")
  169. g_config.setNumber(ConfigManager::LOGIN_PORT, atoi(tmp[1].c_str()));
  170. else if(tmp[0] == "--game-port")
  171. g_config.setNumber(ConfigManager::GAME_PORT, atoi(tmp[1].c_str()));
  172. else if(tmp[0] == "--status-port")
  173. g_config.setNumber(ConfigManager::STATUS_PORT, atoi(tmp[1].c_str()));
  174. #ifndef WINDOWS
  175. else if(tmp[0] == "--runfile" || tmp[0] == "--run-file" || tmp[0] == "--pidfile" || tmp[0] == "--pid-file")
  176. g_config.setString(ConfigManager::RUNFILE, tmp[1]);
  177. #endif
  178. else if(tmp[0] == "--log")
  179. g_config.setString(ConfigManager::OUTPUT_LOG, tmp[1]);
  180. #ifndef WINDOWS
  181. else if(tmp[0] == "--daemon" || tmp[0] == "-d")
  182. g_config.setBool(ConfigManager::DAEMONIZE, true);
  183. #endif
  184. else if(tmp[0] == "--closed")
  185. g_config.setBool(ConfigManager::START_CLOSED, true);
  186. else if(tmp[0] == "--no-script" || tmp[0] == "--noscript")
  187. g_config.setBool(ConfigManager::SCRIPT_SYSTEM, false);
  188. }
  189.  
  190. return true;
  191. }
  192. #endif
  193.  
  194. #ifndef WINDOWS
  195. int32_t OTSYS_getch()
  196. {
  197. struct termios oldt;
  198. tcgetattr(STDIN_FILENO, &oldt);
  199.  
  200. struct termios newt = oldt;
  201. newt.c_lflag &= ~(ICANON | ECHO);
  202. tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  203.  
  204. int32_t ch = getchar();
  205. tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  206. return ch;
  207. }
  208.  
  209. void signalHandler(int32_t sig)
  210. {
  211. switch(sig)
  212. {
  213. case SIGHUP:
  214. Dispatcher::getInstance().addTask(createTask(
  215. boost::bind(&Game::saveGameState, &g_game, (uint8_t)SAVE_PLAYERS | (uint8_t)SAVE_MAP | (uint8_t)SAVE_STATE)));
  216. break;
  217.  
  218. case SIGTRAP:
  219. g_game.cleanMap();
  220. break;
  221.  
  222. case SIGCHLD:
  223. g_game.proceduralRefresh();
  224. break;
  225.  
  226. case SIGUSR1:
  227. Dispatcher::getInstance().addTask(createTask(
  228. boost::bind(&Game::setGameState, &g_game, GAMESTATE_CLOSED)));
  229. break;
  230.  
  231. case SIGUSR2:
  232. g_game.setGameState(GAMESTATE_NORMAL);
  233. break;
  234.  
  235. case SIGCONT:
  236. Dispatcher::getInstance().addTask(createTask(
  237. boost::bind(&Game::reloadInfo, &g_game, RELOAD_ALL, 0, false)));
  238. break;
  239.  
  240. case SIGQUIT:
  241. Dispatcher::getInstance().addTask(createTask(
  242. boost::bind(&Game::setGameState, &g_game, GAMESTATE_SHUTDOWN)));
  243. break;
  244.  
  245. case SIGTERM:
  246. Dispatcher::getInstance().addTask(createTask(
  247. boost::bind(&Game::shutdown, &g_game)));
  248.  
  249. Dispatcher::getInstance().stop();
  250. Scheduler::getInstance().stop();
  251. break;
  252.  
  253. default:
  254. break;
  255. }
  256. }
  257.  
  258. void runfileHandler(void)
  259. {
  260. std::ofstream runfile(g_config.getString(ConfigManager::RUNFILE).c_str(), std::ios::trunc | std::ios::out);
  261. runfile.close();
  262. }
  263. #else
  264. int32_t OTSYS_getch()
  265. {
  266. return (int32_t)getchar();
  267. }
  268. #endif
  269.  
  270. void allocationHandler()
  271. {
  272. puts("Allocation failed, server out of memory!\nDecrease size of your map or compile in a 64-bit mode.");
  273. OTSYS_getch();
  274. std::exit(-1);
  275. }
  276.  
  277. void startupErrorMessage(std::string error = "")
  278. {
  279. // we will get a crash here as the threads aren't going down smoothly
  280. if(error.length() > 0)
  281. std::clog << std::endl << "> ERROR: " << error << std::endl;
  282.  
  283. #if defined(WINDOWS) && !defined(_CONSOLE)
  284. MessageBox(GUI::getInstance()->m_mainWindow, error.c_str(), "Error", MB_OK);
  285. system("pause");
  286. #else
  287. OTSYS_getch();
  288. #endif
  289. std::exit(-1);
  290. }
  291.  
  292. void otserv(
  293. #if !defined(WINDOWS) || defined(_CONSOLE)
  294. StringVec args,
  295. #endif
  296. ServiceManager* services);
  297.  
  298. #if !defined(WINDOWS) || defined(_CONSOLE)
  299. int main(int argc, char *argv[])
  300. {
  301. std::srand((uint32_t)OTSYS_TIME());
  302. StringVec args = StringVec(argv, argv + argc);
  303. if(argc > 1 && !argumentsHandler(args))
  304. return 0;
  305.  
  306. #else
  307. void serverMain(void* param)
  308. {
  309. std::cout.rdbuf(&g_logger);
  310. std::cerr.rdbuf(&g_logger);
  311. std::clog.rdbuf(&g_logger);
  312.  
  313. #endif
  314. std::set_new_handler(allocationHandler);
  315. ServiceManager servicer;
  316. g_config.startup();
  317.  
  318. #ifdef __OTSERV_ALLOCATOR_STATS__
  319. boost::thread(boost::bind(&allocatorStatsThread, (void*)NULL));
  320. // TODO: this thread needs a shutdown (timed_lock + interrupt? .interrupt + .unlock)
  321. #endif
  322. #ifdef __EXCEPTION_TRACER__
  323. ExceptionHandler mainExceptionHandler;
  324. mainExceptionHandler.InstallHandler();
  325. #endif
  326. #ifndef WINDOWS
  327.  
  328. // ignore sigpipe...
  329. struct sigaction sigh;
  330. sigh.sa_handler = SIG_IGN;
  331. sigh.sa_flags = 0;
  332.  
  333. sigemptyset(&sigh.sa_mask);
  334. sigaction(SIGPIPE, &sigh, NULL);
  335.  
  336. // register signals
  337. signal(SIGHUP, signalHandler); //save
  338. signal(SIGTRAP, signalHandler); //clean
  339. signal(SIGCHLD, signalHandler); //refresh
  340. signal(SIGUSR1, signalHandler); //close server
  341. signal(SIGUSR2, signalHandler); //open server
  342. signal(SIGCONT, signalHandler); //reload all
  343. signal(SIGQUIT, signalHandler); //save & shutdown
  344. signal(SIGTERM, signalHandler); //shutdown
  345. #endif
  346.  
  347. Dispatcher::getInstance().addTask(createTask(boost::bind(otserv,
  348. #if !defined(WINDOWS) || defined(_CONSOLE)
  349. args,
  350. #endif
  351. &servicer)));
  352. g_loaderSignal.wait(g_loaderUniqueLock);
  353.  
  354. boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
  355. if(servicer.isRunning())
  356. {
  357. Status::getInstance();
  358. std::clog << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " server Online!" << std::endl << std::endl;
  359. #if defined(WINDOWS) && !defined(_CONSOLE)
  360. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> server Online!");
  361. GUI::getInstance()->m_connections = true;
  362. #endif
  363. servicer.run();
  364. }
  365. else
  366. {
  367. Status::getInstance();
  368. std::clog << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " server Offline! No services available..." << std::endl << std::endl;
  369. #if defined(WINDOWS) && !defined(_CONSOLE)
  370. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> server Offline! No services available...");
  371. GUI::getInstance()->m_connections = true;
  372. #endif
  373. }
  374.  
  375. Dispatcher::getInstance().exit();
  376. Scheduler::getInstance().exit();
  377.  
  378. #ifdef __EXCEPTION_TRACER__
  379. mainExceptionHandler.RemoveHandler();
  380. #endif
  381. #if !defined(WINDOWS) || defined(_CONSOLE)
  382. return 0;
  383. #endif
  384. }
  385.  
  386. void otserv(
  387. #if !defined(WINDOWS) || defined(_CONSOLE)
  388. StringVec,
  389. #endif
  390. ServiceManager* services)
  391. {
  392. std::srand((uint32_t)OTSYS_TIME());
  393. #if defined(WINDOWS)
  394. #if defined(_CONSOLE)
  395. SetConsoleTitle(SOFTWARE_NAME);
  396. #else
  397. GUI::getInstance()->m_connections = false;
  398. #endif
  399. #endif
  400.  
  401. g_game.setGameState(GAMESTATE_STARTUP);
  402. #if !defined(WINDOWS) && !defined(__ROOT_PERMISSION__)
  403. if(!getuid() || !geteuid())
  404. {
  405. std::clog << "> WARNING: " "The " << SOFTWARE_NAME << " has been executed as super user! It is "
  406. << "recommended to run as a normal user." << std::endl << "Continue? (y/N)" << std::endl;
  407. char buffer = OTSYS_getch();
  408. if(buffer != 121 && buffer != 89)
  409. startupErrorMessage("Aborted.");
  410. }
  411. #endif
  412.  
  413. std::clog << "The " << SOFTWARE_NAME << " Version: (" << SOFTWARE_VERSION << "." << MINOR_VERSION << ") - Codename: (" << SOFTWARE_CODENAME << ")" << std::endl
  414. << "Compiled with " << BOOST_COMPILER << " for arch "
  415. #if defined(__amd64__) || defined(_M_X64)
  416. "64 Bits"
  417. #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_)
  418. "32 Bits"
  419. #else
  420. "unk"
  421. #endif
  422. " at " << __DATE__ << " " << __TIME__ << std::endl
  423.  
  424. << std::endl
  425. << "A server developed by: " SOFTWARE_DEVELOPERS "." << std::endl
  426. << "Visit for updates, support, and resources: " GIT_REPO "" << std::endl;
  427. std::stringstream ss;
  428. #ifdef __DEBUG__
  429. ss << " GLOBAL";
  430. #endif
  431. #ifdef __DEBUG_MOVESYS__
  432. ss << " MOVESYS";
  433. #endif
  434. #ifdef __DEBUG_CHAT__
  435. ss << " CHAT";
  436. #endif
  437. #ifdef __DEBUG_HOUSES__
  438. ss << " HOUSES";
  439. #endif
  440. #ifdef __DEBUG_LUASCRIPTS__
  441. ss << " LUA-SCRIPTS";
  442. #endif
  443. #ifdef __DEBUG_MAILBOX__
  444. ss << " MAILBOX";
  445. #endif
  446. #ifdef __DEBUG_NET__
  447. ss << " NET";
  448. #endif
  449. #ifdef __DEBUG_NET_DETAIL__
  450. ss << " NET-DETAIL";
  451. #endif
  452. #ifdef __DEBUG_RAID__
  453. ss << " RAIDS";
  454. #endif
  455. #ifdef __DEBUG_SCHEDULER__
  456. ss << " SCHEDULER";
  457. #endif
  458. #ifdef __DEBUG_SPAWN__
  459. ss << " SPAWNS";
  460. #endif
  461. #ifdef __SQL_QUERY_DEBUG__
  462. ss << " SQL-QUERIES";
  463. #endif
  464.  
  465. std::string debug = ss.str();
  466. if(!debug.empty())
  467. {
  468. std::clog << ">> Debugging:";
  469. #if defined(WINDOWS) && !defined(_CONSOLE)
  470. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Debugging:");
  471. #endif
  472. std::clog << debug << "." << std::endl;
  473. }
  474. std::clog << std::endl;
  475. std::clog << ">> Loading config (" << g_config.getString(ConfigManager::CONFIG_FILE) << ")" << std::endl;
  476. #if defined(WINDOWS) && !defined(_CONSOLE)
  477. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading config");
  478. #endif
  479. if(!g_config.load())
  480. startupErrorMessage("Unable to load " + g_config.getString(ConfigManager::CONFIG_FILE) + "!");
  481.  
  482. #ifndef WINDOWS
  483. if(g_config.getBool(ConfigManager::DAEMONIZE))
  484. {
  485. std::clog << "> Daemonization... ";
  486. if(fork())
  487. {
  488. std::clog << "succeed, bye!" << std::endl;
  489. exit(0);
  490. }
  491. else
  492. std::clog << "failed, continuing." << std::endl;
  493. }
  494.  
  495. #endif
  496. // silently append trailing slash
  497. std::string path = g_config.getString(ConfigManager::DATA_DIRECTORY);
  498. g_config.setString(ConfigManager::DATA_DIRECTORY, path.erase(path.find_last_not_of("/") + 1) + "/");
  499.  
  500. path = g_config.getString(ConfigManager::LOGS_DIRECTORY);
  501. g_config.setString(ConfigManager::LOGS_DIRECTORY, path.erase(path.find_last_not_of("/") + 1) + "/");
  502.  
  503. std::clog << ">> Opening logs" << std::endl;
  504. #if defined(WINDOWS) && !defined(_CONSOLE)
  505. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Opening logs");
  506. #endif
  507. Logger::getInstance()->open();
  508.  
  509. IntegerVec cores = vectorAtoi(explodeString(g_config.getString(ConfigManager::CORES_USED), ","));
  510. if(cores[0] != -1)
  511. {
  512. #ifdef WINDOWS
  513. int32_t mask = 0;
  514. for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it)
  515. mask += 1 << (*it);
  516.  
  517. SetProcessAffinityMask(GetCurrentProcess(), mask);
  518. }
  519.  
  520. std::stringstream mutexName;
  521. mutexName << "otxserver_" << g_config.getNumber(ConfigManager::WORLD_ID);
  522.  
  523. CreateMutex(NULL, FALSE, mutexName.str().c_str());
  524. if(GetLastError() == ERROR_ALREADY_EXISTS)
  525. startupErrorMessage("Another instance of The OTX Server is already running with the same worldId.\nIf you want to run multiple servers, please change the worldId in configuration file.");
  526.  
  527. std::string defaultPriority = asLowerCaseString(g_config.getString(ConfigManager::DEFAULT_PRIORITY));
  528. if(defaultPriority == "realtime" || defaultPriority == "real")
  529. SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  530. else if(defaultPriority == "high" || defaultPriority == "regular")
  531. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  532. else if(defaultPriority == "higher" || defaultPriority == "above" || defaultPriority == "normal")
  533. SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
  534.  
  535. #else
  536. #ifndef __APPLE__
  537. cpu_set_t mask;
  538. CPU_ZERO(&mask);
  539. for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it)
  540. CPU_SET((*it), &mask);
  541.  
  542. sched_setaffinity(getpid(), (int32_t)sizeof(mask), &mask);
  543. }
  544. #endif
  545.  
  546. std::string runPath = g_config.getString(ConfigManager::RUNFILE);
  547. if(!runPath.empty() && runPath.length() > 2)
  548. {
  549. std::ofstream runFile(runPath.c_str(), std::ios::trunc | std::ios::out);
  550. runFile << getpid();
  551. runFile.close();
  552. atexit(runfileHandler);
  553. }
  554.  
  555. if(!nice(g_config.getNumber(ConfigManager::NICE_LEVEL))) {}
  556. #endif
  557.  
  558. std::clog << ">> Loading Password encryption:" << std::endl;
  559. #if defined(WINDOWS) && !defined(_CONSOLE)
  560. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading Password encryption:");
  561. #endif
  562. std::string encryptionType = asLowerCaseString(g_config.getString(ConfigManager::ENCRYPTION_TYPE));
  563. if(encryptionType == "md5")
  564. {
  565. g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_MD5);
  566. std::clog << ">>> Using (MD5) encryption ... (done)." << std::endl;
  567. }
  568. else if(encryptionType == "sha1")
  569. {
  570. g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_SHA1);
  571. std::clog << ">>> Using (SHA1) encryption ... (done)." << std::endl;
  572. }
  573. else if(encryptionType == "sha256")
  574. {
  575. g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_SHA256);
  576. std::clog << ">>> Using (SHA256) encryption ... (done)." << std::endl;
  577. }
  578. else if(encryptionType == "sha512")
  579. {
  580. g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_SHA512);
  581. std::clog << ">>> Using (SHA512) encryption ... (done)." << std::endl;
  582. }
  583. else
  584. {
  585. g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_PLAIN);
  586. std::clog << ">>> Using plaintext encryption" << std::endl << std::endl
  587. << ">>> WARNING: This method is completely unsafe!" << std::endl
  588. << ">>> Please set encryptionType = \"sha1\" (or any other available method) in config.lua" << std::endl;
  589. boost::this_thread::sleep(boost::posix_time::seconds(15));
  590. }
  591.  
  592. #ifdef _MULTIPLATFORM77
  593. std::clog << ">> Loading RSA key" << std::endl;
  594. #if defined(WINDOWS) && !defined(_CONSOLE)
  595. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading RSA Key");
  596. #endif
  597. g_RSA = RSA_new();
  598.  
  599. BN_dec2bn(&g_RSA->p, g_config.getString(ConfigManager::RSA_PRIME1).c_str());
  600. BN_dec2bn(&g_RSA->q, g_config.getString(ConfigManager::RSA_PRIME2).c_str());
  601. BN_dec2bn(&g_RSA->d, g_config.getString(ConfigManager::RSA_PRIVATE).c_str());
  602. BN_dec2bn(&g_RSA->n, g_config.getString(ConfigManager::RSA_MODULUS).c_str());
  603. BN_dec2bn(&g_RSA->e, g_config.getString(ConfigManager::RSA_PUBLIC).c_str());
  604.  
  605. // This check will verify keys set in config.lua
  606. if(RSA_check_key(g_RSA))
  607. {
  608. // Ok, now we calculate a few things, dmp1, dmq1 and iqmp
  609. BN_CTX* ctx = BN_CTX_new();
  610. BN_CTX_start(ctx);
  611.  
  612. BIGNUM *r1 = BN_CTX_get(ctx), *r2 = BN_CTX_get(ctx);
  613. BN_mod(g_RSA->dmp1, g_RSA->d, r1, ctx);
  614. BN_mod(g_RSA->dmq1, g_RSA->d, r2, ctx);
  615.  
  616. BN_mod_inverse(g_RSA->iqmp, g_RSA->q, g_RSA->p, ctx);
  617. }
  618. else
  619. {
  620. ERR_load_crypto_strings();
  621. std::stringstream s;
  622.  
  623. s << std::endl << "> OpenSSL failed - " << ERR_error_string(ERR_get_error(), NULL);
  624. startupErrorMessage(s.str());
  625. }
  626. #endif
  627.  
  628. std::clog << ">> Starting SQL connection" << std::endl;
  629. #if defined(WINDOWS) && !defined(_CONSOLE)
  630. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Starting SQL connection");
  631. #endif
  632. Database* db = Database::getInstance();
  633. if(db && db->isConnected())
  634. {
  635. std::clog << ">> Running Database Manager" << std::endl;
  636. #if defined(WINDOWS) && !defined(_CONSOLE)
  637. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Running Database Manager");
  638. #endif
  639. if(DatabaseManager::getInstance()->isDatabaseSetup())
  640. {
  641. uint32_t version = 0;
  642. do
  643. {
  644. version = DatabaseManager::getInstance()->updateDatabase();
  645. if(version == 0)
  646. break;
  647.  
  648. std::clog << "> Database has been updated to version: " << version << "." << std::endl;
  649. }
  650. while(version < VERSION_DATABASE);
  651. }
  652. else
  653. startupErrorMessage("The database you have specified in config.lua is empty, please import schemas/<engine>.sql to the database.");
  654.  
  655. DatabaseManager::getInstance()->checkTriggers();
  656. DatabaseManager::getInstance()->checkEncryption();
  657. if(g_config.getBool(ConfigManager::OPTIMIZE_DATABASE) && !DatabaseManager::getInstance()->optimizeTables())
  658. std::clog << "> No tables were optimized." << std::endl;
  659. }
  660. else
  661. startupErrorMessage("Couldn't estabilish connection to SQL database!");
  662.  
  663. std::clog << ">> Checking for duplicated items" << std::endl;
  664. #if defined(WINDOWS) && !defined(_CONSOLE)
  665. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Checking for duplicated items");
  666. #endif
  667. DBQuery query;
  668. query << "SELECT unitedItems.serial, COUNT(1) AS duplicatesCount FROM (SELECT serial FROM `player_items` UNION ALL SELECT serial FROM `player_depotitems` UNION ALL SELECT serial FROM `tile_items`) unitedItems GROUP BY unitedItems.serial HAVING COUNT(1) > 1;";
  669. std::string logText = "";
  670.  
  671. DBResult* result;
  672. bool duplicated = false;
  673.  
  674. if (result = db->storeQuery(query.str()))
  675. if (result = db->storeQuery(query.str())) should be if ((result = db->storeQuery(query.str())))
  676. {
  677. do
  678. {
  679. std::string serial = result->getDataString("serial");
  680. if (serial != "" && serial.length() > 1)
  681. {
  682. DBResult* result_;
  683. DBQuery query_playeritems;
  684. query_playeritems << "SELECT `player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`, `serial` FROM `player_items` WHERE `serial` = " << db->escapeString(serial) << ";";
  685. if (result_ = db->storeQuery(query_playeritems.str()))
  686. if (result = db->storeQuery(query.str())) should be if ((result = db->storeQuery(query.str())))
  687. {
  688. duplicated = true;
  689. do
  690. {
  691. std::string name;
  692. IOLoginData::getInstance()->getNameByGuid((uint32_t)result_->getDataInt("player_id"), name, false);
  693. std::clog << ">> Deleted item from 'player_items' with SERIAL: [" << serial.c_str() << "] PLAYER: [" << result_->getDataInt("player_id") << "] PLAYER NAME: [" << name.c_str() << "] ITEM: [" << result_->getDataInt("itemtype") << "] COUNT: [" << result_->getDataInt("count") << "]" << std::endl;
  694. std::stringstream logText;
  695. logText << "Deleted item from 'player_items' with SERIAL: [" << serial << "] PLAYER: [" << result_->getDataInt("player_id") << "] PLAYER NAME: [" << name << "] ITEM: [" << result_->getDataInt("itemtype") << "] COUNT: [" << result_->getDataInt("count") << "]";
  696. Logger::getInstance()->eFile("anti_dupe.log", logText.str(), true);
  697. } while (result_->next());
  698. result_->free();
  699. }
  700.  
  701. query_playeritems.clear();
  702. DBQuery query_playerdepotitems;
  703. query_playerdepotitems << "SELECT `player_id`, `sid`, `pid`, `itemtype`, `count`, `attributes`, `serial` FROM `player_depotitems` WHERE `serial` = " << db->escapeString(serial) << ";";
  704. if (result_ = db->storeQuery(query_playerdepotitems.str()))
  705. if (result = db->storeQuery(query.str())) should be if ((result = db->storeQuery(query.str())))
  706. {
  707. duplicated = true;
  708. do
  709. {
  710. std::string name;
  711. IOLoginData::getInstance()->getNameByGuid((uint32_t)result_->getDataInt("player_id"), name, false);
  712. std::clog << ">> Deleted item from 'player_depotitems' with SERIAL: [" << serial.c_str() << "] PLAYER: [" << result_->getDataInt("player_id") << "] PLAYER NAME: [" << name.c_str() << "] ITEM: [" << result_->getDataInt("itemtype") << "] COUNT: [" << result_->getDataInt("count") << "]" << std::endl;
  713. std::stringstream logText;
  714. logText << "Deleted item from 'player_depotitems' with SERIAL: [" << serial << "] PLAYER: [" << result_->getDataInt("player_id") << "] PLAYER NAME: [" << name << "] ITEM: [" << result_->getDataInt("itemtype") << "] COUNT: [" << result_->getDataInt("count") << "]";
  715. Logger::getInstance()->eFile("anti_dupe.log", logText.str(), true);
  716. } while (result_->next());
  717. result_->free();
  718. }
  719.  
  720. query_playerdepotitems.clear();
  721. DBQuery query_tileitems;
  722. query_tileitems << "SELECT `tile_id`, `world_id`, `sid`, `pid`, `itemtype`, `count`, `attributes`, `serial` FROM `tile_items` WHERE `serial` = " << db->escapeString(serial) << ";";
  723. if (result_ = db->storeQuery(query_tileitems.str()))
  724. if (result = db->storeQuery(query.str())) should be if ((result = db->storeQuery(query.str())))
  725. {
  726. duplicated = true;
  727. do
  728. {
  729. std::clog << ">> Deleted item from 'tile_items' with SERIAL: [" << serial.c_str() << "] TILE ID: [" << result_->getDataInt("tile_id") << "] WORLD ID: [" << result_->getDataInt("world_id") << "] ITEM: [" << result_->getDataInt("itemtype") << "] COUNT: [" << result_->getDataInt("count") << "]" << std::endl;
  730. std::stringstream logText;
  731. logText << "Deleted item from 'tile_items' with SERIAL: [" << serial << "] TILE ID: [" << result_->getDataInt("tile_id") << "] WORLD ID: [" << result_->getDataInt("world_id") << "] ITEM: [" << result_->getDataInt("itemtype") << "] COUNT: [" << result_->getDataInt("count") << "]";
  732. Logger::getInstance()->eFile("anti_dupe.log", logText.str(), true);
  733. } while (result_->next());
  734. result_->free();
  735. }
  736.  
  737. query_tileitems.clear();
  738. DBQuery query_deletepi;
  739. query_deletepi << "DELETE FROM `player_items` WHERE `serial` = " << db->escapeString(serial) << ";";
  740. if (!db->query(query_deletepi.str()))
  741. std::clog << ">> Cannot delete duplicated items from 'player_items'!" << std::endl;
  742.  
  743. query_deletepi.clear();
  744. DBQuery query_deletedi;
  745. query_deletedi << "DELETE FROM `player_depotitems` WHERE `serial` = " << db->escapeString(serial) << ";";
  746. if (!db->query(query_deletedi.str()))
  747. std::clog << ">> Cannot delete duplicated items from 'player_depotitems'!" << std::endl;
  748.  
  749. query_deletedi.clear();
  750. DBQuery query_deleteti;
  751. query_deleteti << "DELETE FROM `tile_items` WHERE `serial` = " << db->escapeString(serial) << ";";
  752. if (!db->query(query_deleteti.str()))
  753. std::clog << ">> Cannot delete duplicated items from 'tile_items'!" << std::endl;
  754.  
  755. query_deleteti.clear();
  756. }
  757. } while (result->next());
  758. result->free();
  759. if (duplicated)
  760. std::clog << ">> Duplicated items successfully removed." << std::endl;
  761. }
  762. else
  763. std::clog << ">> There wasn't duplicated items in the server." << std::endl;
  764.  
  765. std::clog << ">> Loading groups" << std::endl;
  766. #if defined(WINDOWS) && !defined(_CONSOLE)
  767. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading groups");
  768. #endif
  769. if(!Groups::getInstance()->loadFromXml())
  770. startupErrorMessage("Unable to load groups!");
  771.  
  772. std::clog << ">> Loading items (OTB)" << std::endl;
  773. #if defined(WINDOWS) && !defined(_CONSOLE)
  774. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading items (OTB)");
  775. #endif
  776. if(Item::items.loadFromOtb(getFilePath(FILE_TYPE_OTHER, "items/" + ITEMS_PATH + "/items.otb")))
  777. startupErrorMessage("Unable to load items (OTB)!");
  778.  
  779. std::clog << ">> Loading items (XML)" << std::endl;
  780. #if defined(WINDOWS) && !defined(_CONSOLE)
  781. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading items (XML)");
  782. #endif
  783. if(!Item::items.loadFromXml())
  784. {
  785. #if defined(WINDOWS) && !defined(_CONSOLE)
  786. if(MessageBox(GUI::getInstance()->m_mainWindow, "Unable to load items (XML)! Continue?", "Items (XML)", MB_YESNO) == IDNO)
  787. #else
  788. std::clog << "Unable to load items (XML)! Continue? (y/N)" << std::endl;
  789. char buffer = OTSYS_getch();
  790. if(buffer == 10 || (buffer != 121 && buffer != 89))
  791. #endif
  792. startupErrorMessage("Unable to load items (XML)!");
  793. }
  794.  
  795. std::clog << ">> Loading outfits" << std::endl;
  796. #if defined(WINDOWS) && !defined(_CONSOLE)
  797. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading outfits");
  798. #endif
  799. if(!Outfits::getInstance()->loadFromXml())
  800. startupErrorMessage("Unable to load outfits!");
  801.  
  802. std::clog << ">> Loading raids" << std::endl;
  803. #if defined(WINDOWS) && !defined(_CONSOLE)
  804. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading raids");
  805. #endif
  806. if(!Raids::getInstance()->loadFromXml())
  807. startupErrorMessage("Unable to load raids!");
  808.  
  809. std::clog << ">> Loading vocations" << std::endl;
  810. #if defined(WINDOWS) && !defined(_CONSOLE)
  811. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading vocations");
  812. #endif
  813. if(!Vocations::getInstance()->loadFromXml())
  814. startupErrorMessage("Unable to load vocations!");
  815.  
  816. std::clog << ">> Loading chat channels" << std::endl;
  817. #if defined(WINDOWS) && !defined(_CONSOLE)
  818. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading chat channels");
  819. #endif
  820. if(!g_chat.loadFromXml())
  821. startupErrorMessage("Unable to load chat channels!");
  822.  
  823. std::clog << ">> Loading experience stages" << std::endl;
  824. #if defined(WINDOWS) && !defined(_CONSOLE)
  825. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading experience stages");
  826. #endif
  827. if(!g_game.loadExperienceStages())
  828. startupErrorMessage("Unable to load experience stages!");
  829.  
  830. std::clog << ">> Loading mods:" << std::endl;
  831. #if defined(WINDOWS) && !defined(_CONSOLE)
  832. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading mods:");
  833. #endif
  834. if(!ScriptManager::getInstance()->loadMods())
  835. startupErrorMessage();
  836.  
  837. if(g_config.getBool(ConfigManager::SCRIPT_SYSTEM))
  838. {
  839. std::clog << ">> Loading script systems:" << std::endl;
  840. #if defined(WINDOWS) && !defined(_CONSOLE)
  841. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading script systems:");
  842. #endif
  843. if(!ScriptManager::getInstance()->loadSystem())
  844. startupErrorMessage();
  845. }
  846. else
  847. ScriptManager::getInstance();
  848.  
  849. #ifdef __LOGIN_SERVER__
  850. std::clog << ">> Loading game servers" << std::endl;
  851. #if defined(WINDOWS) && !defined(_CONSOLE)
  852. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading game servers");
  853. #endif
  854. if(!GameServers::getInstance()->loadFromXml(true))
  855. startupErrorMessage("Unable to load game servers!");
  856. #endif
  857.  
  858. std::clog << ">> Loading monsters" << std::endl;
  859. #if defined(WINDOWS) && !defined(_CONSOLE)
  860. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading monsters");
  861. #endif
  862. if(!g_monsters.loadFromXml())
  863. {
  864. #if defined(WINDOWS) && !defined(_CONSOLE)
  865. if(MessageBox(GUI::getInstance()->m_mainWindow, "Unable to load monsters! Continue?", "Monsters", MB_YESNO) == IDNO)
  866. #else
  867. std::clog << "Unable to load monsters! Continue? (y/N)" << std::endl;
  868. char buffer = OTSYS_getch();
  869. if(buffer == 10 || (buffer != 121 && buffer != 89))
  870. #endif
  871. startupErrorMessage("Unable to load monsters!");
  872. }
  873.  
  874. if(fileExists(getFilePath(FILE_TYPE_OTHER, "npc/npcs.xml").c_str()))
  875. {
  876. std::clog << ">> Loading npcs" << std::endl;
  877. #if defined(WINDOWS) && !defined(_CONSOLE)
  878. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading npcs");
  879. #endif
  880. if(!g_npcs.loadFromXml())
  881. {
  882. #if defined(WINDOWS) && !defined(_CONSOLE)
  883. if(MessageBox(GUI::getInstance()->m_mainWindow, "Unable to load npcs! Continue?", "NPC", MB_YESNO) == IDNO)
  884. #else
  885. std::clog << "Unable to load npcs! Continue? (y/N)" << std::endl;
  886. char buffer = OTSYS_getch();
  887. if(buffer == 10 || (buffer != 121 && buffer != 89))
  888. #endif
  889. startupErrorMessage("Unable to load npcs!");
  890. }
  891. }
  892.  
  893. std::clog << ">> Loading map and spawns:" << std::endl;
  894. #if defined(WINDOWS) && !defined(_CONSOLE)
  895. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading map and spawns:");
  896. #endif
  897.  
  898. if(!g_game.loadMap(g_config.getString(ConfigManager::MAP_NAME)))
  899. startupErrorMessage();
  900.  
  901. std::clog << ">> Checking world type: ";
  902. #if defined(WINDOWS) && !defined(_CONSOLE)
  903. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Checking world type: ");
  904. #endif
  905. std::string worldType = asLowerCaseString(g_config.getString(ConfigManager::WORLD_TYPE));
  906. if(worldType == "open" || worldType == "2" || worldType == "openpvp")
  907. {
  908. g_game.setWorldType(WORLDTYPE_OPEN);
  909. std::clog << "Open PvP" << std::endl;
  910. }
  911. else if(worldType == "optional" || worldType == "1" || worldType == "optionalpvp")
  912. {
  913. g_game.setWorldType(WORLDTYPE_OPTIONAL);
  914. std::clog << "Optional PvP" << std::endl;
  915. }
  916. else if(worldType == "hardcore" || worldType == "3" || worldType == "hardcorepvp")
  917. {
  918. g_game.setWorldType(WORLDTYPE_HARDCORE);
  919. std::clog << "Hardcore PvP" << std::endl;
  920. }
  921. else
  922. {
  923. std::clog << std::endl;
  924. startupErrorMessage("Unknown world type: " + g_config.getString(ConfigManager::WORLD_TYPE));
  925. }
  926.  
  927. std::clog << ">> Starting to dominate the world... done." << std::endl;
  928. #if defined(WINDOWS) && !defined(_CONSOLE)
  929. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Starting to dominate the world... done.");
  930. #endif
  931.  
  932. std::clog << ">> Initializing game state and binding services:" << std::endl;
  933. #if defined(WINDOWS) && !defined(_CONSOLE)
  934. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Initializing game state and binding services:");
  935. #endif
  936. g_game.setGameState(GAMESTATE_INIT);
  937. IPAddressList ipList;
  938.  
  939. StringVec ip = explodeString(g_config.getString(ConfigManager::IP), ",");
  940. if(asLowerCaseString(ip[0]) == "auto")
  941. {
  942. // TODO: automatic shit
  943. }
  944.  
  945. IPAddress m_ip;
  946. std::clog << ">> Global IP address(es): ";
  947. #if defined(WINDOWS) && !defined(_CONSOLE)
  948. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Global IP address(es): ");
  949. #endif
  950. for(StringVec::iterator it = ip.begin(); it != ip.end(); ++it)
  951. {
  952. uint32_t resolvedIp = inet_addr(it->c_str());
  953. if(resolvedIp == INADDR_NONE)
  954. {
  955. struct hostent* host = gethostbyname(it->c_str());
  956. if(!host)
  957. {
  958. std::clog << "..." << std::endl;
  959. startupErrorMessage("Cannot resolve " + (*it) + "!");
  960. }
  961.  
  962. resolvedIp = *(uint32_t*)host->h_addr;
  963. }
  964.  
  965. serverIps.push_front(std::make_pair(resolvedIp, 0));
  966. m_ip = boost::asio::ip::address_v4(swap_uint32(resolvedIp));
  967.  
  968. ipList.push_back(m_ip);
  969. std::clog << m_ip.to_string() << std::endl;
  970. }
  971.  
  972. ipList.push_back(boost::asio::ip::address_v4(INADDR_LOOPBACK));
  973. if(!g_config.getBool(ConfigManager::BIND_ONLY_GLOBAL_ADDRESS))
  974. {
  975. char hostName[128];
  976. if(!gethostname(hostName, 128))
  977. {
  978. if(hostent* host = gethostbyname(hostName))
  979. {
  980. std::stringstream s;
  981. for(uint8_t** addr = (uint8_t**)host->h_addr_list; addr[0]; addr++)
  982. {
  983. uint32_t resolved = swap_uint32(*(uint32_t*)(*addr));
  984. if(m_ip.to_v4().to_ulong() == resolved)
  985. continue;
  986.  
  987. ipList.push_back(boost::asio::ip::address_v4(resolved));
  988. serverIps.push_front(std::make_pair(*(uint32_t*)(*addr), 0x0000FFFF));
  989.  
  990. s << (int32_t)(addr[0][0]) << "." << (int32_t)(addr[0][1]) << "."
  991. << (int32_t)(addr[0][2]) << "." << (int32_t)(addr[0][3]) << "\t";
  992. }
  993.  
  994. if(s.str().size())
  995. std::clog << ">>> Local IP address(es): " << s.str() << std::endl;
  996. }
  997. }
  998.  
  999. if(m_ip.to_v4().to_ulong() != LOCALHOST)
  1000. ipList.push_back(boost::asio::ip::address_v4(LOCALHOST));
  1001. }
  1002. else if(ipList.size() < 2)
  1003. startupErrorMessage("Unable to bind any IP address! You may want to disable \"bindOnlyGlobalAddress\" setting in config.lua");
  1004.  
  1005. services->add<ProtocolStatus>(g_config.getNumber(ConfigManager::STATUS_PORT), ipList);
  1006.  
  1007. if(
  1008. #ifdef __LOGIN_SERVER__
  1009. true
  1010. #else
  1011. !g_config.getBool(ConfigManager::LOGIN_ONLY_LOGINSERVER)
  1012. #endif
  1013. )
  1014. {
  1015. services->add<ProtocolLogin>(g_config.getNumber(ConfigManager::LOGIN_PORT), ipList);
  1016. }
  1017.  
  1018. services->add<ProtocolGame>(g_config.getNumber(ConfigManager::GAME_PORT), ipList);
  1019. std::clog << "> Bound ports: ";
  1020. #if defined(WINDOWS) && !defined(_CONSOLE)
  1021. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Bound ports: ");
  1022. #endif
  1023.  
  1024. std::list<uint16_t> ports = services->getPorts();
  1025. for(std::list<uint16_t>::iterator it = ports.begin(); it != ports.end(); ++it)
  1026. std::clog << (*it) << "\t";
  1027.  
  1028. std::clog << std::endl << ">> Everything smells good, server is starting up..." << std::endl;
  1029. #if defined(WINDOWS) && !defined(_CONSOLE)
  1030. SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Everything smells good, server is starting up...");
  1031. #endif
  1032. g_game.start(services);
  1033. g_game.setGameState(g_config.getBool(ConfigManager::START_CLOSED) ? GAMESTATE_CLOSED : GAMESTATE_NORMAL);
  1034. g_loaderSignal.notify_all();
  1035. }
  1036.  
  1037. #if defined(WINDOWS) && !defined(_CONSOLE)
  1038. LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1039. {
  1040. CInputBox iBox(hwnd);
  1041. switch(message)
  1042. {
  1043. case WM_CREATE:
  1044. {
  1045. GUI::getInstance()->m_logWindow = CreateWindow("edit", NULL,
  1046. WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE | ES_MULTILINE | DS_CENTER, 0, 0, 640, 450, hwnd, (HMENU)ID_LOG, NULL, NULL);
  1047. GUI::getInstance()->m_statusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
  1048. WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwnd, (HMENU)ID_STATUS_BAR, GetModuleHandle(NULL), NULL);
  1049.  
  1050. int32_t statusBarWidthLine[] = {150, -1};
  1051. GUI::getInstance()->m_lineCount = 0;
  1052.  
  1053. SendMessage(GUI::getInstance()->m_statusBar, SB_SETPARTS, sizeof(statusBarWidthLine) / sizeof(int32_t), (LPARAM)statusBarWidthLine);
  1054. SendMessage(GUI::getInstance()->m_statusBar, SB_SETTEXT, 0, (LPARAM)">> Not loaded");
  1055.  
  1056. GUI::getInstance()->m_minimized = false;
  1057. GUI::getInstance()->m_pBox.setParent(hwnd);
  1058. SendMessage(GUI::getInstance()->m_logWindow, WM_SETFONT, (WPARAM)GUI::getInstance()->m_font, 0);
  1059.  
  1060. NID.hWnd = hwnd;
  1061. NID.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ICON));
  1062. NID.uCallbackMessage = WM_USER + 1;
  1063. NID.uFlags = NIF_TIP | NIF_ICON | NIF_MESSAGE;
  1064.  
  1065. strcpy(NID.szTip, SOFTWARE_NAME);
  1066. Shell_NotifyIcon(NIM_ADD, &NID);
  1067.  
  1068. boost::thread(boost::bind(&serverMain, (void*)hwnd));
  1069. break;
  1070. }
  1071.  
  1072. case WM_SIZE:
  1073. {
  1074. if(wParam == SIZE_MINIMIZED)
  1075. {
  1076. GUI::getInstance()->m_minimized = true;
  1077. ShowWindow(hwnd, SW_HIDE);
  1078. ModifyMenu(GUI::getInstance()->m_trayMenu, ID_TRAY_HIDE, MF_STRING, ID_TRAY_HIDE, "&Show window");
  1079. }
  1080. else
  1081. {
  1082. RECT rcStatus;
  1083. int32_t iStatusHeight;
  1084. int32_t iEditHeight;
  1085. RECT rcClient;
  1086. GUI::getInstance()->m_statusBar = GetDlgItem(hwnd, ID_STATUS_BAR);
  1087. SendMessage(GUI::getInstance()->m_statusBar, WM_SIZE, 0, 0);
  1088. GetWindowRect(GUI::getInstance()->m_statusBar, &rcStatus);
  1089. iStatusHeight = rcStatus.bottom - rcStatus.top;
  1090. GetClientRect(hwnd, &rcClient);
  1091. iEditHeight = rcClient.bottom - iStatusHeight;
  1092. GUI::getInstance()->m_logWindow = GetDlgItem(hwnd, ID_LOG);
  1093. SetWindowPos(GUI::getInstance()->m_logWindow, NULL, 0, rcClient.top, rcClient.right, iEditHeight, SWP_NOZORDER);
  1094. }
  1095.  
  1096. break;
  1097. }
  1098.  
  1099. case WM_COMMAND:
  1100. {
  1101. switch(LOWORD(wParam))
  1102. {
  1103. case ID_TRAY_HIDE:
  1104. {
  1105. if(GUI::getInstance()->m_minimized)
  1106. {
  1107. ShowWindow(hwnd, SW_SHOW);
  1108. ShowWindow(hwnd, SW_RESTORE);
  1109. ModifyMenu(GUI::getInstance()->m_trayMenu, ID_TRAY_HIDE, MF_STRING, ID_TRAY_HIDE, "&Hide window");
  1110. GUI::getInstance()->m_minimized = false;
  1111. }
  1112. else
  1113. {
  1114. ShowWindow(hwnd, SW_HIDE);
  1115. ModifyMenu(GUI::getInstance()->m_trayMenu, ID_TRAY_HIDE, MF_STRING, ID_TRAY_HIDE, "&Show window");
  1116. GUI::getInstance()->m_minimized = true;
  1117. }
  1118.  
  1119. break;
  1120. }
  1121.  
  1122. case ID_MENU_MAIN_ACCEPT:
  1123. {
  1124. if(g_game.getGameState() != GAMESTATE_STARTUP && !GUI::getInstance()->m_connections)
  1125. {
  1126. GUI::getInstance()->m_connections = true;
  1127. ModifyMenu(GetMenu(hwnd), ID_MENU_MAIN_ACCEPT, MF_STRING, ID_MENU_MAIN_REJECT, "&Reject connections");
  1128. }
  1129.  
  1130. break;
  1131. }
  1132.  
  1133. case ID_MENU_MAIN_REJECT:
  1134. {
  1135. if(g_game.getGameState() != GAMESTATE_STARTUP && GUI::getInstance()->m_connections)
  1136. {
  1137. GUI::getInstance()->m_connections = false;
  1138. ModifyMenu(GetMenu(hwnd), ID_MENU_MAIN_REJECT, MF_STRING, ID_MENU_MAIN_ACCEPT, "&Accept connections");
  1139. }
  1140.  
  1141. break;
  1142. }
  1143.  
  1144. case ID_MENU_MAIN_CLEARLOG:
  1145. {
  1146. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1147. {
  1148. GUI::getInstance()->m_logText = "";
  1149. GUI::getInstance()->m_lineCount = 0;
  1150. std::clog << "The " << SOFTWARE_NAME << " Version: (" << SOFTWARE_VERSION << "." << MINOR_VERSION << ") - Codename: (" << SOFTWARE_CODENAME << ")" << std::endl
  1151. << "Compiled with " << BOOST_COMPILER << " for arch "
  1152. #if defined(__amd64__) || defined(_M_X64)
  1153. "64 Bits"
  1154. #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_)
  1155. "32 Bits"
  1156. #else
  1157. "unk"
  1158. #endif
  1159. " at " << __DATE__ << " " << __TIME__ << std::endl
  1160.  
  1161. << std::endl
  1162. << "A server developed by: " SOFTWARE_DEVELOPERS "." << std::endl
  1163. << "Visit for updates, support, and resources: " GIT_REPO "" << std::endl;
  1164. }
  1165.  
  1166. break;
  1167. }
  1168.  
  1169. case ID_TRAY_SHUTDOWN:
  1170. case ID_MENU_MAIN_SHUTDOWN:
  1171. {
  1172. if(MessageBox(hwnd, "Are you sure you want to shutdown the server?", "Shutdown", MB_YESNO) == IDYES)
  1173. {
  1174. Dispatcher::getInstance().addTask(
  1175. createTask(boost::bind(&Game::setGameState, &g_game, GAMESTATE_SHUTDOWN)));
  1176. Shell_NotifyIcon(NIM_DELETE, &NID);
  1177. }
  1178.  
  1179. break;
  1180. }
  1181.  
  1182. case ID_MENU_SERVER_WORLDTYPE_OPTIONAL:
  1183. {
  1184. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1185. {
  1186. g_game.setWorldType(WORLDTYPE_OPTIONAL);
  1187. std::clog << "WorldType set to 'Optional PVP'." << std::endl;
  1188. g_game.broadcastMessage("WorldType set to Optional PVP.", MSG_EVENT_ADVANCE);
  1189. }
  1190.  
  1191. break;
  1192. }
  1193.  
  1194. case ID_MENU_SERVER_WORLDTYPE_OPEN:
  1195. {
  1196. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1197. {
  1198. g_game.setWorldType(WORLDTYPE_OPEN);
  1199. std::clog << "WorldType set to 'Open PVP'." << std::endl;
  1200. g_game.broadcastMessage("WorldType set to Open PVP.", MSG_EVENT_ADVANCE);
  1201. }
  1202.  
  1203. break;
  1204. }
  1205.  
  1206. case ID_MENU_SERVER_WORLDTYPE_HARDCORE:
  1207. {
  1208. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1209. {
  1210. g_game.setWorldType(WORLDTYPE_HARDCORE);
  1211. std::clog << "WorldType set to 'HardCore PVP'." << std::endl;
  1212. g_game.broadcastMessage("WorldType set to HardCore PVP.", MSG_EVENT_ADVANCE);
  1213. }
  1214.  
  1215. break;
  1216. }
  1217.  
  1218. case ID_MENU_SERVER_BROADCAST:
  1219. {
  1220. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1221. {
  1222. if(iBox.DoModal("Broadcast message", "What would you like to broadcast?"))
  1223. g_game.broadcastMessage(iBox.Text, MSG_STATUS_WARNING);
  1224. }
  1225.  
  1226. break;
  1227. }
  1228.  
  1229. case ID_MENU_ADD_PREMIUM:
  1230. {
  1231. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1232. {
  1233. if(iBox.DoModal("Premium Account", "Please enter the name to win premium account."))
  1234. {
  1235. Player* player = g_game.getPlayerByName(iBox.Text);
  1236. Account account = IOLoginData::getInstance()->loadAccount(player->getAccount());
  1237.  
  1238. if(iBox.Text != NULL)
  1239. {
  1240. uint32_t days = g_config.getNumber(ConfigManager::GUI_PREMIUM_DAYS);
  1241. account.premiumDays += days;
  1242.  
  1243. IOLoginData::getInstance()->saveAccount(account);
  1244. MessageBox(NULL, "Premium acocunt has been added.", "Premium Added", MB_OK);
  1245. }
  1246. else
  1247. MessageBox(hwnd, "You does not use empty name.", "Error", 0);
  1248. }
  1249. else
  1250. MessageBox(hwnd, "You must need to put a player name.", "Error", 0);
  1251. }
  1252.  
  1253. break;
  1254. }
  1255.  
  1256. case ID_MENU_KICK_PLAYER:
  1257. {
  1258. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1259. {
  1260. if(iBox.DoModal("Kick Player", "Please enter the name to kick."))
  1261. {
  1262. Player* player = g_game.getPlayerByName(iBox.Text);
  1263. if(iBox.Text != NULL)
  1264. {
  1265. player->kick(true, true);
  1266. MessageBox(NULL, "Player have been kicked.", "Kick Player", MB_OK);
  1267. }
  1268. else
  1269. MessageBox(hwnd, "You does not use empty name.", "Error", 0);
  1270. }
  1271. else
  1272. MessageBox(hwnd, "You must need to put a player name.", "Error", 0);
  1273. }
  1274.  
  1275. break;
  1276. }
  1277.  
  1278. case ID_MENU_SERVER_SAVE:
  1279. {
  1280. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1281. {
  1282. Dispatcher::getInstance().addTask(createTask(
  1283. boost::bind(&Game::saveGameState, &g_game, SAVE_PLAYERS | SAVE_MAP | SAVE_STATE)));
  1284. MessageBox(NULL, "Server has been saved.", "Server save", MB_OK);
  1285. }
  1286.  
  1287. break;
  1288. }
  1289.  
  1290. case ID_MENU_SERVER_CLEAN:
  1291. {
  1292. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1293. {
  1294. uint32_t count = 0;
  1295. g_game.cleanMapEx(count);
  1296.  
  1297. char buffer[100];
  1298. sprintf(buffer, "Map has been cleaned, collected %u items.", count);
  1299. MessageBox(NULL, buffer, "Map clean", MB_OK);
  1300. }
  1301.  
  1302. break;
  1303. }
  1304.  
  1305. case ID_MENU_SERVER_REFRESH:
  1306. {
  1307. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1308. {
  1309. g_game.proceduralRefresh();
  1310. MessageBox(NULL, "Map will now refresh in a while.", "Map refresh", MB_OK);
  1311. }
  1312.  
  1313. break;
  1314. }
  1315.  
  1316. case ID_MENU_SERVER_OPEN:
  1317. {
  1318. if(g_game.getGameState() != GAMESTATE_STARTUP && GUI::getInstance()->m_connections)
  1319. {
  1320. g_game.setGameState(GAMESTATE_NORMAL);
  1321. ModifyMenu(GetMenu(hwnd), ID_MENU_SERVER_OPEN, MF_STRING, ID_MENU_SERVER_CLOSE, "&Close server");
  1322. }
  1323.  
  1324. break;
  1325. }
  1326.  
  1327. case ID_MENU_SERVER_CLOSE:
  1328. {
  1329. if(g_game.getGameState() != GAMESTATE_STARTUP && GUI::getInstance()->m_connections)
  1330. {
  1331. Dispatcher::getInstance().addTask(createTask(
  1332. boost::bind(&Game::setGameState, &g_game, GAMESTATE_CLOSED)));
  1333. ModifyMenu(GetMenu(hwnd), ID_MENU_SERVER_CLOSE, MF_STRING, ID_MENU_SERVER_OPEN, "&Open server");
  1334. }
  1335.  
  1336. break;
  1337. }
  1338.  
  1339. case ID_MENU_RELOAD_ACTIONS:
  1340. {
  1341. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1342. {
  1343. if(g_game.reloadInfo(RELOAD_ACTIONS))
  1344. std::clog << "Reloaded actions." << std::endl;
  1345. }
  1346.  
  1347. break;
  1348. }
  1349.  
  1350. case ID_MENU_RELOAD_CHAT:
  1351. {
  1352. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1353. {
  1354. if(g_game.reloadInfo(RELOAD_CHAT))
  1355. std::clog << "Reloaded chat channels." << std::endl;
  1356. }
  1357.  
  1358. break;
  1359. }
  1360.  
  1361. case ID_MENU_RELOAD_CONFIG:
  1362. {
  1363. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1364. {
  1365. if(g_game.reloadInfo(RELOAD_CONFIG))
  1366. std::clog << "Reloaded config." << std::endl;
  1367. }
  1368.  
  1369. break;
  1370. }
  1371.  
  1372. case ID_MENU_RELOAD_CREATUREEVENTS:
  1373. {
  1374. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1375. {
  1376. if(g_game.reloadInfo(RELOAD_CREATUREEVENTS))
  1377. std::clog << "Reloaded creature events." << std::endl;
  1378. }
  1379.  
  1380. break;
  1381. }
  1382.  
  1383. #ifdef __LOGIN_SERVER__
  1384. case ID_MENU_RELOAD_GAMESERVERS:
  1385. {
  1386. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1387. {
  1388. if(g_game.reloadInfo(RELOAD_GAMESERVERS))
  1389. std::clog << "Reloaded game servers." << std::endl;
  1390. }
  1391.  
  1392. break;
  1393. }
  1394. #endif
  1395.  
  1396. case ID_MENU_RELOAD_GLOBALEVENTS:
  1397. {
  1398. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1399. {
  1400. if(g_game.reloadInfo(RELOAD_GLOBALEVENTS))
  1401. std::clog << "Reloaded global events." << std::endl;
  1402. }
  1403.  
  1404. break;
  1405. }
  1406.  
  1407. case ID_MENU_RELOAD_MONSTERS:
  1408. {
  1409. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1410. {
  1411. if(g_game.reloadInfo(RELOAD_MONSTERS))
  1412. std::clog << "Reloaded monsters." << std::endl;
  1413. }
  1414.  
  1415. break;
  1416. }
  1417.  
  1418. case ID_MENU_RELOAD_MOVEMENTS:
  1419. {
  1420. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1421. {
  1422. if(g_game.reloadInfo(RELOAD_MOVEEVENTS))
  1423. std::clog << "Reloaded movements." << std::endl;
  1424. }
  1425.  
  1426. break;
  1427. }
  1428.  
  1429. case ID_MENU_RELOAD_RAIDS:
  1430. {
  1431. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1432. {
  1433. if(g_game.reloadInfo(RELOAD_RAIDS))
  1434. std::clog << "Reloaded raids." << std::endl;
  1435. }
  1436.  
  1437. break;
  1438. }
  1439.  
  1440. case ID_MENU_RELOAD_SPELLS:
  1441. {
  1442. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1443. {
  1444. if(g_game.reloadInfo(RELOAD_SPELLS))
  1445. std::clog << "Reloaded spells." << std::endl;
  1446. }
  1447.  
  1448. break;
  1449. }
  1450.  
  1451. case ID_MENU_RELOAD_STAGES:
  1452. {
  1453. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1454. {
  1455. if(g_game.reloadInfo(RELOAD_STAGES))
  1456. std::clog << "Reloaded stages." << std::endl;
  1457. }
  1458.  
  1459. break;
  1460. }
  1461.  
  1462. case ID_MENU_RELOAD_TALKACTIONS:
  1463. {
  1464. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1465. {
  1466. if(g_game.reloadInfo(RELOAD_TALKACTIONS))
  1467. std::clog << "Reloaded talk actions." << std::endl;
  1468. }
  1469.  
  1470. break;
  1471. }
  1472.  
  1473. case ID_MENU_RELOAD_MODS:
  1474. {
  1475. if(g_game.getGameState() != GAMESTATE_STARTUP)
  1476. {
  1477. if(g_game.reloadInfo(RELOAD_MODS))
  1478. std::clog << "Reloaded mods." << std::endl;
  1479. }
  1480.  
  1481. break;
  1482. }
  1483.  
  1484. case ID_MENU_ABOUT_SERVER:
  1485. {
  1486. MessageBox(NULL, "The " SOFTWARE_NAME " is a custom OpenTibia Server.\n"
  1487. "The current server version is " SOFTWARE_VERSION "." MINOR_VERSION , "The " SOFTWARE_NAME , MB_OK);
  1488. break;
  1489. }
  1490.  
  1491. case ID_MENU_ABOUT_DEVELOPERS:
  1492. {
  1493. MessageBox(NULL, "The developers of The " SOFTWARE_NAME " are:\n"
  1494. SOFTWARE_DEVELOPERS".", "Developers", MB_OK);
  1495. break;
  1496. }
  1497.  
  1498. case ID_MENU_ABOUT_GUI_EXECUTABLE:
  1499. {
  1500. MessageBox(NULL, "The GUI executable for originally created by The Forgotten Server Team.\n", "GUI Executable", MB_OK);
  1501. break;
  1502. }
  1503.  
  1504. case ID_MENU_OTSERV:
  1505. {
  1506. ShellExecute(NULL, "open", "http://blacktibia.org/",
  1507. NULL, NULL, SW_SHOWNORMAL);
  1508. break;
  1509. }
  1510.  
  1511. case ID_MENU_OTSERV2:
  1512. {
  1513. ShellExecute(NULL, "open", "http://tibiaking.com/",
  1514. NULL, NULL, SW_SHOWNORMAL);
  1515. break;
  1516. }
  1517.  
  1518. case ID_MENU_OTSERV3:
  1519. {
  1520. ShellExecute(NULL, "open", "http://otland.net/",
  1521. NULL, NULL, SW_SHOWNORMAL);
  1522. break;
  1523. }
  1524.  
  1525. case ID_MENU_OT_SERVERLIST:
  1526. {
  1527. ShellExecute(NULL, "open", "http://www.otservlist.org",
  1528. NULL, NULL, SW_SHOWNORMAL);
  1529. break;
  1530. }
  1531.  
  1532. case ID_MENU_BUG_FEATURE:
  1533. {
  1534. ShellExecute(NULL, "open", "https://code.google.com/p/otservdata/issues/list",
  1535. NULL, NULL, SW_SHOWNORMAL);
  1536. break;
  1537. }
  1538.  
  1539. case ID_MENU_SERVER_SOURCE:
  1540. {
  1541. ShellExecute(NULL, "open", "http://code.google.com/p/otservdata/source/list",
  1542. NULL, NULL, SW_SHOWNORMAL);
  1543. break;
  1544. }
  1545.  
  1546. default:
  1547. break;
  1548. }
  1549.  
  1550. break;
  1551. }
  1552.  
  1553. case WM_CLOSE:
  1554. case WM_DESTROY:
  1555. {
  1556. if(MessageBox(hwnd, "Are you sure you want to shutdown the server?", "Shutdown", MB_YESNO) == IDYES)
  1557. {
  1558. Shell_NotifyIcon(NIM_DELETE, &NID);
  1559. Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::setGameState, &g_game, GAMESTATE_SHUTDOWN)));
  1560. }
  1561.  
  1562. break;
  1563. }
  1564.  
  1565. case WM_USER + 1: // tray icon messages
  1566. {
  1567. switch(lParam)
  1568. {
  1569. case WM_RBUTTONUP: // right click
  1570. {
  1571. POINT mp;
  1572. GetCursorPos(&mp);
  1573. TrackPopupMenu(GetSubMenu(GUI::getInstance()->m_trayMenu, 0), 0, mp.x, mp.y, 0, hwnd, 0);
  1574. break;
  1575. }
  1576.  
  1577. case WM_LBUTTONUP: // left click
  1578. {
  1579. if(GUI::getInstance()->m_minimized)
  1580. {
  1581. ShowWindow(hwnd, SW_SHOW);
  1582. ShowWindow(hwnd, SW_RESTORE);
  1583. ModifyMenu(GUI::getInstance()->m_trayMenu, ID_TRAY_HIDE, MF_STRING, ID_TRAY_HIDE, "&Hide window");
  1584. GUI::getInstance()->m_minimized = false;
  1585. }
  1586.  
  1587. break;
  1588. }
  1589. }
  1590.  
  1591. break;
  1592. }
  1593.  
  1594. default:
  1595. return DefWindowProc(hwnd, message, wParam, lParam);
  1596. }
  1597.  
  1598. return 0;
  1599. }
  1600.  
  1601. int32_t WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int32_t WindowStyle)
  1602. {
  1603. MSG messages;
  1604. WNDCLASSEX wincl;
  1605. GUI::getInstance()->initTrayMenu();
  1606. GUI::getInstance()->initFont();
  1607. wincl.hInstance = hInstance;
  1608. wincl.lpszClassName = "otxserver_gui";
  1609. wincl.lpfnWndProc = WindowProcedure;
  1610. wincl.style = CS_DBLCLKS;
  1611. wincl.cbSize = sizeof(WNDCLASSEX);
  1612. wincl.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ICON));
  1613. wincl.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ICON), IMAGE_ICON, 16, 16, 0);
  1614. wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
  1615. wincl.lpszMenuName = MAKEINTRESOURCE(ID_MENU);
  1616. wincl.cbClsExtra = 0;
  1617. wincl.cbWndExtra = 0;
  1618. wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
  1619. if(!RegisterClassEx(&wincl))
  1620. return 0;
  1621.  
  1622. GUI::getInstance()->m_mainWindow = CreateWindowEx(0, "otxserver_gui", SOFTWARE_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 450, HWND_DESKTOP, NULL, hInstance, NULL);
  1623. ShowWindow(GUI::getInstance()->m_mainWindow, 1);
  1624. while(GetMessage(&messages, NULL, 0, 0))
  1625. {
  1626. TranslateMessage(&messages);
  1627. DispatchMessage(&messages);
  1628. }
  1629.  
  1630. return messages.wParam;
  1631. }
  1632. #endif
Advertisement
Add Comment
Please, Sign In to add comment