Clone of PhatAC @ https://github.com/floaterxk/PhatAC

Server.cpp 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "StdAfx.h"
  2. #include "Server.h"
  3. #include "Rules.h"
  4. #include "Database.h"
  5. #include "World.h"
  6. #include "Network.h"
  7. #include "BinaryWriter.h"
  8. #include "ChatMsgs.h"
  9. #include "Database2.h"
  10. CDatabase *g_pDB = 0;
  11. CMYSQLDatabase *g_pDB2 = 0;
  12. CGameDatabase *g_pGameDatabase = 0;
  13. CWorld *g_pWorld = 0;
  14. CNetwork *g_pNetwork = 0;
  15. TURBINEPORTAL *g_pPortal = 0;
  16. TURBINECELL *g_pCell = 0;
  17. GAMERULES *g_pGameRules = 0;
  18. CPhatServer::CPhatServer(in_addr hostmachine, u_short hostport)
  19. {
  20. m_lastframe = g_pGlobals->m_CounterTime;
  21. m_frames = 0;
  22. //
  23. memcpy(&m_hostaddr, &hostmachine, sizeof(in_addr));
  24. m_hostport = hostport;
  25. g_pGlobals->ResetPackets();
  26. m_socketCount = 10;
  27. for (int i = 0; i < m_socketCount; i++)
  28. m_sockets[i] = INVALID_SOCKET;
  29. InitializeSocket(hostport);
  30. g_pPortal = new TURBINEPORTAL();
  31. g_pCell = new TURBINECELL();
  32. g_pGameRules = new GAMERULES();
  33. g_pDB = new CDatabase; // Old, dumb, bad
  34. g_pDB2 = new CMYSQLDatabase("127.0.0.1", 0, "root", "", "phatac"); // Newer, shiny, makes pancakes in the morning
  35. g_pGameDatabase = new CGameDatabase();
  36. g_pWorld = new CWorld();
  37. g_pNetwork = new CNetwork(m_sockets, m_socketCount);
  38. g_pGameDatabase->Init();
  39. LOG(Temp, Normal, "The server is now online.\n");
  40. int missing = 0;
  41. int has = 0;
  42. int missingE = 0;
  43. int hasE = 0;
  44. int hasD = 0;
  45. int missingD = 0;
  46. int hasUD = 0;
  47. int hasUDT = 0;
  48. int hasM = 0;
  49. int missingM = 0;
  50. FILE *fp = NULL;
  51. #if 0 // ndef _DEBUG
  52. if (GetAsyncKeyState(VK_F12))
  53. {
  54. fp = fopen("missingCells.txt", "wt");
  55. }
  56. for (int i = 0; i <= 0xFFFF; i++)
  57. {
  58. if (!g_pCell->FileExists((i << 16) | 0xFFFF))
  59. {
  60. missing++;
  61. }
  62. else
  63. {
  64. has++;
  65. if (TURBINEFILE *pCell = g_pCell->GetFile((i << 16) | 0xFFFF))
  66. {
  67. if (pCell->GetLength() >= 8)
  68. {
  69. DWORD value = ((DWORD *)pCell->GetData())[1];
  70. if (value)
  71. {
  72. if (!g_pCell->FileExists((i << 16) | 0xFFFE))
  73. {
  74. missingE++;
  75. }
  76. else
  77. {
  78. hasE++;
  79. if (TURBINEFILE *pCellData = g_pCell->GetFile((i << 16) | 0xFFFE))
  80. {
  81. DWORD value = ((DWORD *)pCellData->GetData())[1];
  82. if (value >= 10000)
  83. {
  84. __asm int 3;
  85. }
  86. for (unsigned int j = 0; j < value; j++)
  87. {
  88. if (g_pCell->FileExists((i << 16) | (0x100 + j)))
  89. {
  90. if (TURBINEFILE *pEnvData = g_pCell->GetFile((i << 16) | (0x100 + j)))
  91. {
  92. BYTE *ptr = pEnvData->GetData();
  93. ptr += 12;
  94. BYTE numSurface = *ptr;
  95. ptr += 4;
  96. ptr += 2 * numSurface;
  97. WORD envID = *(WORD *)ptr;
  98. if (g_pPortal->FileExists(0x0D000000UL | envID))
  99. {
  100. hasM++;
  101. }
  102. else
  103. {
  104. missingM++;
  105. }
  106. delete pEnvData;
  107. }
  108. hasD++;
  109. }
  110. else
  111. {
  112. if (fp)
  113. {
  114. fprintf(fp, "%08X\n", (i << 16) | (0x100 + j));
  115. }
  116. missingD++;
  117. }
  118. }
  119. delete pCellData;
  120. }
  121. }
  122. }
  123. }
  124. delete pCell;
  125. }
  126. }
  127. }
  128. if (fp)
  129. {
  130. fclose(fp);
  131. }
  132. LOG(Temp, Normal, "Has %u landblocks, missing %u (%.2f%%)\n", has, missing, ((float)has / (has+missing)) * 100.00);
  133. LOG(Temp, Normal, "Has %u landblock environments, missing %u of the ones known (%.2f%%)\n", hasE, missingE, ((float)hasE / (hasE + missingE)) * 100.00);
  134. LOG(Temp, Normal, "Has %u dungeon cells, missing %u of the ones known (%.2f%%)\n", hasD, missingD, ((float)hasD / (hasD + missingD)) * 100.00);
  135. LOG(Temp, Normal, "Resolved %u dungeon meshes, missing %u of the ones attempted (%.2f%%)\n", hasM, missingM, ((float)hasM / (hasM + missingM)) * 100.00);
  136. #endif
  137. }
  138. CPhatServer::~CPhatServer()
  139. {
  140. if (g_pNetwork)
  141. {
  142. SystemBroadcast("ATTENTION - This Asheron's Call Server is shutting down NOW!!!!");
  143. g_pNetwork->Think();
  144. SafeDelete(g_pNetwork);
  145. }
  146. SafeDelete(g_pWorld);
  147. SafeDelete(g_pGameDatabase);
  148. SafeDelete(g_pDB2);
  149. SafeDelete(g_pDB);
  150. SafeDelete(g_pGameRules);
  151. SafeDelete(g_pCell);
  152. SafeDelete(g_pPortal);
  153. for (int i = 0; i < m_socketCount; i++)
  154. {
  155. if (m_sockets[i] != INVALID_SOCKET)
  156. {
  157. closesocket(m_sockets[i]);
  158. m_sockets[i] = INVALID_SOCKET;
  159. }
  160. }
  161. }
  162. void CPhatServer::InitializeSocket(u_short port)
  163. {
  164. SOCKADDR_IN localhost;
  165. localhost.sin_family = AF_INET;
  166. localhost.sin_addr.s_addr = INADDR_ANY;
  167. for (int i = 0; i < m_socketCount; i++)
  168. m_sockets[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  169. u_short startport = port;
  170. while (port < (startport + 30))
  171. {
  172. localhost.sin_port = htons(port);
  173. if (!bind(m_sockets[0], (struct sockaddr *)&localhost, sizeof(SOCKADDR_IN)))
  174. {
  175. LOG(Temp, Normal, "Bound to port %u!\n", port);
  176. break;
  177. }
  178. LOG(Temp, Normal, "Failed bind on port %u!\n", port);
  179. port++;
  180. }
  181. if (port == 9080)
  182. {
  183. LOG(Temp, Normal, "Failure to bind socket!\n");
  184. }
  185. else
  186. {
  187. SendMessage(GetDlgItem(g_pGlobals->GetWindowHandle(), IDC_SERVERPORT), WM_SETTEXT, 0, (LPARAM)csprintf("%u", port));
  188. int basePort = port;
  189. // Try to bind the other ports
  190. for (int i = 1; i < m_socketCount; i++)
  191. {
  192. localhost.sin_port = htons(basePort + i);
  193. if (bind(m_sockets[i], (struct sockaddr *)&localhost, sizeof(SOCKADDR_IN)))
  194. {
  195. LOG(Temp, Normal, "Failure to bind socket port %d!\n", basePort + i);
  196. }
  197. }
  198. }
  199. //Non-blocking sockets are more fun
  200. for (int i = 0; i < m_socketCount; i++)
  201. {
  202. unsigned long arg = 1;
  203. ioctlsocket(m_sockets[i], FIONBIO, &arg);
  204. }
  205. }
  206. void CPhatServer::SystemBroadcast(char *text)
  207. {
  208. if (!g_pNetwork || !g_pWorld)
  209. return;
  210. LOG(Temp, Normal, "Broadcast, \"%s\"\n", text);
  211. g_pWorld->BroadcastGlobal(ServerBroadcast("System", text, 1), PRIVATE_MSG);
  212. }
  213. void CPhatServer::Tick(void)
  214. {
  215. g_pGlobals->Update();
  216. if ((m_lastframe + g_pGlobals->m_CounterFreq) < g_pGlobals->m_CounterTime)
  217. {
  218. double timediff = (g_pGlobals->m_CounterTime - m_lastframe) / (double)g_pGlobals->m_CounterFreq;
  219. UpdateFramesHUD((UINT64)(m_frames / timediff));
  220. m_lastframe = g_pGlobals->m_CounterTime;
  221. m_frames = 0;
  222. }
  223. g_pNetwork->Think();
  224. g_pWorld->Think();
  225. g_pCell->Think();
  226. m_frames++;
  227. }
  228. u_short CPhatServer::GetPort()
  229. {
  230. return m_hostport;
  231. }
  232. void CPhatServer::KickClient(WORD index)
  233. {
  234. g_pNetwork->KickClient(index);
  235. }
  236. void CPhatServer::BanClient(WORD index)
  237. {
  238. KickClient(index); //for now
  239. }