Clone of UAS2 @ https://github.com/drudgedance/uas2

CharacterServer.cpp 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /*
  2. * This file is part of UAS2.
  3. *
  4. * UAS2 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 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * UAS2 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. * You should have received a copy of the GNU General Public License
  14. * along with UASv1; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. /**
  18. * @file CharacterServer.cpp
  19. * Handles the CharacterServer.
  20. *
  21. * CharacterServer handles interactions with clients outside of the server game world.
  22. * Actions include account verification, providing the character list, the creation and deletion
  23. * of characters, and the connection and disconnection of clients.
  24. */
  25. #include <sstream>
  26. #include "Client.h"
  27. #include "CharacterServer.h"
  28. #include "MasterServer.h"
  29. #include "RecvPacket.h"
  30. #include "VersionNo.h"
  31. // Initialize static members
  32. //================================================
  33. DWORD cCharacterServer::m_dwSendCRCSeed;
  34. DWORD cCharacterServer::m_dwRecvCRCSeed;
  35. WORD cCharacterServer::m_wLogicalID;
  36. SOCKET cCharacterServer::m_Socket;
  37. DWORD cCharacterServer::m_dwClientCount;
  38. //DWORD cCharacterServer::ReturnPadOffset( DWORD dwLength );
  39. DWORD dwClientCount;
  40. //================================================
  41. static BYTE PacketTwo[122] = { // Nov Patch
  42. 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
  43. 0x67, 0x4A, 0x83, 0x6A,
  44. 0x0B, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00,0x00, //0x01, 0x00,
  45. 0x52, 0x5B, 0x95, 0x5B,
  46. 0xC9, 0x9A, 0x97, 0x41,
  47. 0x00, 0x00, 0x00, 0x00,
  48. 0x00, 0x00, 0x00, 0x00,
  49. 0xB2, 0x00, 0x0C, 0x00,
  50. // Byte 41
  51. 0x00, 0x00, 0x32, 0x30, 0x30, 0x34, 0x2E, 0x30, 0x31, 0x2E, 0x30, 0x30, 0x31, 0x00, 0x00, 0x20, 0x00, 0x20, // 58 bytes
  52. // Keep below from Dec Client
  53. 0x3C, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x33, 0x08, 0x00, 0x00, 0x00,
  54. 0xFB, 0x63, 0xC5, 0x08, 0x16, 0xC7, 0x80, 0x31, 0xFF, 0x43, 0xE5, 0xFE,
  55. 0x8A, 0xF3, 0xE3, 0x69, 0x23, 0xCF, 0xF8, 0x82, 0xB9, 0xC4, 0x59, 0x80,
  56. 0x99, 0x30, 0xB6, 0x08, 0xE5, 0xC2, 0x80, 0xDD, 0xBB, 0xAD, 0xCD, 0xAD,
  57. 0x03, 0x00, 0x00, 0x00, 0xF8, 0xCA, 0xEF, 0x74, 0x54, 0x9E, 0xFC, 0x4B,
  58. 0x85, 0x48, 0xDF, 0xBB, // 122 bytes
  59. };
  60. static BYTE PacketThree[250] = {
  61. 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xD7, 0xA2, 0xCD, 0x6B, 0x0B, 0x00, 0x00, 0x00, //(____@______k____)
  62. 0xE6, 0x00, 0x00, 0x00, 0xE3, 0x5B, 0x4C, 0x6F, 0xE6, 0xD4, 0x8F, 0x41,
  63. 0x00, 0x00, 0x00, 0x00, //(_____[Lo___A____)
  64. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  65. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  68. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  69. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  71. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  74. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  75. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  76. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(________________)
  77. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //(__________)
  78. };
  79. static BYTE UserName[44] = { // This is the tail of the Char list used in the June+ Clients
  80. 0xEF,0xBE,0xEF,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  81. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  82. 0x00,0x00,0x00,0x00,0x00,0x00,
  83. };
  84. static char szClientVersion[12] = {
  85. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  86. };
  87. static char szBadClientVersion[12] = {
  88. 0x32, 0x30, 0x30, 0x34, 0x2E, 0x30, 0x31, 0x2E, 0x30, 0x30, 0x31, 0x00
  89. };
  90. static byte Invalid2[24] = {
  91. 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5F, 0x72, 0x6B, 0xBD,
  92. 0x15, 0x00, 0x7A, 0x02, 0x04, 0x00, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00,
  93. };
  94. std::string aMonth[12] = { "January","February","March","April","May","June","July","August","September","October","November","December"};
  95. /**
  96. * Processes Character Server packets
  97. *
  98. * This function is called when the client sends a general Character Server message.
  99. * These encompass the actions performed by a client when outside of the server game world.
  100. */
  101. void cClient::ProcessPacket_CS( cRecvPacket *pcRecvPacket )
  102. {
  103. m_dwLastRecvTime = timeGetTime( );
  104. switch ( pcRecvPacket->GetFlags( ) )
  105. {
  106. //Client logout
  107. case 0x00000020:
  108. {
  109. cMasterServer::DisconnectClient( this );
  110. if(cMasterServer::m_dwNumUsers > 0)
  111. {
  112. cMasterServer::m_dwNumUsers--;
  113. }
  114. return ;
  115. }
  116. case 0x000000004:
  117. {
  118. DWORD dwLastGoodSeq;
  119. m_PacketPipe_CS.m_wTime = pcRecvPacket->GetTime( );
  120. pcRecvPacket->CopyPayload( 0, &dwLastGoodSeq, 4 );
  121. m_PacketPipe_CS.ClearSentPackets( dwLastGoodSeq );
  122. return ;
  123. }
  124. case 0x00100000:
  125. case 0x00200200:
  126. case 0x00000200:
  127. {
  128. m_PacketPipe_CS.m_dwRecvSequence = pcRecvPacket->GetSequence( );
  129. m_PacketPipe_CS.m_wTime = pcRecvPacket->GetTime( );
  130. if ( pcRecvPacket->GetFlags( ) == 0x00100000 )
  131. {
  132. m_PacketPipe_CS.ReturnPing( m_saSockAddr );
  133. return ;
  134. }
  135. break; // case 0x00100000, case 0x00200200, and case 0x00000200
  136. }
  137. }
  138. #ifdef _DEBUG
  139. char szPacketA[100];
  140. sprintf( szPacketA, "Character Server Packet: %08x ",pcRecvPacket->GetFlags( ));
  141. cMasterServer::WriteToFile(szPacketA);
  142. //cMasterServer::ServerMessage( ColorGreen,this,(char *)szPacketA);
  143. #endif
  144. switch ( m_bCharState )
  145. {
  146. case 1:
  147. {
  148. if ( pcRecvPacket->GetFlags( ) == 0x00000000 )
  149. {
  150. m_bCharState = 2;
  151. bool bClientOk = false;
  152. CopyMemory( &szClientVersion[0], pcRecvPacket->GetPayload( 06 ), 12 ); // Connecting client version
  153. //If the client is of the correct version
  154. if((szClientVersion[0] == 0x32)&&(szClientVersion[1] == 0x30)&&(szClientVersion[2] == 0x30)&&(szClientVersion[3] == 0x34))
  155. {
  156. bClientOk = true;
  157. }
  158. char szLoginInfo[45];
  159. char szPasswordInfo[45];
  160. WORD wLength;
  161. CopyMemory(&wLength, pcRecvPacket->GetPayload(32),2);
  162. if(szClientVersion[3] == '4')
  163. {
  164. // <-- Post 012704 Clients
  165. CopyMemory( szLoginInfo, pcRecvPacket->GetPayload( 34 ), wLength );
  166. }
  167. else if(szClientVersion[0] == '5')
  168. {
  169. // Sentinel Client
  170. CopyMemory( szLoginInfo, pcRecvPacket->GetPayload( 76 ), 44 );
  171. }
  172. else
  173. {
  174. //<-- Pre 012704 Clients
  175. CopyMemory( szLoginInfo, pcRecvPacket->GetPayload( 74 ), 44 ); // Dec-> (80), 44); June-> (74), 44);
  176. }
  177. szLoginInfo[wLength] = '\0';
  178. char* pszSep = strchr(szLoginInfo, (int)':');
  179. char szIP[32];
  180. cMasterServer::FormatIP_Port( m_saSockAddr, szIP );
  181. //Display console text information for a client login attempt
  182. m_wAccountNameLength = pszSep-szLoginInfo;
  183. CopyMemory( m_szAccountName, szLoginInfo,m_wAccountNameLength );
  184. m_szAccountName [m_wAccountNameLength] = '\0';
  185. UpdateConsole( " Client login attempt:\r\n"
  186. " User: %s\r\n"
  187. " IP: %s\r\n", m_szAccountName,szIP);
  188. //If no password is provided
  189. if(pszSep == NULL)
  190. {
  191. UpdateConsole( " Invalid login information from IP %s.\r\n ", szIP );
  192. cClient::Hash_Remove( this );
  193. break;
  194. }
  195. else
  196. {
  197. *pszSep = '\0';
  198. ++pszSep;
  199. CopyMemory( &UserName[0], szLoginInfo, sizeof(szLoginInfo) ); // Added for June Client
  200. cMasterServer::m_dwNumUsers++;
  201. }
  202. if( bClientOk == true)
  203. {
  204. CopyMemory( szPasswordInfo, pszSep,wLength );
  205. if ( !cDatabase::VerifyAccount( szLoginInfo, szPasswordInfo, m_dwAccountID, TRUE ))
  206. {
  207. UpdateConsole( " <SQL> No matching account found.\r\n" );
  208. bClientOk = false;
  209. //cClient::Hash_Remove( this );
  210. //cMasterServer::DeleteClient( m_saSockAddr );
  211. //break; // case 1
  212. }
  213. else
  214. {
  215. UpdateConsole( " <SQL> Account verified.\r\n" );
  216. }
  217. }
  218. else
  219. {
  220. UpdateConsole( " Invalid client connection attempt.\r\n" );
  221. }
  222. m_dwLastRecvTime = 0;
  223. //If the client is of the correct version
  224. if(bClientOk == true)
  225. {
  226. CopyMemory( &PacketTwo[42],szClientVersion,12);
  227. m_PacketPipe_CS.CalcCRC( PacketTwo, 102 );
  228. sendto( m_PacketPipe_CS.m_Socket, (char *)PacketTwo, sizeof( PacketTwo ), NULL, (SOCKADDR *)&m_saSockAddr, sizeof( SOCKADDR ) );
  229. }
  230. else
  231. {
  232. CopyMemory( &PacketTwo[42],szBadClientVersion,12);
  233. m_PacketPipe_CS.CalcCRC( PacketTwo, 102 );
  234. sendto( m_PacketPipe_CS.m_Socket, (char *)PacketTwo, sizeof( PacketTwo ), NULL, (SOCKADDR *)&m_saSockAddr, sizeof( SOCKADDR ) );
  235. cClient::Hash_Remove( this );
  236. }
  237. }
  238. break; //case 1
  239. }
  240. case 2:
  241. {
  242. if ( pcRecvPacket->GetFlags( ) == 0x00000080 )
  243. {
  244. m_bCharState = 3;
  245. m_PacketPipe_CS.CalcCRC( PacketThree, 230 );
  246. for ( int i = 0; i < 10; ++i )
  247. sendto( m_PacketPipe_CS.m_Socket, (char *)PacketThree, sizeof( PacketThree ), NULL, (SOCKADDR *)&m_saSockAddr, sizeof( SOCKADDR ) );
  248. }
  249. break; //case 2
  250. }
  251. case 3:
  252. {
  253. if ( pcRecvPacket->GetFlags( ) == 0x00000040 )
  254. {
  255. m_bCharState = 4;
  256. SendPacketF7B8( );
  257. cDatabase::LoadAvatarList( m_dwAccountID, m_AvatarList );
  258. SendAvatarList( );
  259. SendMOTD( );
  260. }
  261. break; //case 3
  262. }
  263. case 4:
  264. {
  265. if ( pcRecvPacket->GetFlags( ) & 0x00000200 )
  266. {
  267. DWORD dwMsgId;
  268. pcRecvPacket->CopyPayload( 16, &dwMsgId, sizeof( DWORD ) );
  269. switch(dwMsgId)
  270. {
  271. case 0xF7C8L:
  272. SendPacketF7C7( );
  273. break;
  274. //Avatar deletion
  275. case 0xF655:
  276. {
  277. //AvatarDeleteMessage *adm = (AvatarDeleteMessage*)pcRecvPacket->GetPayload( 16 );
  278. AvatarDeleteMessage adm;
  279. pcRecvPacket->CopyPayload(16, &adm, 6 );
  280. pcRecvPacket->CopyPayload( 16 + 6, adm.szAccountName, adm.wNameLength + 1);
  281. pcRecvPacket->CopyPayload( 16 + 6 + adm.wNameLength + cCharacterServer::ReturnPadOffset(adm.wNameLength), &adm.dwSlot, 8 );
  282. cDatabase::DeleteAvatar( (m_AvatarList.begin() + adm.dwSlot)->m_dwGUID );
  283. m_AvatarList.erase( m_AvatarList.begin() + adm.dwSlot );
  284. AddPacket( CHAR_SERVER, (unsigned char*)&dwMsgId, sizeof( dwMsgId ), 4 );
  285. SendDeleteAck( );
  286. SendAvatarList( );
  287. break;
  288. }
  289. //Character creation
  290. case 0xF656L:
  291. {
  292. CreateCharacterMessage ccm;
  293. pcRecvPacket->CopyPayload( 16, &ccm, 6 );
  294. //ccm.szAccountName = new char[ccm.wLengthOfAccountName + 1];
  295. pcRecvPacket->CopyPayload( 16 + 6, ccm.szAccountName, ccm.wLengthOfAccountName + 1);
  296. pcRecvPacket->CopyPayload( 16 + 6 + ccm.wLengthOfAccountName + cCharacterServer::ReturnPadOffset(ccm.wLengthOfAccountName), &ccm.dwValOne, 152 );
  297. pcRecvPacket->CopyPayload( 16 + 6 + ccm.wLengthOfAccountName + cCharacterServer::ReturnPadOffset(ccm.wLengthOfAccountName) + 152, &ccm.dwNumSkills, 4 );
  298. pcRecvPacket->CopyPayload( 16 + 6 + ccm.wLengthOfAccountName + cCharacterServer::ReturnPadOffset(ccm.wLengthOfAccountName) + 152 + 4, &ccm.dwSkillStatus, 4 * ccm.dwNumSkills );
  299. pcRecvPacket->CopyPayload( 16 + 6 + ccm.wLengthOfAccountName + cCharacterServer::ReturnPadOffset(ccm.wLengthOfAccountName) + 152 + 4 + (4 * ccm.dwNumSkills), &ccm.wNameLength, 2 );
  300. pcRecvPacket->CopyPayload( 16 + 6 + ccm.wLengthOfAccountName + cCharacterServer::ReturnPadOffset(ccm.wLengthOfAccountName) + 152 + 4 + (4 * ccm.dwNumSkills) + 2, ccm.szName, ccm.wNameLength);
  301. ccm.szName[ccm.wNameLength] = '\0'; //fix the name from name padding
  302. DWORD Test;
  303. Test = cCharacterServer::ReturnPadOffset(ccm.wLengthOfAccountName);
  304. //Cubem0j0: Test to see what is returned for character name as this does not appear to work.
  305. FILE* pFile = cMasterServer::pFile;
  306. pFile = fopen( "server.log", "wa" );
  307. setbuf(pFile,NULL);
  308. cMasterServer::WriteToFile(ccm.szName);
  309. //End test
  310. pcRecvPacket->CopyPayload( ((cFragmentHeader*)(pcRecvPacket->m_bData+20))->m_wFragmentLength - 16, &ccm.dwUnk4, 16);
  311. cAvatarList cAL;
  312. if( cDatabase::CreateAvatar( m_dwAccountID, ccm, cAL.m_dwGUID ) ) //Create avatar
  313. {
  314. cMessage cMsg;
  315. cMsg << 0xF7B0L << 0L << 0L << 0xF643L << 1L << cAL.m_dwGUID << ccm.szName << 0L;
  316. AddPacket( CHAR_SERVER, cMsg, 4);
  317. cAL.m_strName = ccm.szName;
  318. m_AvatarList.push_back(cAL);
  319. SendAvatarList( );
  320. }
  321. else
  322. {
  323. cMessage cMsg;
  324. cMsg << 0xF7B0L << 0L << 0L << 0xF643L << 3L << 0xBEEFBEEF << ccm.szName << 0L;
  325. AddPacket( CHAR_SERVER, cMsg, 4);
  326. }
  327. //SAFEDELETE_ARRAY( ccm.szAccountName )
  328. //SAFEDELETE_ARRAY( ccm.szName )
  329. break;
  330. }
  331. //Avatar creation
  332. case 0xF657L:
  333. cMasterServer::CreateNewAvatar( &m_pcAvatar, ((DWORD*)&(*pcRecvPacket)[0])[0x0A] );
  334. m_pcAvatar->m_wNumLogins = 0x3C;
  335. m_pcAvatar->m_wModelSequenceType = 0xC6;
  336. m_pcAvatar->m_wModelSequence = 0x0;
  337. SendAddress( g_szLocalIP, g_nWorldPort );
  338. m_bCharState = 6;
  339. break;
  340. }
  341. }
  342. break; // case 4
  343. }
  344. case 6:
  345. {
  346. if ( pcRecvPacket->GetFlags( ) == 0x00020000 )
  347. m_bCharState = 7;
  348. else
  349. SendAddress( g_szLocalIP, g_nWorldPort );
  350. break; // case 6
  351. }
  352. case 7:
  353. {
  354. break; // case 7
  355. }
  356. //Client connection (to the server page)
  357. case 8:
  358. {
  359. m_bCharState = 4;
  360. SendAvatarList( ); //Send avatar list
  361. SendMOTD( ); //Send message of the day
  362. DWORD dwEnd3D = 0xF653;
  363. AddPacket( CHAR_SERVER, (BYTE *)&dwEnd3D, 4, 4 );
  364. if(cCharacterServer::m_dwClientCount > 0)
  365. {
  366. cCharacterServer::m_dwClientCount--;
  367. }
  368. break; // case 8
  369. }
  370. }
  371. }
  372. /**
  373. * Sends the client its list of avatars on the server
  374. *
  375. * This function is called whenever a client connects to a server
  376. * Returns a server message to the client.
  377. */
  378. void cClient::SendAvatarList( )
  379. {
  380. cMessage cMsg;
  381. cMsg << 0xF658L << 0x0000L << m_AvatarList.size();
  382. //Iterate through the client's avatar list
  383. for( std::vector<cAvatarList>::iterator ical = m_AvatarList.begin(); ical != m_AvatarList.end(); ical++ )
  384. {
  385. cMsg << ical->m_dwGUID << ical->m_strName.c_str( );
  386. cMsg.pasteAlign(4);
  387. cMsg << 0L;
  388. }
  389. cMsg << 0L << 5L; //Dec Client ends here
  390. //June Client addition starts here
  391. for (int ib = 0; ib < 45; ib++)
  392. {
  393. if ((UserName[ib]) == 0)
  394. {
  395. break;
  396. }
  397. }
  398. cMsg << WORD(ib);
  399. cMsg.pasteData(UserName,ib);
  400. //for (int ia = 0; ia < (45 - ib); ia++)
  401. //{
  402. // cMsg << BYTE(0x00);
  403. //}
  404. cMsg.pasteAlign(4);
  405. cMsg << DWORD(0x0L);
  406. //June Client ends here
  407. AddPacket( CHAR_SERVER, cMsg, 4 );
  408. }
  409. void cClient::SendDeleteAck( )
  410. {
  411. cMessage cAckMsg;
  412. cAckMsg << 0xF655L << 0x00108F04;
  413. AddPacket( CHAR_SERVER, cAckMsg, 4 );
  414. }
  415. /**
  416. * Sends the client the server Message of the Day
  417. *
  418. * This function is called whenever a client connects to a server
  419. * Returns a server message to the client.
  420. */
  421. void cClient::SendMOTD( )
  422. {
  423. FILE *pcMOTD = fopen( "Server.motd","rt" );
  424. std::stringstream strstrm;
  425. std::stringstream strstrm2;
  426. SYSTEMTIME st;
  427. GetSystemTime( &st );
  428. char str[20] ={0,};
  429. CopyMemory( &str[0], &STRFILEVER, sizeof(STRFILEVER) );
  430. for(int a = 0;a<strlen(str);a++)
  431. {
  432. if(str[a] == ',')
  433. {
  434. str[a] = '.';
  435. }
  436. }
  437. //The Message of the Day text
  438. strstrm << "Currently " << cMasterServer::m_UserCount << " user(s) playing.\n";//cCharacterServer::m_dwClientCount << " clients connected.\n";
  439. strstrm2 << "You are in the World of " << cMasterServer::m_szServerName << ".\n";
  440. strstrm2 << "\nWelcome to Asheron's Call!\n\n";
  441. strstrm2 << aMonth[st.wMonth -1] << " " << st.wDay << ", " << st.wYear << "\n";
  442. strstrm2 << "=================\n";
  443. strstrm2 << " This emulator is powered by\n";
  444. strstrm2 << " UAS2: http://uastwo.googlecode.com\n";
  445. strstrm2 << " Debug Build Copy\n";
  446. strstrm2 << " Server Version " << SERVERVERSION <<" v";
  447. strstrm2 << str << "\n";
  448. strstrm2 << "=================\n";
  449. strstrm2 << " Developers:\n";
  450. strstrm2 << " Cubem0j0\n";
  451. strstrm2 << " eLeM\n";
  452. strstrm2 << " agentsparrow\n";
  453. strstrm2 << "=================\n";
  454. strstrm2 << " Special thanks to:\n";
  455. strstrm2 << " Johnnyjpg -> For webspace to host our forum!\n";
  456. strstrm2 << " k109 -> For project management assistance.\n";
  457. strstrm2 << " Paaa -> For helping to test early releases.\n";
  458. strstrm2 << " And all of the fans at http://forum.johnnyjpg.com!\n";
  459. strstrm2 << "=================\n";
  460. if ( pcMOTD )
  461. {
  462. char buff[65536];
  463. while ( !feof( pcMOTD ) )
  464. {
  465. fgets( buff, 65535, pcMOTD );
  466. strstrm << buff;
  467. }
  468. fclose( pcMOTD );
  469. }
  470. cMessage cMsg;
  471. cMsg << 0xF65AL << strstrm.str( ).c_str( ) << strstrm2.str( ).c_str( );
  472. AddPacket( CHAR_SERVER, cMsg, 4 );
  473. }
  474. void cClient::SendAddress( char *szAddr, WORD wPort )
  475. {
  476. BYTE pbSendBuffer[0x60];
  477. SOCKADDR_IN *saSockAddr = (SOCKADDR_IN *)&pbSendBuffer[0x14];
  478. cTransportHeader *pcTH = reinterpret_cast< cTransportHeader * >( pbSendBuffer );
  479. pcTH->m_dwSequence = 0;
  480. pcTH->m_dwFlags = 0x00020000;
  481. pcTH->m_wLogicalID = m_PacketPipe_CS.m_wLogicalID;
  482. pcTH->m_wTotalSize = 0x10;
  483. pcTH->m_wTime = 0;
  484. pcTH->m_wTable = 0;
  485. saSockAddr->sin_family = AF_INET;
  486. saSockAddr->sin_port = htons( wPort );
  487. saSockAddr->sin_addr.s_addr = inet_addr( szAddr );
  488. ZeroMemory( &saSockAddr->sin_zero, 8 );
  489. m_PacketPipe_CS.CalcCRC( pbSendBuffer, 16 );
  490. sendto( m_PacketPipe_CS.m_Socket, (char *)pbSendBuffer, 36, NULL, (SOCKADDR *)&m_saSockAddr, sizeof( SOCKADDR ) );
  491. }
  492. /**
  493. * Pads messages to the DWORD boundary.
  494. *
  495. * Used for variable-length (text/char[]) fields.
  496. * The client expects the next variable to start at the next whole DWORD (4 byte value)
  497. * The variable length field is zero-padded until this boundary is reached.
  498. *
  499. * @param dwLength - The length of the variable-length field.
  500. *
  501. * @return dwOffset - The BYTE value of padding required.
  502. */
  503. DWORD cCharacterServer::ReturnPadOffset( DWORD dwLength )
  504. {
  505. DWORD dwOffset;
  506. int intTest;
  507. intTest = ((dwLength + 2) % 4);
  508. switch(intTest)
  509. {
  510. case 0:
  511. {
  512. dwOffset = 0;
  513. break;
  514. }
  515. case 1:
  516. {
  517. dwOffset = 3;
  518. break;
  519. }
  520. case 2:
  521. {
  522. dwOffset = 2;
  523. break;
  524. }
  525. case 3:
  526. {
  527. dwOffset = 1;
  528. break;
  529. }
  530. default:
  531. {
  532. dwOffset = 0;
  533. break;
  534. }
  535. }
  536. return dwOffset; // Returns DWORD alignment padding amount
  537. }