Clone of Akilla's ac2d @ https://github.com/deregtd/AC2D

cNetwork.cpp 78KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864
  1. #include "stdafx.h"
  2. #include "cNetwork.h"
  3. //-a teqilla -h 74.201.102.233:9000
  4. bool SockCompare(SOCKADDR_IN *a, SOCKADDR_IN *b);
  5. bool SockCompare(SOCKADDR_IN *a, SOCKADDR_IN *b)
  6. {
  7. if ((memcmp(&a->sin_addr, &b->sin_addr, sizeof(in_addr)))
  8. ||
  9. (
  10. (a->sin_port != b->sin_port)
  11. &&
  12. (a->sin_port != b->sin_port + 0x0100)
  13. // XXX: Loginserver is retarded and sends from one port higher sometimes, so we have to account
  14. // and allow for that...
  15. )
  16. ) return false;
  17. return true;
  18. }
  19. cNetwork::cNetwork()
  20. {
  21. m_dwGUIDLogin = 0;
  22. f74ccount = 0;
  23. m_zPassword[0] = 0;
  24. WSADATA wsaData;
  25. USHORT wVR = 0x0202;
  26. WSAStartup( wVR, &wsaData );
  27. SOCKADDR_IN siSockAddr;
  28. siSockAddr.sin_family = AF_INET;
  29. siSockAddr.sin_addr.s_addr = INADDR_ANY;
  30. m_sSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
  31. iConnPacketCount = 0;
  32. bPortalMode = false;
  33. int iError = SOCKET_ERROR;
  34. int iSrcPort = 0; // binding to port "0" tells winsock to get a random open port
  35. while (iError == SOCKET_ERROR)
  36. {
  37. siSockAddr.sin_port = htons( iSrcPort );
  38. iError = bind(m_sSocket, (struct sockaddr *) &siSockAddr, sizeof(SOCKADDR_IN));
  39. iSrcPort++;
  40. }
  41. m_dwStartTicks = GetTickCount();
  42. m_zTicketSize = 0;
  43. char acServerIP[32];
  44. int acServerPort = 0;
  45. /* parse command line arguments */
  46. /* the options are the same as the original client */
  47. for (int arg=0; arg < __argc; arg++)
  48. {
  49. /* options always have two characters and start with '-' */
  50. if (strlen(__argv[arg]) != 2) { continue; }
  51. if (__argv[arg][0] == '-')
  52. {
  53. switch (__argv[arg][1])
  54. {
  55. /* server IP address */
  56. case 'h':
  57. {
  58. if (arg + 1 < __argc) {
  59. strcpy(acServerIP, __argv[arg+1]);
  60. if (strchr(acServerIP, ':') != NULL) {
  61. acServerPort = atoi(strchr(acServerIP, ':') + 1);
  62. *strchr(acServerIP, ':') = 0;
  63. }
  64. }
  65. break;
  66. }
  67. /* port number */
  68. case 'p':
  69. {
  70. if (arg + 1 < __argc) {
  71. acServerPort = atoi(__argv[arg+1]);
  72. }
  73. break;
  74. }
  75. /* account */
  76. case 'a':
  77. {
  78. if (arg + 1 < __argc) {
  79. ZeroMemory(m_zAccountName, 40);
  80. strcpy(m_zAccountName, __argv[arg+1]);
  81. // check if password is provided
  82. char* password_index = strchr(m_zAccountName, ':');
  83. if (password_index != NULL) {
  84. strcpy(m_zPassword, password_index + 1);
  85. // end account name string at the colon
  86. *password_index = 0;
  87. }
  88. }
  89. break;
  90. }
  91. /* password */
  92. case 'v':
  93. {
  94. if (arg + 1 < __argc) {
  95. ZeroMemory(m_zPassword, 100);
  96. strcpy(m_zPassword, __argv[arg+1]);
  97. }
  98. break;
  99. }
  100. }
  101. }
  102. }
  103. if (m_zPassword[0] == 0) {
  104. // password wasn't provided at command line so use GLSTicket
  105. HKEY hkTicket;
  106. if (!RegOpenKey(HKEY_CURRENT_USER, "Software\\Turbine\\AC1", &hkTicket))
  107. {
  108. m_zTicketSize = 0xf4;
  109. DWORD tpout = 0x100;
  110. if (RegQueryValueEx(hkTicket, "GLSTicket", NULL, NULL, m_zTicket, &tpout))
  111. {
  112. MessageBox(NULL, "GLSTicket not found!", "Error", MB_OK);
  113. }
  114. }
  115. }
  116. else {
  117. m_zTicketSize = 0;
  118. }
  119. m_siLoginServer.m_saServer.sin_family = AF_INET;
  120. m_siLoginServer.m_saServer.sin_addr.s_addr = inet_addr(acServerIP);
  121. m_siLoginServer.m_wBasePort = acServerPort;
  122. m_treeNameIDCache.clear();
  123. m_pActiveWorld = 0;
  124. Reset();
  125. }
  126. cNetwork::~cNetwork()
  127. {
  128. // Disconnect();
  129. // closesocket(m_sSocket);
  130. WSACleanup();
  131. }
  132. void cNetwork::Reset()
  133. {
  134. //Reset the login servers.
  135. for (std::list<cPacket *>::iterator it = m_siLoginServer.m_lSentPackets.begin(); it != m_siLoginServer.m_lSentPackets.end(); ++it)
  136. {
  137. delete (*it);
  138. }
  139. m_siLoginServer.m_lSentPackets.clear();
  140. m_siLoginServer.m_dwSendSequence = 0;
  141. m_siLoginServer.m_wLogicalID = 0;
  142. m_siLoginServer.m_wTable = 0;
  143. m_siLoginServer.m_dwFlags = 0;
  144. m_siLoginServer.m_dwLastPing = GetTickCount();
  145. m_siLoginServer.m_dwLastSyncSent = 0;
  146. m_siLoginServer.m_dwRecvSequence = 0;
  147. m_siLoginServer.m_dwLastPacketAck = GetTickCount();
  148. m_siLoginServer.m_dwLastPacketSent = GetTickCount();
  149. m_siLoginServer.m_dwLastConnectAttempt = GetTickCount();
  150. //Now the world servers..
  151. for (std::list<stServerInfo>::iterator i = m_siWorldServers.begin(); i != m_siWorldServers.end(); i++)
  152. {
  153. for (std::list<cPacket *>::iterator j = (*i).m_lSentPackets.begin(); j != (*i).m_lSentPackets.end(); ++j)
  154. {
  155. delete (*j);
  156. }
  157. (*i).m_lSentPackets.clear();//Not really necessary?
  158. }
  159. m_siWorldServers.clear();
  160. m_dwStartTicks = GetTickCount();
  161. m_dwGameEventOut = 0;
  162. // start 0. we pre-increment for each fragment so the first one out will be 1
  163. // XXX: should we be keeping track of this separately for each server? also when do we start it back at 0?
  164. m_dwFragmentSequenceOut = 0;
  165. }
  166. static DWORD checksum(const void* data, size_t size)
  167. {
  168. DWORD result = static_cast<DWORD>(size) << 16;
  169. for (size_t i = 0; i < size / 4; i++)
  170. {
  171. result += static_cast<const DWORD*>(data)[i];
  172. }
  173. int shift = 24;
  174. for (size_t i = (size / 4) * 4; i < size; i++)
  175. {
  176. result += static_cast<const BYTE*>(data)[i] << shift;
  177. shift -= 8;
  178. }
  179. return result;
  180. }
  181. static DWORD checksumHeader(stTransitHeader& header)
  182. {
  183. DWORD origChecksum = header.m_dwCRC;
  184. header.m_dwCRC = 0xBADD70DD;
  185. DWORD result = checksum(&header, sizeof(stTransitHeader));
  186. header.m_dwCRC = origChecksum;
  187. return result;
  188. }
  189. static DWORD checksumContent(stTransitHeader& header, const void* data)
  190. {
  191. if (header.m_dwFlags & kBlobFragments)
  192. {
  193. cByteStream reader((BYTE *) data, header.m_wSize);
  194. if (header.m_dwFlags & kServerSwitch)
  195. {
  196. reader.ReadGroup(8);
  197. }
  198. if (header.m_dwFlags & kRequestRetransmit)
  199. {
  200. DWORD nseq = reader.ReadDWORD();
  201. reader.ReadGroup(nseq * sizeof(DWORD));
  202. }
  203. if (header.m_dwFlags & kRejectRetransmit)
  204. {
  205. DWORD nseq = reader.ReadDWORD();
  206. reader.ReadGroup(nseq * sizeof(DWORD));
  207. }
  208. if (header.m_dwFlags & kAckSequence)
  209. {
  210. reader.ReadGroup(4);
  211. }
  212. if (header.m_dwFlags & kCICMDCommand)
  213. {
  214. reader.ReadGroup(8);
  215. }
  216. if (header.m_dwFlags & kTimeSync)
  217. {
  218. reader.ReadGroup(8);
  219. }
  220. if (header.m_dwFlags & kEchoRequest)
  221. {
  222. reader.ReadGroup(4);
  223. }
  224. if (header.m_dwFlags & kEchoResponse)
  225. {
  226. reader.ReadGroup(8);
  227. }
  228. if (header.m_dwFlags & kFlow)
  229. {
  230. reader.ReadGroup(6);
  231. }
  232. DWORD result = checksum(data, reader.GetOffset());
  233. while (!reader.AtEOF())
  234. {
  235. const stFragmentHeader* fragment = (stFragmentHeader*) reader.ReadGroup(sizeof(stFragmentHeader));
  236. reader.ReadGroup(fragment->m_wSize - sizeof(stFragmentHeader));
  237. result += checksum(fragment, fragment->m_wSize);
  238. }
  239. return result;
  240. }
  241. return checksum(data, header.m_wSize);
  242. }
  243. static DWORD checksumPacket(cPacket *packet, ChecksumXorGenerator * xorGen)
  244. {
  245. stTransitHeader *header = packet->GetTransit();
  246. DWORD xorVal = (header->m_dwFlags & kEncryptedChecksum) ? xorGen->get(header->m_dwSequence) : 0;
  247. return checksumHeader(*header) + (checksumContent(*header, packet->GetPayload()) ^ xorVal);
  248. }
  249. void cNetwork::SendPacket(cPacket *Packet, stServerInfo *Target, bool IncludeSeq, bool IncrementSeq)
  250. {
  251. #ifndef TerrainOnly
  252. if (!Target)
  253. return;
  254. stTransitHeader *Head = Packet->GetTransit();
  255. //calc size (remove header from length)
  256. Head->m_wSize = Packet->GetLength() - (int) sizeof(stTransitHeader);
  257. if (IncrementSeq)
  258. {
  259. Target->m_dwSendSequence++;
  260. }
  261. if (IncludeSeq) {
  262. Head->m_dwSequence = Target->m_dwSendSequence;
  263. Head->m_wTime = GetTime();
  264. }
  265. else {
  266. Head->m_dwSequence = 0;
  267. Head->m_wTime = 0;
  268. }
  269. if (Target->m_dwFlags & SF_CONNECTED) {
  270. Head->m_wID = Target->m_wLogicalID;
  271. Head->m_wTable = Target->m_wTable;
  272. }
  273. else {
  274. Head->m_wID = 0;
  275. Head->m_wTable = 0;
  276. }
  277. if (Packet->GetTransit()->m_dwFlags & kEncryptedChecksum)
  278. {
  279. if (!(Target->m_dwFlags & SF_CRCSEEDS)) {
  280. m_Interface->OutputConsoleString("WARNING: trying to send encrypted-checksum packet with no seeds (OK if loginserver)");
  281. }
  282. }
  283. Head->m_dwCRC = checksumPacket(Packet, Target->clientXorGen);
  284. SendPacket(Packet, Target);
  285. #endif
  286. }
  287. /* Send packet to login server */
  288. void cNetwork::SendLSPacket(cPacket *Packet, bool IncludeSeq, bool IncrementSeq)
  289. {
  290. return SendPacket(Packet, &m_siLoginServer, IncludeSeq, IncrementSeq);
  291. // stTransitHeader *Head = Packet->GetTransit();
  292. // //calc size (remove header from length)
  293. // Head->m_wSize = Packet->GetLength() - (int) sizeof(stTransitHeader);
  294. //if (IncrementSeq)
  295. //{
  296. // m_siLoginServer.m_dwSendSequence++;
  297. //}
  298. //if (IncludeSeq) {
  299. // Head->m_dwSequence = m_siLoginServer.m_dwSendSequence;
  300. // Head->m_wTime = GetTime();
  301. //}
  302. //else {
  303. // Head->m_dwSequence = 0;
  304. // Head->m_wTime = 0;
  305. //}
  306. //Head->m_wID = m_siLoginServer.m_wLogicalID;
  307. //Head->m_wTable = m_siLoginServer.m_wTable;
  308. //Head->m_dwCRC = checksumPacket(Packet, m_siLoginServer.clientXorGen);
  309. //SendPacket(Packet, &m_siLoginServer);
  310. }
  311. void cNetwork::SendLostPacket(int iSendSequence, stServerInfo *Target)
  312. {
  313. Lock();
  314. for (std::list<cPacket *>::iterator i = Target->m_lSentPackets.begin(); i != Target->m_lSentPackets.end(); i++)
  315. {
  316. cPacket *Packet = *i;
  317. if (Packet->GetTransit()->m_dwSequence == iSendSequence)
  318. {
  319. //Match
  320. m_Interface->OutputConsoleString("Resending %X (%X) on %s", iSendSequence, Packet->GetTransit()->m_dwFlags, inet_ntoa(Target->m_saServer.sin_addr));
  321. if (Packet->GetTransit()->m_dwFlags & 0x200)
  322. {
  323. Packet->GetTransit()->m_wTime = GetTime();
  324. Packet->GetTransit()->m_dwFlags = 0x00000201;
  325. //DWORD dwNewCRC;
  326. //Packet->GetTransit()->m_dwCRC = dwNewCRC;
  327. sendto(m_sSocket, (char *)Packet->GetData(), Packet->GetLength(), NULL, (SOCKADDR *)&Target->m_saServer, sizeof( SOCKADDR ) );
  328. Unlock();
  329. return;
  330. }
  331. else
  332. {
  333. Packet->GetTransit()->m_wTime = GetTime();
  334. sendto(m_sSocket, (char *)Packet->GetData(), Packet->GetLength(), NULL, (SOCKADDR *)&Target->m_saServer, sizeof( SOCKADDR ) );
  335. Unlock();
  336. return;
  337. }
  338. break;
  339. }
  340. }
  341. Unlock();
  342. m_Interface->OutputConsoleString("Couldn't resend %X on server %s, packet not found!", iSendSequence, inet_ntoa(Target->m_saServer.sin_addr));
  343. }
  344. void cNetwork::SendPacket(cPacket *Packet, stServerInfo *Target)
  345. {
  346. BYTE *pbData = Packet->GetData();
  347. int iLength = Packet->GetLength();
  348. // server wants connect response on next higher port
  349. if (Packet->GetTransit()->m_dwFlags == kConnectResponse)
  350. {
  351. Target->m_saServer.sin_port = htons(Target->m_wBasePort + 1);
  352. } else {
  353. Target->m_saServer.sin_port = htons(Target->m_wBasePort);
  354. }
  355. //m_Interface->OutputConsoleString("Sending Packet: Seq: %i, Dest: %s:%i", Packet->GetTransit()->m_dwSequence, inet_ntoa(Target->m_saServer.sin_addr), htons(Target->m_saServer.sin_port));
  356. int tp = sendto(m_sSocket, (char *) pbData, iLength, NULL, (SOCKADDR *)&Target->m_saServer, sizeof( SOCKADDR ) );
  357. //don't cache packets without a sequence number
  358. //don't cache ping packets, they have a mirrored send sequence
  359. //don't cache 0x100 packets, they have a mirrored send sequence
  360. if (Packet->GetTransit()->m_dwSequence == 0 ||
  361. Packet->GetTransit()->m_dwFlags & 4 ||
  362. Packet->GetTransit()->m_dwFlags & 0x100 ||
  363. Packet->GetTransit()->m_dwFlags & 0x400)
  364. delete Packet;
  365. else
  366. {
  367. Lock();
  368. Target->m_lSentPackets.push_back(Packet);
  369. Target->m_dwLastPacketSent = GetTickCount();
  370. Unlock();
  371. }
  372. }
  373. void cNetwork::SetInterface(cInterface *Interface)
  374. {
  375. m_Interface = Interface;
  376. }
  377. void cNetwork::SetObjectDB(cObjectDB *ObjectDB)
  378. {
  379. m_ObjectDB = ObjectDB;
  380. }
  381. void cNetwork::SetCharInfo(cCharInfo *CharInfo)
  382. {
  383. m_CharInfo = CharInfo;
  384. }
  385. WORD cNetwork::GetTime()
  386. {
  387. return (WORD)((GetTickCount() - m_dwStartTicks) / 500.0f);
  388. }
  389. void cNetwork::Connect()
  390. {
  391. m_Interface->OutputConsoleString("--- New Session... Connecting... ---");
  392. m_Interface->SetInterfaceMode(eConnecting);
  393. m_Interface->SetConnProgress(0);
  394. //Clear all connection stuff, incase of repeated connect attempts.
  395. Reset();
  396. cPacket *LoginPacket = new cPacket();
  397. stTransitHeader header;
  398. header.m_dwFlags = 0x00010000;
  399. LoginPacket->Add(&header, sizeof(stTransitHeader));
  400. LoginPacket->Add(std::string("1802")); // magic string
  401. // Data length left in packet including ticket (FIXME: calculate this, but ACEmulator doesn't seem to care)
  402. if (m_zPassword[0] != 0) {
  403. LoginPacket->Add((DWORD)0x00000020);
  404. } else {
  405. LoginPacket->Add((DWORD)0x00000116);
  406. }
  407. // Authentication Type
  408. if (m_zPassword[0] != 0) {
  409. LoginPacket->Add((DWORD)kAuthAccountPassword);
  410. } else {
  411. LoginPacket->Add((DWORD)kAuthGlsTicket);
  412. }
  413. LoginPacket->Add((DWORD)0x00000000); // Authentication Flags
  414. LoginPacket->Add((DWORD)time(NULL)); // Timestamp
  415. LoginPacket->Add(std::string(m_zAccountName)); // Account name
  416. // Empty string for special admin account name
  417. LoginPacket->Add(std::string());
  418. if (m_zPassword[0] != 0) {
  419. LoginPacket->AddString32L(std::string(m_zPassword)); // Password uses weird 32L format
  420. } else {
  421. LoginPacket->Add((DWORD)0x000000F6);
  422. LoginPacket->Add((WORD)0xF480);
  423. LoginPacket->Add(m_zTicket, m_zTicketSize);
  424. }
  425. SendLSPacket(LoginPacket, true, false);
  426. m_siLoginServer.m_dwConnectAttempts++;
  427. m_siLoginServer.m_dwLastConnectAttempt = GetTickCount();
  428. }
  429. void cNetwork::CloseConnection(stServerInfo *Server)
  430. {
  431. static BYTE CLOSE_CONNECTION[] =
  432. {
  433. 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xD4, 0x72, 0xF2, 0xBA, 0xD7, 0x01, 0x00, 0x00,
  434. 0x00, 0x00, 0x01, 0x00
  435. };
  436. cPacket *CloseClient = new cPacket();
  437. CloseClient->Add(CLOSE_CONNECTION, sizeof(CLOSE_CONNECTION));
  438. if (Server == &m_siLoginServer)
  439. SendLSPacket(CloseClient, false, false);
  440. else
  441. SendPacket(CloseClient, Server, false, false);
  442. }
  443. void cNetwork::Disconnect()
  444. {
  445. if (m_siLoginServer.m_dwFlags & SF_CONNECTED) {
  446. CloseConnection(&m_siLoginServer);
  447. Lock();
  448. m_siLoginServer.m_dwFlags &= ~SF_CONNECTED;
  449. Unlock();
  450. }
  451. for (std::list<stServerInfo>::iterator i = m_siWorldServers.begin(); i != m_siWorldServers.end(); i++)
  452. {
  453. if (i->m_dwFlags & SF_CONNECTED) {
  454. CloseConnection(&*i);
  455. Lock();
  456. i->m_dwFlags &= ~SF_CONNECTED;
  457. Unlock();
  458. }
  459. }
  460. }
  461. void cNetwork::PingServer(stServerInfo *Server)
  462. {
  463. // m_Interface->OutputConsoleString("Pinging %s:%i...", inet_ntoa(Server->m_saServer.sin_addr), ntohs(Server->m_saServer.sin_port));
  464. static BYTE PING_PACKET[] = {
  465. 0x00, 0x00, 0x00, 0x00,
  466. 0x04, 0x00, 0x00, 0x00,
  467. 0x00, 0x00, 0x00, 0x00,
  468. 0x00, 0x00, 0x00, 0x00,
  469. 0x00, 0x00, 0x00, 0x00,
  470. 0x00, 0x00, 0x00, 0x00
  471. };
  472. // Lock();
  473. memcpy(&PING_PACKET[20], &Server->m_dwRecvSequence, 4);
  474. // Unlock();
  475. cPacket *Ping = new cPacket;
  476. Ping->Add(PING_PACKET, sizeof(PING_PACKET));
  477. if (Server == &m_siLoginServer)
  478. SendLSPacket(Ping, true, false);
  479. else
  480. SendPacket(Ping, Server, true, false);
  481. // Lock();
  482. Server->m_dwLastPing = GetTickCount();
  483. // Unlock();
  484. }
  485. void cNetwork::SyncServer(stServerInfo *Server)
  486. {
  487. // m_Interface->OutputConsoleString("Syncing with %s:%i...", inet_ntoa(Server->m_saServer.sin_addr), ntohs(Server->m_saServer.sin_port));
  488. static BYTE SYNC_PACKET[] = {
  489. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  490. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  491. };
  492. // Lock();
  493. DWORD TimeDiff = (GetTickCount() - Server->m_dwLastSyncRecv);
  494. double TimeEstimate = Server->m_flServerTime + (TimeDiff / 1000.0f);
  495. Server->m_dwLastSyncSent = GetTickCount();
  496. // Unlock();
  497. }
  498. void cNetwork::CheckPings()
  499. {
  500. if (iConnPacketCount >= 10)
  501. {
  502. if (m_siLoginServer.m_dwLastPing < (GetTickCount() - 2000))
  503. {
  504. PingServer(&m_siLoginServer);
  505. }
  506. if ((m_siLoginServer.m_dwFlags & SF_CRCSEEDS) &&
  507. (m_siLoginServer.m_dwFlags & SF_CONNECTED))
  508. {
  509. if (m_siLoginServer.m_dwLastSyncSent < (GetTickCount() - 2000))
  510. {
  511. SyncServer(&m_siLoginServer);
  512. }
  513. }
  514. for (std::list<stServerInfo>::iterator i = m_siWorldServers.begin(); i != m_siWorldServers.end(); i++)
  515. {
  516. stServerInfo j = *i;
  517. if (j.m_dwLastPing < (GetTickCount() - 2000))
  518. {
  519. PingServer(&j);
  520. }
  521. if ((j.m_dwFlags & SF_CRCSEEDS) &&
  522. (j.m_dwFlags & SF_CONNECTED))
  523. {
  524. if (j.m_dwLastSyncSent < (GetTickCount() - 2000))
  525. {
  526. SyncServer(&j);
  527. }
  528. }
  529. }
  530. }
  531. }
  532. void cNetwork::Run()
  533. {
  534. //message loop for the network thread
  535. while (!m_bQuit)
  536. {
  537. //keep trying to connect to login server if first time doesn't work
  538. if (!(m_siLoginServer.m_dwFlags & SF_CONNECTED))
  539. {
  540. // timeout trying to connect
  541. if ((m_siLoginServer.m_dwLastConnectAttempt + TIMEOUT_MS) < GetTickCount())
  542. {
  543. m_Interface->OutputConsoleString("Timed out after %d ms.", TIMEOUT_MS);
  544. m_Interface->OutputConsoleString("Couldn't connect first time, trying again..");
  545. Connect();
  546. }
  547. }
  548. cPacket *Packet = new cPacket();
  549. BYTE bRawData[1024];
  550. SOCKADDR Target;
  551. int siSize = sizeof( sockaddr_in );
  552. int iRawSize = recvfrom( m_sSocket, (char *)bRawData, 1024, NULL, &Target, &siSize );
  553. if (iRawSize == SOCKET_ERROR)
  554. continue;
  555. Packet->Add(bRawData, iRawSize);
  556. bool bFound = false;
  557. // make sure we recognize this server before processing the packet
  558. stServerInfo* verifiedServer = NULL;
  559. if (SockCompare((SOCKADDR_IN *)&Target, &m_siLoginServer.m_saServer)) {
  560. verifiedServer = &m_siLoginServer;
  561. }
  562. else {
  563. for (std::list<stServerInfo>::iterator i = m_siWorldServers.begin(); i != m_siWorldServers.end(); i++)
  564. {
  565. if (SockCompare((SOCKADDR_IN *)&Target, &(*i).m_saServer))
  566. {
  567. verifiedServer = &(*i);
  568. }
  569. }
  570. }
  571. if (verifiedServer != NULL) {
  572. ProcessPacket(Packet, verifiedServer);
  573. if (verifiedServer->m_dwLastPacketAck + ACK_INTERVAL_MS < GetTickCount()) {
  574. SendAckPacket(verifiedServer);
  575. }
  576. } else {
  577. /** We didn't recognize the packet source. Dump some info to the console for troubleshooting purposes. */
  578. SOCKADDR_IN *tp = (SOCKADDR_IN *) &Target;
  579. char tps[50];
  580. char *tps2 = inet_ntoa(m_siLoginServer.m_saServer.sin_addr);
  581. strcpy(tps, tps2);
  582. m_Interface->OutputConsoleString("Received packet from unknown server: %s:%i. Login server: %s:%i"
  583. , inet_ntoa(tp->sin_addr)
  584. , (int)ntohs(tp->sin_port)
  585. , tps
  586. , (int)ntohs(m_siLoginServer.m_saServer.sin_port));
  587. m_Interface->OutputConsoleString("World servers:");
  588. DumpWorldServerList();
  589. delete Packet;
  590. }
  591. CheckPings();
  592. }
  593. }
  594. void cNetwork::SendAckPacket(stServerInfo *Server) {
  595. stTransitHeader header;
  596. header.m_dwFlags = kAckSequence | kFlow | kEncryptedChecksum;
  597. cPacket *ackSequence = new cPacket();
  598. ackSequence->Add(&header, sizeof(header));
  599. ackSequence->Add((DWORD)Server->m_dwRecvSequence);
  600. SendPacket(ackSequence, Server, true, false);
  601. Server->m_dwLastPacketAck = GetTickCount();
  602. }
  603. void cNetwork::ProcessFragment(cByteStream* stream, stServerInfo *Server) {
  604. //Loop through the fragments
  605. while (!stream->AtEOF())
  606. {
  607. const stFragmentHeader *fragHead = (const stFragmentHeader *)stream->ReadGroup(sizeof(stFragmentHeader));
  608. WORD payloadSize = fragHead->m_wSize - sizeof(stFragmentHeader);
  609. BYTE *fragData = stream->ReadGroup(payloadSize);
  610. if (fragHead->m_wCount == 1)
  611. {
  612. // if count is 1 it's just a singular message, no group. process immediately!
  613. cMessage *Msg = new cMessage(fragData, fragHead);
  614. ProcessMessage(Msg, Server);
  615. }
  616. else
  617. {
  618. //Check for existing fragments
  619. bool bAdded = false;
  620. for (std::list< cMessage * >::iterator it = Server->m_lIncomingMessages.begin(); it != Server->m_lIncomingMessages.end(); it++)
  621. {
  622. if (bAdded)
  623. break;
  624. cMessage *scan = *it;
  625. /* fragment matches existing sequence we have started receiving */
  626. if (scan->m_dwSequence == fragHead->m_dwSequence)
  627. {
  628. scan->AddChunk(fragData, payloadSize, fragHead->m_wIndex);
  629. bAdded = true;
  630. if (scan->IsComplete())
  631. {
  632. ProcessMessage(scan, Server);
  633. Server->m_lIncomingMessages.erase(it);
  634. }
  635. break;
  636. }
  637. }
  638. //No existing group matches, create one
  639. if (!bAdded)
  640. {
  641. cMessage *Msg = new cMessage(fragData, fragHead);
  642. Server->m_lIncomingMessages.push_back(Msg);
  643. }
  644. }
  645. }
  646. }
  647. void cNetwork::ProcessPacket(cPacket *Packet, stServerInfo *Server)
  648. {
  649. // Lock();
  650. stTransitHeader *Head = (stTransitHeader *) Packet->GetData();
  651. BYTE *Data = Packet->GetData() + sizeof(stTransitHeader);
  652. cByteStream stream(Data, Head->m_wSize);
  653. DWORD dwFlags = Head->m_dwFlags;
  654. if (dwFlags & kServerSwitch) {
  655. // server ID?
  656. stream.ReadDWORD();
  657. stream.ReadDWORD();
  658. }
  659. if (dwFlags & kRetransmission)
  660. {
  661. // XXX: not sure how to handle this one yet
  662. //Flags a packet that has been resent
  663. dwFlags &= ~kRetransmission;
  664. }
  665. if (dwFlags & kRequestRetransmit)
  666. {
  667. // XXX: not sure how to handle this one yet
  668. dwFlags &= ~kRejectRetransmit;
  669. }
  670. if (dwFlags & kRejectRetransmit)
  671. {
  672. // XXX: not sure how to handle this one yet
  673. dwFlags &= ~kRejectRetransmit;
  674. }
  675. if (dwFlags & kEncryptedChecksum)
  676. {
  677. //TODO: Check the checksum
  678. dwFlags &= ~kEncryptedChecksum;
  679. }
  680. if (dwFlags & kAckSequence)
  681. {
  682. DWORD ackSequenceNumber = stream.ReadDWORD();
  683. Server->m_dwSendSequence = max(Server->m_dwSendSequence, ackSequenceNumber);
  684. // TODO: Clear saved packets with sequences before the acked one
  685. dwFlags &= ~kAckSequence;
  686. }
  687. else {
  688. // update sequence number only if not an ack
  689. // XXX: are there other cases we should not update sequence number?
  690. // XXX: are there cases where we should update even if it's just an ack?
  691. if (Head->m_dwSequence != Server->m_dwRecvSequence + 1) {
  692. Server->m_dwRecvSequence += 1;
  693. }
  694. else {
  695. if (Head->m_dwSequence <= Server->m_dwRecvSequence && Head->m_dwSequence != 0) {
  696. // we already received this packet
  697. m_Interface->OutputConsoleString("Received packet #%d again", Head->m_dwSequence);
  698. }
  699. else if (Head->m_dwSequence > Server->m_dwRecvSequence + 1) {
  700. // we missed a packet
  701. // TODO: handle out of order packet by storing it and playing back later when we get the preceding packet
  702. m_Interface->OutputConsoleString("Received out of order packet with id #%d", Head->m_dwSequence);
  703. Server->m_dwRecvSequence = Head->m_dwSequence;
  704. }
  705. }
  706. }
  707. // Second step of the connection process is to receive a Connect Request packet from the server
  708. if (dwFlags & kConnectRequest)
  709. {
  710. m_Interface->OutputConsoleString("Received connection request from server...");
  711. // Connection request from the server
  712. Server->m_wTable = Head->m_wTable;
  713. Server->m_dwLastSyncRecv = GetTickCount();
  714. Server->m_dwFlags |= SF_CONNECTED;
  715. Server->m_flServerTime = stream.ReadDouble(); //Time sync
  716. Server->m_qwCookie = stream.ReadQWORD(); // Connection cookie
  717. Server->m_wLogicalID = stream.ReadWORD(); // Client ID for our session
  718. WORD paddingWord = stream.ReadWORD();
  719. DWORD serverSeed = stream.ReadDWORD(); // for encrtypted checksum
  720. DWORD clientSeed = stream.ReadDWORD(); // for encrypted checksum
  721. Server->serverXorGen = new ChecksumXorGenerator();
  722. Server->clientXorGen = new ChecksumXorGenerator();
  723. Server->serverXorGen->init(serverSeed);
  724. Server->clientXorGen->init(clientSeed);
  725. Server->m_dwFlags |= SF_CRCSEEDS;
  726. DWORD unknownPadding = stream.ReadDWORD();
  727. m_Interface->SetConnProgress(0.1f);
  728. // XXX: delay to avoid race condition where server hasn't entered AuthConnectResponse state
  729. Sleep(500);
  730. m_Interface->SetConnProgress(0.5f);
  731. m_Interface->OutputConsoleString("Sending connect response...");
  732. // Final third step of the connection process is to send connect response packet with cookie
  733. SendConnectResponse();
  734. m_Interface->SetConnProgress(0.2f);
  735. dwFlags &= ~kConnectRequest;
  736. // login server is world server unless we get a redirect
  737. // use the same CRC, etc.
  738. SOCKADDR_IN tpaddr;
  739. memcpy(&tpaddr, &Server->m_saServer, sizeof(tpaddr));
  740. tpaddr.sin_port = htons(Server->m_wBasePort);
  741. AddWorldServer(tpaddr);
  742. SetActiveWorldServer(tpaddr);
  743. m_pActiveWorld->clientXorGen = Server->clientXorGen;
  744. m_pActiveWorld->serverXorGen = Server->serverXorGen;
  745. m_pActiveWorld->m_dwFlags |= SF_CRCSEEDS | SF_CONNECTED;
  746. m_pActiveWorld->m_wLogicalID = Server->m_wLogicalID;
  747. m_pActiveWorld->m_wTable = 0x14; // XXX: from pcaps?
  748. }
  749. if (dwFlags & kNetError1)
  750. {
  751. //? I seem to get these when connecting with a stale gls ticket
  752. MessageBox(NULL, "Stale GLS Ticket", "Error", MB_OK);
  753. dwFlags &= ~kNetError1;
  754. }
  755. if (dwFlags & kBlobFragments)
  756. {
  757. ProcessFragment(&stream, Server);
  758. dwFlags &= ~kBlobFragments;
  759. }
  760. if (dwFlags & kTimeSync)
  761. {
  762. double serverTime = stream.ReadDouble();
  763. time_t sT = (DWORD)serverTime;
  764. time_t offset = time(NULL) - sT;
  765. char *woohoo = ctime(&offset);
  766. Server->m_dwLastSyncRecv = GetTickCount();
  767. Server->m_flServerTime = serverTime;
  768. dwFlags &= ~kTimeSync;
  769. }
  770. if (dwFlags > 0)
  771. {
  772. m_Interface->OutputConsoleString("LS: Unhandled Flags: %08X", dwFlags);
  773. }
  774. // if (dwFlags & 0x00800000) { //Displays a server error
  775. // DWORD error = stream.ReadDWORD();
  776. // ServerLoginError( error );
  777. // dwFlags &= ~0x00800000;
  778. //}
  779. //case 0x00000000: //stripped packets
  780. // {
  781. // break;
  782. // }
  783. //case 0x00000002: //requests lost packets
  784. // {
  785. // DWORD packetCount = *((DWORD *)&Data[iPos]); iPos += 4;
  786. // for (int i = 0; i < (int)packetCount; i++)
  787. // {
  788. // DWORD packetSeq = *((DWORD *)&Data[iPos]); iPos += 4;
  789. // SendLostPacket(packetSeq, &m_siLoginServer);
  790. // }
  791. // break;
  792. // }
  793. //case 0x00000004: //ping
  794. // {
  795. // Lock();
  796. // DWORD serverSequence = *((DWORD *)&Data[iPos]);
  797. // if ((int)serverSequence < Server->m_iSendSequence)
  798. // {
  799. // //allow 1000 latency
  800. // if ((Server->m_dwLastPacketSent + 1000) < GetTickCount())
  801. // {
  802. // //server lost some packets
  803. // for (int i = serverSequence + 1; i <= Server->m_iSendSequence; i++)
  804. // {
  805. // SendLostPacket(i, &m_siLoginServer);
  806. // }
  807. // }
  808. // }
  809. // else if ((int)serverSequence > Server->m_iSendSequence)
  810. // {
  811. // m_Interface->OutputConsoleString("Login sequence is AHEAD of the client (previous connection?)");
  812. // }
  813. // Unlock();
  814. // break;
  815. // }
  816. //case 0x00000008: //declines requested packets
  817. // break;
  818. //case 0x00000100: //update CRC
  819. // m_Interface->OutputConsoleString("Received 0x100 on login server?");
  820. // break;
  821. // case 0x00000200: //game-related messages
  822. //
  823. // //Loop through the fragments
  824. // while ((iPos + sizeof(stFragmentHeader)) < Head->m_wSize)
  825. // {
  826. // stFragmentHeader *FragHead = (stFragmentHeader *)&Data[iPos];
  827. // BYTE *FragData = sizeof(stFragmentHeader) + &Data[iPos];
  828. // iPos += FragHead->m_wSize;
  829. //
  830. // if (FragHead->m_wCount == 1)
  831. // {
  832. // cMessage *Msg = new cMessage(FragData, FragHead);
  833. // ProcessMessage(Msg, &m_siLoginServer);
  834. // }
  835. // else
  836. // {
  837. // if (Server->m_lIncomingMessages.size() > 0)
  838. // {
  839. // //Check for existing fragments
  840. // bool bAdded = false;
  841. // std::list< cMessage * >::iterator it;
  842. // for (it = Server->m_lIncomingMessages.begin(); it != Server->m_lIncomingMessages.end(); it++)
  843. // {
  844. // if (bAdded)
  845. // break;
  846. //
  847. // cMessage *scan = *it;
  848. // if ( scan->m_dwSequence == FragHead->m_dwSequence)
  849. // {
  850. // scan->AddChunk(FragData, FragHead->m_wSize - sizeof(stFragmentHeader), FragHead->m_wIndex);
  851. // bAdded = true;
  852. //
  853. // if ( scan->IsComplete() )
  854. // {
  855. // ProcessMessage(scan, &m_siLoginServer);
  856. // Server->m_lIncomingMessages.erase(it);
  857. // }
  858. // break;
  859. // }
  860. // }
  861. //
  862. // //No existing group matches, create one
  863. // if (!bAdded) //(it == Server->m_lIncomingMessages.end() )
  864. // {
  865. // cMessage *Msg = new cMessage(FragData, FragHead);
  866. // Server->m_lIncomingMessages.push_back(Msg);
  867. // }
  868. // }
  869. // else
  870. // {
  871. // cMessage *Msg = new cMessage(FragData, FragHead);
  872. // Server->m_lIncomingMessages.push_back(Msg);
  873. // }
  874. // }
  875. // }
  876. // break;
  877. // case 0x00000800: //login server redirect
  878. // Reset();
  879. //
  880. // SOCKADDR_IN tp;
  881. // memcpy(&tp, Data, sizeof(SOCKADDR_IN));
  882. //
  883. // char tps[50];
  884. // strcpy(tps, inet_ntoa(Server->m_saServer.sin_addr));
  885. // m_Interface->OutputConsoleString("Login Redirect: %s:%i -> %s:%i",
  886. // tps,
  887. // (int)ntohs(Server->m_saServer.sin_port),
  888. // inet_ntoa(tp.sin_addr),
  889. // (int)ntohs(tp.sin_port) );
  890. //
  891. // memcpy(&Server->m_saServer, Data, sizeof(SOCKADDR_IN));
  892. // Connect();
  893. // break;
  894. // case 0x00020000:
  895. // {
  896. // SOCKADDR_IN tpaddr;
  897. // memcpy(&tpaddr, Data, sizeof(tpaddr));
  898. // DWORD dwAck = *((DWORD *) (Data+sizeof(tpaddr)));
  899. //
  900. // char tps[50];
  901. // strcpy(tps, inet_ntoa(tpaddr.sin_addr));
  902. // if (!m_pActiveWorld)
  903. // m_Interface->OutputConsoleString("LS: Setting Worldserver: %s:%i...", tps, ntohs(tpaddr.sin_port));
  904. // else
  905. // m_Interface->OutputConsoleString("LS: Worldserver Redirect: %s:%i->%s:%i...", inet_ntoa(m_pActiveWorld->m_saServer.sin_addr), ntohs(m_pActiveWorld->m_saServer.sin_port), tps, ntohs(tpaddr.sin_port));
  906. // AddWorldServer(tpaddr);
  907. // SetActiveWorldServer(tpaddr);
  908. //
  909. // //Now tell LS that we've added it
  910. // BYTE acceptServer[] =
  911. // {
  912. // 0x00, 0x00, 0x00, 0x00,
  913. // 0x00, 0x00, 0x02, 0x00,
  914. // 0x00, 0x00, 0x00, 0x00,
  915. // 0x40, 0x00, 0x00, 0x00,
  916. // 0x00, 0x00, 0x00, 0x00
  917. //// ,0x5c, 0x00, 0x00, 0x00
  918. // };
  919. //
  920. // for (int i=0; i<4; i++)
  921. // {
  922. // //gotta do this shit 4 times
  923. // //WakeServer(m_pActiveWorld);
  924. //
  925. // cPacket *AcceptServer = new cPacket();
  926. // AcceptServer->Add(acceptServer, sizeof(acceptServer));
  927. // AcceptServer->Add(dwAck);
  928. // SendLSPacket(AcceptServer, false, false);
  929. // }
  930. //
  931. // break;
  932. // }
  933. // default:
  934. // m_Interface->OutputConsoleString("LS: Unknown Packet Type: %08X", dwFlags);
  935. // break;
  936. // }
  937. delete Packet;
  938. }
  939. void cNetwork::SendConnectResponse()
  940. {
  941. stTransitHeader header;
  942. header.m_dwFlags = kConnectResponse;
  943. cPacket *connectReply = new cPacket();
  944. connectReply->Add(&header, sizeof(header));
  945. connectReply->Add(m_siLoginServer.m_qwCookie);
  946. SendLSPacket(connectReply, false, false);
  947. }
  948. void cNetwork::ProcessWSPacket(cPacket *Packet, stServerInfo *Server)
  949. {
  950. // XXX: for now, everything is handled in ProcessPacket
  951. return ProcessPacket(Packet, Server);
  952. //// m_Interface->OutputConsoleString("Worldserver Packet...");
  953. // stTransitHeader *Head = (stTransitHeader *) Packet->GetData();
  954. // BYTE *Data = Packet->GetData() + sizeof(stTransitHeader);
  955. // int iPos = 0;
  956. //
  957. // //Update our received sequence, if necessary
  958. // if (Head->m_dwSequence > Server->m_dwRecvSequence)
  959. // Server->m_dwRecvSequence = Head->m_dwSequence;
  960. //
  961. // DWORD dwType = Head->m_dwFlags;
  962. //
  963. // if ((~Server->m_dwFlags & SF_CONNECTED) || Head->m_wTable != Server->m_wTable)
  964. // {
  965. // //Our 'table' ID isn't the same, are they telling us ours?
  966. // if ((~dwType & 0x00000080) && (~dwType & 0x00000100))
  967. // {
  968. // m_Interface->OutputConsoleString("WS (%s:%i): Wrong Table: Hooked: %i, Table: %04X/%04X, Type: %08X",
  969. // inet_ntoa(Server->m_saServer.sin_addr), htons(Server->m_saServer.sin_port),
  970. // (int)(~Server->m_dwFlags & SF_CONNECTED),
  971. // Server->m_wTable, Head->m_wTable,
  972. // dwType);
  973. //// m_Interface->OutputConsoleString("Packet from wrong server??");
  974. // delete Packet;
  975. // return;
  976. // }
  977. // }
  978. //
  979. //// m_Interface->OutputConsoleString("Sequence: %04X Packet: %04X", Head->m_dwSequence, dwType);
  980. //
  981. // if (dwType & 0x00000001) { //Flags a packet that has been resent
  982. // dwType &= ~0x00000001;
  983. // }
  984. // if (dwType & 0x00002000) { //Server issued a close-connection request?
  985. // m_Interface->OutputConsoleString("WS (%s:%i): Wants connection closed? Closing!",
  986. // inet_ntoa(Server->m_saServer.sin_addr), htons(Server->m_saServer.sin_port)
  987. // );
  988. // dwType &= ~0x00002000;
  989. //
  990. // CloseConnection(Server);
  991. // }
  992. // if (dwType & 0x00100000) { //These are sent every 20 seconds, they DO increment sequence
  993. // double serverTime = *((double *)&Data[iPos]);
  994. // time_t sT = (DWORD) serverTime;
  995. // time_t offset = time(NULL) - sT;
  996. // char *woohoo = ctime(&offset);
  997. //
  998. // Server->m_dwLastSyncRecv = GetTickCount();
  999. // Server->m_flServerTime = serverTime;
  1000. // Server->m_dwFlags |= SF_SYNC;
  1001. //
  1002. // dwType &= ~0x00100000;
  1003. // iPos += 8;
  1004. // }
  1005. // if (dwType & 0x00200000) { //*Shrug* some DWORD and WORD
  1006. // dwType &= ~0x00200000;
  1007. // iPos += 6;
  1008. // }
  1009. // if (dwType & 0x00800000) { //Displays a server error
  1010. // ServerLoginError( *((DWORD *)&Data[iPos]) );
  1011. //
  1012. // dwType &= ~0x00800000;
  1013. // iPos += 4;
  1014. // }
  1015. //
  1016. // switch (dwType)
  1017. // {
  1018. // case 0x00000000: //stripped packets
  1019. // {
  1020. // break;
  1021. // }
  1022. // case 0x00000002: //requests lost packets
  1023. // {
  1024. //// m_Interface->OutputConsoleString("Lost packet requested by server.");
  1025. //// DWORD seqAsked = *((DWORD *)&Data[iPos]);
  1026. //// SendLostPacket(seqAsked, Server);
  1027. // DWORD packetCount = *((DWORD *)&Data[iPos]); iPos += 4;
  1028. // for (int i = 0; i < (int)packetCount; i++)
  1029. // {
  1030. // DWORD packetSeq = *((DWORD *)&Data[iPos]); iPos += 4;
  1031. // SendLostPacket(packetSeq, Server);
  1032. // }
  1033. //
  1034. // break;
  1035. // }
  1036. // case 0x00000004: //ping
  1037. // {
  1038. // Lock();
  1039. // DWORD serverSequence = *((DWORD *)&Data[iPos]);
  1040. // if ((int)serverSequence < Server->m_iSendSequence)
  1041. // {
  1042. // //allow 1000 latency
  1043. // if ((Server->m_dwLastPacketSent + 1000) < GetTickCount())
  1044. // {
  1045. // //server lost some packets
  1046. // for (int i = serverSequence + 1; i <= Server->m_iSendSequence; i++)
  1047. // {
  1048. // SendLostPacket(i, Server);
  1049. // }
  1050. // }
  1051. // }
  1052. // else if ((int)serverSequence > Server->m_iSendSequence)
  1053. // {
  1054. // m_Interface->OutputConsoleString("World sequence is AHEAD of the client (WTF?)");
  1055. // }
  1056. // Unlock();
  1057. //
  1058. // break;
  1059. // }
  1060. // case 0x00000008: //declines requested packets
  1061. //
  1062. // break;
  1063. // case 0x00000100: //update CRC
  1064. // {
  1065. // Server->m_wTable = Head->m_wTable;
  1066. // Server->m_wLogicalID = *((WORD *)&Data[0x0]);
  1067. // Server->m_dwFlags |= SF_CONNECTED;
  1068. // DWORD input8[8];
  1069. // DWORD input3[3];
  1070. // memcpy(input8, &Data[0x12], 8 * sizeof(DWORD));
  1071. // memcpy(input3, &Data[0x3A], 3 * sizeof(DWORD));
  1072. // DWORD *seeds = DecryptSeeds(input8, input3);
  1073. // Server->m_dwRecvCRCSeed = seeds[0];
  1074. // Server->m_dwSendCRCSeed = seeds[1];
  1075. // Server->m_pdwRecvCRC = Server->m_lpdwRecvCRC;
  1076. // Server->m_pdwSendCRC = Server->m_lpdwSendCRC;
  1077. // GenerateCRCs(Server->m_dwSendCRCSeed, Server->m_dwRecvCRCSeed, Server->m_pdwSendCRC, Server->m_pdwRecvCRC);
  1078. // Server->m_dwFlags |= SF_CRCSEEDS;
  1079. //
  1080. // m_Interface->OutputConsoleString("WS (%s:%i): New seeds set. Table: %04X",
  1081. // inet_ntoa(Server->m_saServer.sin_addr), htons(Server->m_saServer.sin_port),
  1082. // Server->m_wTable);
  1083. //
  1084. // static BYTE acceptSeeds[] = {
  1085. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1086. // 0x00, 0x00, 0x00, 0x00
  1087. // };
  1088. // cPacket *Ack100 = new cPacket();
  1089. // Ack100->Add(acceptSeeds, sizeof(acceptSeeds));
  1090. // SendPacket(Ack100, Server, true, false);
  1091. //
  1092. // break;
  1093. // }
  1094. // case 0x00000200: //game-related messages
  1095. //
  1096. // //Loop through the fragments
  1097. // while ((iPos + sizeof(stFragmentHeader)) < Head->m_wSize)
  1098. // {
  1099. // stFragmentHeader *FragHead = (stFragmentHeader *)&Data[iPos];
  1100. // BYTE *FragData = sizeof(stFragmentHeader) + &Data[iPos];
  1101. // iPos += FragHead->m_wSize;
  1102. //
  1103. // if (FragHead->m_wCount == 1)
  1104. // {
  1105. // cMessage *Msg = new cMessage(FragData, FragHead);
  1106. // ProcessMessage(Msg, Server);
  1107. // }
  1108. // else
  1109. // {
  1110. // //Check for existing fragments
  1111. // if (Server->m_lIncomingMessages.size() > 0)
  1112. // {
  1113. // bool bAdded = false;
  1114. // std::list< cMessage * >::iterator it;
  1115. // for (it = Server->m_lIncomingMessages.begin(); it != Server->m_lIncomingMessages.end(); it++)
  1116. // {
  1117. // if (bAdded)
  1118. // break;
  1119. //
  1120. // cMessage *scan = *it;
  1121. // if ( scan->m_dwSequence == FragHead->m_dwSequence)
  1122. // {
  1123. // bAdded = true;
  1124. // scan->AddChunk(FragData, FragHead->m_wSize - sizeof(stFragmentHeader), FragHead->m_wIndex);
  1125. //
  1126. // if ( scan->IsComplete() )
  1127. // {
  1128. // ProcessMessage(scan, Server);
  1129. // Server->m_lIncomingMessages.erase(it);
  1130. // }
  1131. // break;
  1132. // }
  1133. // }
  1134. //
  1135. // //No existing group matches, create one
  1136. // if (!bAdded) //(it == Server->m_lIncomingMessages.end() )
  1137. // {
  1138. // cMessage *Msg = new cMessage(FragData, FragHead);
  1139. // Server->m_lIncomingMessages.push_back(Msg);
  1140. // }
  1141. // }
  1142. // else
  1143. // {
  1144. // cMessage *Msg = new cMessage(FragData, FragHead);
  1145. // Server->m_lIncomingMessages.push_back(Msg);
  1146. // }
  1147. // }
  1148. // }
  1149. // break;
  1150. // case 0x00000400: //wtf?
  1151. // {
  1152. // static BYTE acceptWTF[] = {
  1153. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1154. // 0x00, 0x00, 0x00, 0x00
  1155. // };
  1156. // cPacket *Ack400 = new cPacket();
  1157. // Ack400->Add(acceptWTF, sizeof(acceptWTF));
  1158. // SendPacket(Ack400, Server, false, false);
  1159. // m_Interface->OutputConsoleString("Set output server to %s:%i...", inet_ntoa(Server->m_saServer.sin_addr), ntohs(Server->m_saServer.sin_port));
  1160. //
  1161. // SetActiveWorldServer(Server->m_saServer);
  1162. //
  1163. // //no idea if this is what i should do
  1164. // double serverTime = *((double *)&Data[iPos]);
  1165. // m_pActiveWorld->m_dwLastSyncRecv = GetTickCount();
  1166. // m_pActiveWorld->m_flServerTime = serverTime;
  1167. // m_pActiveWorld->m_dwFlags |= SF_SYNC;
  1168. // break;
  1169. // }
  1170. // case 0x00010000:
  1171. // {
  1172. // //data: 0BAD70DD (bad todd)
  1173. //
  1174. // m_Interface->OutputConsoleString("10000 from %s:%i..", inet_ntoa(Server->m_saServer.sin_addr), ntohs(Server->m_saServer.sin_port));
  1175. //
  1176. ///* DWORD dataSize = Packet->GetLength() - sizeof(stTransitHeader);
  1177. // BYTE *data = Packet->GetData() + sizeof(stTransitHeader);
  1178. // m_Interface->OutputConsoleString("10000: Contents:");
  1179. // for (DWORD i = 0; i <= ((dataSize - (dataSize % 16)) / 16); i++)
  1180. // {
  1181. // char valbuff[128]; memset(valbuff, 0, 128);
  1182. // char linebuff[128]; memset(linebuff, 0, 128);
  1183. // char strbuff[128]; memset(strbuff, 0, 128);
  1184. //
  1185. // strcat(strbuff, "; ");
  1186. // for (DWORD j = i * 16; (j < ((i+1)*16)) && (j < dataSize); j++)
  1187. // {
  1188. // sprintf(valbuff, "%.1s", &data[j]);
  1189. // strcat(strbuff, valbuff);
  1190. // sprintf(valbuff, "%02X ", data[j]);
  1191. // strcat(linebuff, valbuff);
  1192. // }
  1193. // strcat(linebuff, strbuff);
  1194. // m_Interface->OutputConsoleString("%s", linebuff);
  1195. // }*/
  1196. //
  1197. // break;
  1198. // }
  1199. // case 0x00020000:
  1200. // {
  1201. // SOCKADDR_IN tpaddr;
  1202. // memcpy(&tpaddr, Data, sizeof(tpaddr));
  1203. // DWORD dwAck = *((DWORD *) (Data+sizeof(tpaddr)));
  1204. //
  1205. // char outt[50];
  1206. // strcpy(outt, inet_ntoa(m_pActiveWorld->m_saServer.sin_addr));
  1207. // m_Interface->OutputConsoleString("WS: Worldserver Redirect: %s:%i->%s:%i...", outt, ntohs(m_pActiveWorld->m_saServer.sin_port), inet_ntoa(tpaddr.sin_addr), ntohs(tpaddr.sin_port));
  1208. // stServerInfo *newserv = AddWorldServer(tpaddr);
  1209. //// SetActiveWorldServer(tpaddr);
  1210. //
  1211. // //woo, trying this out my ass...
  1212. // newserv->m_dwLastSyncRecv = Server->m_dwLastSyncRecv;
  1213. // newserv->m_flServerTime = Server->m_flServerTime;
  1214. // if (Server->m_dwFlags & SF_SYNC)
  1215. // newserv->m_dwFlags |= SF_SYNC;
  1216. //
  1217. // //Now tell Last WS that we've added it
  1218. // BYTE acceptServer[] =
  1219. // {
  1220. // 0x00, 0x00, 0x00, 0x00,
  1221. // 0x00, 0x00, 0x02, 0x00,
  1222. // 0x00, 0x00, 0x00, 0x00,
  1223. // 0x40, 0x00, 0x00, 0x00,
  1224. // 0x00, 0x00, 0x00, 0x00
  1225. //// ,0x5c, 0x00, 0x00, 0x00
  1226. // };
  1227. //
  1228. // //WakeServer(newserv);
  1229. //
  1230. // //Tell the last worldserver we're acking it
  1231. // cPacket *AcceptServer = new cPacket();
  1232. // AcceptServer->Add(acceptServer, sizeof(acceptServer));
  1233. // AcceptServer->Add(dwAck);
  1234. // SendPacket(AcceptServer, Server, false, false);
  1235. //
  1236. // break;
  1237. // }
  1238. // default:
  1239. // m_Interface->OutputConsoleString("WS: Unknown Packet Type: %08X", dwType);
  1240. // break;
  1241. // }
  1242. delete Packet;
  1243. }
  1244. void cNetwork::Stop()
  1245. {
  1246. Disconnect();
  1247. WSACleanup();
  1248. closesocket(m_sSocket);
  1249. cThread::Stop();
  1250. }
  1251. void cNetwork::ServerLoginError(DWORD Error)
  1252. {
  1253. //these will usually occur at the connection phase
  1254. switch (Error)
  1255. {
  1256. case 0x04:
  1257. m_Interface->OutputConsoleString("Client: Your zone ticket expired before reaching the server.");
  1258. break;
  1259. default:
  1260. m_Interface->OutputConsoleString("Client: Received login error #%u.", Error);
  1261. break;
  1262. }
  1263. }
  1264. void cNetwork::ServerCharCreateError(DWORD Error)
  1265. {
  1266. //these will occur when logging in or creating a character
  1267. switch(Error)
  1268. {
  1269. case 0x03:
  1270. m_Interface->OutputConsoleString("The name you have chosen for your character is already in use by another character.");
  1271. break;
  1272. case 0x04:
  1273. m_Interface->OutputConsoleString("Sorry, but that name is not permitted.");
  1274. break;
  1275. case 0x05:
  1276. m_Interface->OutputConsoleString("The server has found an unexplained error with this new character. The data may be corrupt or out of date.");
  1277. break;
  1278. case 0x06:
  1279. m_Interface->OutputConsoleString("The server cannot create your new character at this time. Please try again later.");
  1280. break;
  1281. case 0x07:
  1282. m_Interface->OutputConsoleString("Sorry, but you do not have the privileges to make an administrator character.");
  1283. break;
  1284. default:
  1285. m_Interface->OutputConsoleString("Client: Character creation error #%u", Error);
  1286. break;
  1287. }
  1288. }
  1289. void cNetwork::ServerCharacterError(DWORD Error)
  1290. {
  1291. //these will occur when logging in or creating a character
  1292. switch(Error)
  1293. {
  1294. case 0x01:
  1295. m_Interface->OutputConsoleString("Cannot have two accounts logged on at the same time.");
  1296. break;
  1297. case 0x03:
  1298. m_Interface->OutputConsoleString("Server could not access your account information. Please try again in a few minutes.");
  1299. break;
  1300. case 0x04:
  1301. m_Interface->OutputConsoleString("The server has disconnected. Please try again in a few minutes.");
  1302. break;
  1303. case 0x05:
  1304. m_Interface->OutputConsoleString("Server could not log off your character.");
  1305. break;
  1306. case 0x06:
  1307. m_Interface->OutputConsoleString("Server could not delete your character.");
  1308. break;
  1309. case 0x08:
  1310. m_Interface->OutputConsoleString("The account you specified is already in use.");
  1311. break;
  1312. case 0x09:
  1313. m_Interface->OutputConsoleString("The account name you specified was not valid.");
  1314. break;
  1315. case 0x0A:
  1316. m_Interface->OutputConsoleString("The account you specified doesn't exist.");
  1317. break;
  1318. case 0x0B:
  1319. m_Interface->OutputConsoleString("Server could not put your character in the game. Please try again in a few minutes.");
  1320. break;
  1321. case 0x0C:
  1322. m_Interface->OutputConsoleString("You cannot enter the game with a stress creating character.");
  1323. break;
  1324. case 0x0D:
  1325. m_Interface->OutputConsoleString("One of your characters is still in the world. Please try again in a few minutes.");
  1326. break;
  1327. case 0x0E:
  1328. m_Interface->OutputConsoleString("Server unable to find player account. Please try again later.");
  1329. break;
  1330. case 0x0F:
  1331. m_Interface->OutputConsoleString("You do not own this character.");
  1332. break;
  1333. case 0x10:
  1334. m_Interface->OutputConsoleString("One of your characters is currently in the world. Please try again later. This is likely an internal server error.");
  1335. break;
  1336. case 0x11:
  1337. m_Interface->OutputConsoleString("Please try again in a few minutes. If this problem persists, the character might be out of date and no longer usable.");
  1338. break;
  1339. case 0x12:
  1340. m_Interface->OutputConsoleString("This character's data has been corrupted. Please delete it and create a new character.");
  1341. break;
  1342. case 0x13:
  1343. m_Interface->OutputConsoleString("This character's starting server is experiencing difficulties. Please try again in a few minutes.");
  1344. break;
  1345. case 0x14:
  1346. m_Interface->OutputConsoleString("This character couldn't be placed in the world right now. Please try again in a few minutes.");
  1347. break;
  1348. case 0x15:
  1349. m_Interface->OutputConsoleString("Sorry, but the Asheron's Call server is full currently. Please try again later.");
  1350. break;
  1351. case 0x17:
  1352. m_Interface->OutputConsoleString("A save of this character is still in progress, please try again later.");
  1353. break;
  1354. default:
  1355. m_Interface->OutputConsoleString("Client: Received character error #%u", Error);
  1356. break;
  1357. }
  1358. }
  1359. //Is the server information even needed? *shrug*
  1360. void cNetwork::ProcessMessage(cMessage *Msg, stServerInfo *Server)
  1361. {
  1362. Msg->ReadBegin();
  1363. DWORD dwType = Msg->ReadDWORD();
  1364. // m_Interface->OutputConsoleString("Message: %04X", dwType);
  1365. switch ( dwType ) //Message Type
  1366. {
  1367. case 0x0024:
  1368. {
  1369. //destroy object
  1370. m_ObjectDB->DeleteObject(Msg->ReadDWORD());
  1371. break;
  1372. }
  1373. case 0x0197:
  1374. {
  1375. //adjust stack size
  1376. BYTE sequence = Msg->ReadByte();
  1377. DWORD item = Msg->ReadDWORD();
  1378. DWORD count = Msg->ReadDWORD();
  1379. DWORD value = Msg->ReadDWORD();
  1380. cWObject *tpObj = m_ObjectDB->FindObject(item);
  1381. if (!tpObj)
  1382. return;
  1383. tpObj->AdjustStack(count, value);
  1384. break;
  1385. }
  1386. case 0x019E:
  1387. {
  1388. //player kill
  1389. char * text = Msg->ReadString();
  1390. DWORD killee = Msg->ReadDWORD();
  1391. DWORD killer = Msg->ReadDWORD();
  1392. m_Interface->OutputString(eRed, "%s", text);
  1393. delete []text;
  1394. break;
  1395. }
  1396. case 0x01E0:
  1397. {
  1398. //indirect text
  1399. DWORD sender = Msg->ReadDWORD();
  1400. char *senderName = Msg->ReadString();
  1401. char *text = Msg->ReadString();
  1402. m_Interface->OutputString(eWhite, "Indirect: %s, %s", senderName, text);
  1403. delete []text;
  1404. delete []senderName;
  1405. break;
  1406. }
  1407. case 0x01E2:
  1408. {
  1409. //emote text
  1410. DWORD sender = Msg->ReadDWORD();
  1411. char *senderName = Msg->ReadString();
  1412. char *text = Msg->ReadString();
  1413. m_Interface->OutputString(eWhite, "Emote: %s, %s", senderName, text);
  1414. delete []text;
  1415. delete []senderName;
  1416. break;
  1417. }
  1418. case 0x02BB:
  1419. {
  1420. //chat window message
  1421. char *text = Msg->ReadString();
  1422. char *senderName = Msg->ReadString();
  1423. DWORD sender = Msg->ReadDWORD();
  1424. eColor type = (eColor) Msg->ReadDWORD();
  1425. m_Interface->OutputString(eRed, "<%s> %s", senderName, text);
  1426. delete []text;
  1427. delete []senderName;
  1428. break;
  1429. }
  1430. case 0x02BC:
  1431. {
  1432. //chat window message (ranged)
  1433. char *text = Msg->ReadString();
  1434. char *senderName = Msg->ReadString();
  1435. DWORD sender = Msg->ReadDWORD();
  1436. float range = Msg->ReadFloat();
  1437. eColor type = (eColor) Msg->ReadDWORD();
  1438. m_Interface->OutputString(type, "Ranged (%f): <%s> %s", range, senderName, text);
  1439. delete []text;
  1440. delete []senderName;
  1441. break;
  1442. }
  1443. case 0x02CD:
  1444. {
  1445. //set Character DWORD
  1446. BYTE sequence = Msg->ReadByte();
  1447. DWORD key = Msg->ReadDWORD();
  1448. DWORD value = Msg->ReadDWORD();
  1449. m_CharInfo->UpdateStatisticDW(key, value);
  1450. break;
  1451. }
  1452. case 0x02CE:
  1453. {
  1454. //set Object DWORD
  1455. BYTE sequence = Msg->ReadByte();
  1456. DWORD object = Msg->ReadDWORD();
  1457. DWORD key = Msg->ReadDWORD();
  1458. DWORD value = Msg->ReadDWORD();
  1459. //do something with this eventually...
  1460. break;
  1461. }
  1462. case 0x02CF:
  1463. {
  1464. //set Character QWORD
  1465. BYTE sequence = Msg->ReadByte();
  1466. DWORD key = Msg->ReadDWORD();
  1467. QWORD value = Msg->ReadQWORD();
  1468. m_CharInfo->UpdateStatisticQW(key, value);
  1469. break;
  1470. }
  1471. case 0x02D1:
  1472. {
  1473. //set Character Boolean
  1474. BYTE sequence = Msg->ReadByte();
  1475. DWORD key = Msg->ReadDWORD();
  1476. DWORD value = Msg->ReadDWORD();
  1477. m_CharInfo->UpdateStatisticBool(key, (value == 1));
  1478. break;
  1479. }
  1480. case 0x02D2:
  1481. {
  1482. //set Object Boolean
  1483. BYTE sequence = Msg->ReadByte();
  1484. DWORD object = Msg->ReadDWORD();
  1485. DWORD key = Msg->ReadDWORD();
  1486. DWORD value = Msg->ReadDWORD();
  1487. //do something with this eventually...
  1488. break;
  1489. }
  1490. case 0x02D6:
  1491. {
  1492. //set Object String
  1493. BYTE sequence = Msg->ReadByte();
  1494. DWORD key = Msg->ReadDWORD();
  1495. DWORD object = Msg->ReadDWORD();
  1496. Msg->ReadAlign();
  1497. char * value = Msg->ReadString();
  1498. //do something with this eventually...
  1499. delete []value;
  1500. break;
  1501. }
  1502. case 0x02D8:
  1503. {
  1504. //set Object Resource
  1505. BYTE sequence = Msg->ReadByte();
  1506. DWORD object = Msg->ReadDWORD();
  1507. DWORD key = Msg->ReadDWORD();
  1508. DWORD value = Msg->ReadDWORD();
  1509. //do something with this eventually...
  1510. break;
  1511. }
  1512. case 0x02D9:
  1513. {
  1514. //set Character Link
  1515. BYTE sequence = Msg->ReadByte();
  1516. DWORD key = Msg->ReadDWORD();
  1517. DWORD value = Msg->ReadDWORD();
  1518. switch (key)
  1519. {
  1520. case 0x0B:
  1521. m_Interface->SetLastAttacker(value);
  1522. break;
  1523. //fill in the rest of this
  1524. };
  1525. break;
  1526. }
  1527. case 0x02DA:
  1528. {
  1529. //set Object Link
  1530. BYTE sequence = Msg->ReadByte();
  1531. DWORD object = Msg->ReadDWORD();
  1532. DWORD key = Msg->ReadDWORD();
  1533. DWORD value = Msg->ReadDWORD();
  1534. //do something with this eventually
  1535. break;
  1536. }
  1537. case 0x02DB:
  1538. {
  1539. //set player location info
  1540. BYTE sequence = Msg->ReadByte();
  1541. DWORD key = Msg->ReadDWORD();
  1542. if (key == 0x0E)
  1543. {
  1544. //last corpse location
  1545. stLocation tploc;
  1546. memcpy(&tploc, Msg->ReadGroup(sizeof(stLocation)), sizeof(stLocation));
  1547. m_CharInfo->AddCorpse(tploc);
  1548. }
  1549. break;
  1550. }
  1551. case 0x02DD:
  1552. {
  1553. //set character skill level
  1554. BYTE sequence = Msg->ReadByte();
  1555. DWORD skill = Msg->ReadDWORD();
  1556. WORD raised = Msg->ReadWORD();
  1557. WORD unknown1 = Msg->ReadWORD();
  1558. DWORD trained = Msg->ReadDWORD();
  1559. DWORD xp = Msg->ReadDWORD();
  1560. DWORD bonus = Msg->ReadDWORD();
  1561. DWORD diff = Msg->ReadDWORD();
  1562. QWORD unknown2 = Msg->ReadQWORD();
  1563. m_CharInfo->UpdateSkill(skill, raised, trained, xp, bonus);
  1564. break;
  1565. }
  1566. case 0x02E1:
  1567. {
  1568. //set character skill train state
  1569. BYTE sequence = Msg->ReadByte();
  1570. DWORD skill = Msg->ReadDWORD();
  1571. DWORD skillTrained = Msg->ReadDWORD();
  1572. m_CharInfo->UpdateSkillTrain(skill, skillTrained);
  1573. break;
  1574. }
  1575. case 0x02E3:
  1576. {
  1577. //update character attribute
  1578. BYTE sequence = Msg->ReadByte();
  1579. DWORD Attribute = Msg->ReadDWORD();
  1580. DWORD NewIncrement = Msg->ReadDWORD();
  1581. DWORD StartingValue = Msg->ReadDWORD();
  1582. DWORD TotalAppliedXP = Msg->ReadDWORD();
  1583. m_CharInfo->UpdateAttribute(Attribute, NewIncrement, StartingValue, TotalAppliedXP);
  1584. break;
  1585. }
  1586. case 0x02E7:
  1587. {
  1588. //update character vital
  1589. BYTE sequence = Msg->ReadByte();
  1590. DWORD Attribute = Msg->ReadDWORD();
  1591. DWORD PointsAdded = Msg->ReadDWORD();
  1592. DWORD unknown1 = Msg->ReadDWORD();
  1593. DWORD TotalAppliedXP = Msg->ReadDWORD();
  1594. DWORD unknown2 = Msg->ReadDWORD();
  1595. m_CharInfo->UpdateSecondaryAttribute(Attribute, PointsAdded, TotalAppliedXP);
  1596. break;
  1597. }
  1598. case 0x02E9:
  1599. {
  1600. //update character current vital
  1601. BYTE sequence = Msg->ReadByte();
  1602. DWORD vital = Msg->ReadDWORD();
  1603. DWORD value = Msg->ReadDWORD();
  1604. m_CharInfo->UpdateVital(vital, value);
  1605. break;
  1606. }
  1607. case 0xF619:
  1608. {
  1609. //lifestone recall
  1610. //not going to bother right now...
  1611. break;
  1612. }
  1613. case 0xF625:
  1614. {
  1615. //change model
  1616. DWORD object = Msg->ReadDWORD();
  1617. cWObject *woThis = m_ObjectDB->FindObject(object);
  1618. if (!woThis)
  1619. {
  1620. m_ObjectDB->Unlock();
  1621. return;
  1622. }
  1623. woThis->ParseF625(Msg);
  1624. WORD modelSequenceType = Msg->ReadWORD();
  1625. WORD modelSequence = Msg->ReadWORD();
  1626. break;
  1627. }
  1628. case 0xF643:
  1629. {
  1630. //Character Create Result
  1631. DWORD dwResult = Msg->ReadDWORD();
  1632. if (dwResult == 1)
  1633. m_Interface->OutputConsoleString("Character successfully created.");
  1634. else
  1635. ServerCharCreateError(dwResult);
  1636. break;
  1637. }
  1638. case 0xF653:
  1639. {
  1640. //End 3D Mode
  1641. m_Interface->OutputConsoleString("End 3D Mode.");
  1642. m_Interface->SetInterfaceMode(eMOTD);
  1643. break;
  1644. }
  1645. case 0xF655:
  1646. {
  1647. //Char Deletion
  1648. break;
  1649. }
  1650. case 0xF658:
  1651. {
  1652. //Character List
  1653. stCharList CharList;
  1654. ZeroMemory(&CharList, sizeof(CharList));
  1655. Msg->ReadDWORD(); //unknown1
  1656. CharList.CharCount = Msg->ReadDWORD(); //characterCount
  1657. for (int i=0;i<CharList.CharCount;i++) //characters *Vector*
  1658. {
  1659. stCharList::CharInfo tpChar;
  1660. tpChar.GUID = Msg->ReadDWORD(); //character
  1661. char *tpName = Msg->ReadString(); //name
  1662. strcpy(tpChar.Name, tpName);
  1663. delete []tpName;
  1664. tpChar.DelTimeout = Msg->ReadDWORD(); //deleteTimeout
  1665. CharList.Chars.push_back(tpChar);
  1666. }
  1667. DWORD unknown2 = Msg->ReadDWORD(); //0?
  1668. CharList.CharSlots = Msg->ReadDWORD(); //slotCount - 0x0b
  1669. char *zoneName = Msg->ReadString(); //read Zone Name (WORD len + string)
  1670. CharList.ZoneName = std::string(zoneName);
  1671. delete []zoneName;
  1672. DWORD turbineChatEnabled = Msg->ReadDWORD(); //0x00010000
  1673. DWORD unknown3 = Msg->ReadDWORD(); //0x00010000
  1674. m_Interface->SetCharList(&CharList);
  1675. m_Interface->SetInterfaceMode(eMOTD);
  1676. break;
  1677. }
  1678. case 0xF659:
  1679. {
  1680. //Character Error
  1681. DWORD dwError = Msg->ReadDWORD();
  1682. ServerCharacterError(dwError);
  1683. break;
  1684. }
  1685. case 0xF745:
  1686. {
  1687. //create object
  1688. cWObject *tpObj = new cWObject();
  1689. tpObj->ParseF745(Msg);
  1690. m_ObjectDB->AddObject(tpObj);
  1691. if (tpObj->GetGUID() == m_dwGUIDLogin)
  1692. {
  1693. //cache it!
  1694. std::vector<stModelSwap> *mod = tpObj->GetModelSwaps();
  1695. std::vector<stTextureSwap> *tex = tpObj->GetTextureSwaps();
  1696. std::vector<stPaletteSwap> *pal = tpObj->GetPaletteSwaps();
  1697. char tpfn[80];
  1698. size_t iCount;
  1699. sprintf(tpfn, "%08X.charcache", tpObj->GetGUID());
  1700. FILE *tpo = fopen(tpfn, "wb");
  1701. iCount = mod->size(); fwrite(&iCount, 4, 1, tpo);
  1702. for (DWORD i=0;i<iCount;i++)
  1703. fwrite(&(*mod)[i], sizeof(stModelSwap), 1, tpo);
  1704. iCount = tex->size(); fwrite(&iCount, 4, 1, tpo);
  1705. for (DWORD i=0;i<iCount;i++)
  1706. fwrite(&(*tex)[i], sizeof(stTextureSwap), 1, tpo);
  1707. iCount = pal->size(); fwrite(&iCount, 4, 1, tpo);
  1708. for (DWORD i=0;i<iCount;i++)
  1709. fwrite(&(*pal)[i], sizeof(stPaletteSwap), 1, tpo);
  1710. fclose(tpo);
  1711. }
  1712. break;
  1713. }
  1714. case 0xF746:
  1715. {
  1716. DWORD object = Msg->ReadDWORD();
  1717. m_CharInfo->SetGUID(object);
  1718. break;
  1719. }
  1720. case 0xF747:
  1721. {
  1722. //remove item
  1723. DWORD object = Msg->ReadDWORD();
  1724. //hack
  1725. if (object == m_dwGUIDLogin)
  1726. return;
  1727. m_ObjectDB->DeleteObject(object);
  1728. DWORD unknown = Msg->ReadDWORD();
  1729. break;
  1730. }
  1731. case 0xF748:
  1732. {
  1733. //set position/motion
  1734. DWORD object = Msg->ReadDWORD();
  1735. cWObject *tpObj = m_ObjectDB->FindObject(object);
  1736. if (tpObj)
  1737. tpObj->ParseF748(Msg);
  1738. break;
  1739. }
  1740. case 0xF749:
  1741. {
  1742. //wield object... and other stuff
  1743. //figure this out at some point
  1744. break;
  1745. }
  1746. case 0xF74A:
  1747. {
  1748. //move object into inventory
  1749. //figure this out at some point
  1750. break;
  1751. }
  1752. case 0xF74B:
  1753. {
  1754. //toggle object visibility
  1755. DWORD character = Msg->ReadDWORD();
  1756. WORD portalType = Msg->ReadWORD();
  1757. WORD unknown_1 = Msg->ReadWORD();
  1758. WORD totalLogins = Msg->ReadWORD();
  1759. WORD loginPortals = Msg->ReadWORD();
  1760. if ((character == m_dwGUIDLogin) && (portalType == 0x4410))
  1761. {
  1762. //no portal mode!! Just materialize!
  1763. bPortalMode = true;
  1764. m_Interface->OutputConsoleString("I wanna mat!");
  1765. SendMaterialize();
  1766. }
  1767. break;
  1768. }
  1769. case 0xF74C:
  1770. {
  1771. //animation...
  1772. DWORD object = Msg->ReadDWORD();
  1773. cWObject *woThis = m_ObjectDB->FindObject(object);
  1774. if (!woThis)
  1775. return;
  1776. woThis->ParseF74C(Msg);
  1777. break;
  1778. }
  1779. case 0xF74E:
  1780. {
  1781. //jumping...
  1782. //figure this out at some point
  1783. break;
  1784. }
  1785. case 0xF750:
  1786. {
  1787. //sound effect
  1788. //figure this out at some point
  1789. break;
  1790. }
  1791. case 0xF751:
  1792. {
  1793. //enter portal mode
  1794. //figure this out at some point
  1795. break;
  1796. }
  1797. case 0xF755:
  1798. {
  1799. //visual/sound effect
  1800. //figure this out at some point
  1801. break;
  1802. }
  1803. case 0xF7DE:
  1804. {
  1805. //turbine chat
  1806. break;
  1807. }
  1808. case 0xF7DF:
  1809. {
  1810. // Server reported OK to enter world
  1811. //Enter 3D Mode
  1812. m_Interface->OutputConsoleString("Enter 3D Mode.");
  1813. SendEnterWorldMessage(m_dwGUIDLogin, m_zAccountName);
  1814. m_Interface->SetInterfaceMode(eGame);
  1815. break;
  1816. }
  1817. case 0xF7E0:
  1818. {
  1819. //display message
  1820. char *text = Msg->ReadString();
  1821. eColor color = (eColor) Msg->ReadDWORD();
  1822. m_Interface->OutputString(color, "%s", text);
  1823. delete []text;
  1824. break;
  1825. }
  1826. case 0xF7E1:
  1827. {
  1828. // # of players
  1829. DWORD players = Msg->ReadDWORD();
  1830. // # maximum number of players
  1831. DWORD max_players = Msg->ReadDWORD();
  1832. // server name
  1833. char *server = Msg->ReadString();
  1834. m_Interface->SetWorldPlayers(server, players, max_players);
  1835. delete []server;
  1836. //unknown WORD - 0x0000
  1837. break;
  1838. }
  1839. case 0xF7E5:
  1840. {
  1841. SendDDDInterrogationResponse();
  1842. break;
  1843. }
  1844. case 0xF7EA:
  1845. {
  1846. SendDDDEndMessage();
  1847. break;
  1848. }
  1849. case 0xF7B0:
  1850. {
  1851. DWORD character = Msg->ReadDWORD();
  1852. DWORD sequence = Msg->ReadDWORD();
  1853. DWORD event = Msg->ReadDWORD();
  1854. switch (event)
  1855. {
  1856. case 0x0013:
  1857. {
  1858. //login character...
  1859. m_CharInfo->ParseLogin(Msg);
  1860. //send materialize packet. H@x.
  1861. SendMaterialize();
  1862. break;
  1863. }
  1864. case 0x0020:
  1865. {
  1866. //allegiance info -- response to F7B1/1F query
  1867. m_CharInfo->ParseAllegiance(Msg);
  1868. break;
  1869. }
  1870. case 0x0021:
  1871. {
  1872. //Friends list Update
  1873. m_CharInfo->ParseFriendsUpdate(Msg);
  1874. break;
  1875. }
  1876. case 0x0029:
  1877. {
  1878. //TitleList
  1879. m_CharInfo->ParseTitleList(Msg);
  1880. break;
  1881. }
  1882. case 0x0196:
  1883. {
  1884. m_ObjectDB->ParsePackContents(Msg);
  1885. break;
  1886. }
  1887. case 0x004D:
  1888. {
  1889. //remove spell from spellbook
  1890. m_CharInfo->RemoveSpellFromBook(Msg->ReadDWORD());
  1891. WORD unknown = Msg->ReadWORD();
  1892. break;
  1893. }
  1894. case 0x01AD:
  1895. {
  1896. //kill/death message
  1897. char *text = Msg->ReadString();
  1898. m_Interface->OutputString(eWhite, "Kill/Death: %s", text);
  1899. delete []text;
  1900. break;
  1901. }
  1902. case 0x01C0:
  1903. {
  1904. //update creature health bar
  1905. DWORD object = Msg->ReadDWORD();
  1906. float health = Msg->ReadFloat();
  1907. //update the interface with this, soon as i make a selected object bar...
  1908. break;
  1909. }
  1910. case 0x01C3:
  1911. {
  1912. //age command result
  1913. char *unknown = Msg->ReadString();
  1914. char *age = Msg->ReadString();
  1915. m_Interface->OutputString(eYellow, "Your age: %s", age);
  1916. delete []age;
  1917. delete []unknown;
  1918. break;
  1919. }
  1920. case 0x01C7:
  1921. {
  1922. //previous action complete!
  1923. //uh, do we care...?
  1924. break;
  1925. }
  1926. case 0x01C8:
  1927. {
  1928. //Allegiance info
  1929. DWORD unkzero = Msg->ReadDWORD(); //no idea what this does, but the DWORD always seems to be zero
  1930. break;
  1931. }
  1932. case 0x01F4:
  1933. {
  1934. //squelched users list
  1935. m_CharInfo->ParseSquelches(Msg);
  1936. break;
  1937. }
  1938. case 0x0226:
  1939. {
  1940. //House info panel for non-owners
  1941. DWORD ownershipStatus = Msg->ReadDWORD();
  1942. //was "2" on my char.. means you do not own and can buy a new house immediately?
  1943. break;
  1944. }
  1945. case 0x028A:
  1946. {
  1947. //Action Failure!
  1948. DWORD reason = Msg->ReadDWORD();
  1949. switch (reason)
  1950. {
  1951. case 0x001D: m_Interface->OutputString(eGreen, "You're too busy!"); break;
  1952. case 0x001C: m_Interface->OutputString(eGreen, "You've charged too far!"); break;
  1953. case 0x0039: m_Interface->OutputString(eGreen, "Unable to move object!"); break;
  1954. case 0x03F7: m_Interface->OutputString(eGreen, "You're too fatigued to attack!"); break;
  1955. case 0x03F8: m_Interface->OutputString(eGreen, "You are out of ammunition!"); break;
  1956. case 0x03F9: m_Interface->OutputString(eGreen, "Your missile attack misfired!"); break;
  1957. case 0x03FA: m_Interface->OutputString(eGreen, "You've attempted an impossible spell path!"); break;
  1958. case 0x03FE: m_Interface->OutputString(eGreen, "You don't know that spell!"); break;
  1959. case 0x03FF: m_Interface->OutputString(eGreen, "Incorrect target type!"); break;
  1960. case 0x0400: m_Interface->OutputString(eGreen, "You don't have all the components for this spell."); break;
  1961. case 0x0401: m_Interface->OutputString(eGreen, "You don't have enough Mana to cast this spell."); break;
  1962. case 0x0402: m_Interface->OutputString(eGreen, "Your spell fizzled."); break;
  1963. case 0x0403: m_Interface->OutputString(eGreen, "Your spell's target is missing!"); break;
  1964. case 0x0404: m_Interface->OutputString(eGreen, "Your projectile spell mislaunched!"); break;
  1965. case 0x040A: m_Interface->OutputString(eGreen, "(You're not in combat mode!)?"); break;
  1966. case 0x043E: m_Interface->OutputString(eGreen, "You have solved this quest too recently!"); break;
  1967. case 0x043F: m_Interface->OutputString(eGreen, "You have solved this quest too many times!"); break;
  1968. case 0x051B: m_Interface->OutputString(eGreen, "You have entered your allegiance chat room."); break;
  1969. case 0x051C: m_Interface->OutputString(eGreen, "You have left an allegiance chat room."); break;
  1970. case 0x051D: m_Interface->OutputString(eGreen, "Turbine Chat is enabled."); break;
  1971. default: m_Interface->OutputString(eGreen, "28A - Error: %08X", reason); break;
  1972. };
  1973. break;
  1974. }
  1975. case 0x028B:
  1976. {
  1977. //Action Failure with Text!
  1978. DWORD reason = Msg->ReadDWORD();
  1979. char *text = Msg->ReadString();
  1980. switch (reason)
  1981. {
  1982. case 0x001E: m_Interface->OutputString(eLightBlue, "%s is too busy to accept gifts right now.", text); break;
  1983. case 0x002B: m_Interface->OutputString(eLightBlue, "%s cannot carry anymore.", text); break;
  1984. case 0x0051: m_Interface->OutputString(eLightBlue, "You fail to affect %s because you are not a player killer!", text); break;
  1985. case 0x03EF: m_Interface->OutputString(eLightBlue, "%s is not accepting gifts right now.", text); break;
  1986. case 0x046A: m_Interface->OutputString(eLightBlue, "%s doesn't know what to do with that.", text); break;
  1987. case 0x04D6: m_Interface->OutputString(eLightBlue, "You have succeeded in specializing your %s skill!", text); break;
  1988. case 0x04D7: m_Interface->OutputString(eLightBlue, "You have succeeded in lowering your %s skill from specialized to trained!", text); break;
  1989. case 0x04D8: m_Interface->OutputString(eLightBlue, "You have succeeded in untraining your %s skill!", text); break;
  1990. case 0x04D9: m_Interface->OutputString(eLightBlue, "Although you cannot untrain your %s skill, you have succeeded in recovering all the experience you had invested in it.", text); break;
  1991. case 0x04F6: m_Interface->OutputString(eLightBlue, "%s fails to affect you because %s is not a player killer!", text, text); break;
  1992. case 0x051B: m_Interface->OutputString(eGreen4, "You have entered the %s channel.", text); break;
  1993. default: m_Interface->OutputString(eLightBlue, "28B - Error: %08X, Text: %s", reason, text); break;
  1994. };
  1995. delete []text;
  1996. break;
  1997. }
  1998. case 0x0295:
  1999. {
  2000. //set (turbine? allegiance?) chat channel
  2001. DWORD channel = Msg->ReadDWORD();
  2002. break;
  2003. }
  2004. case 0x02BD:
  2005. {
  2006. //@tell to me
  2007. char *text = Msg->ReadString();
  2008. char *sourceName = Msg->ReadString();
  2009. DWORD source = Msg->ReadDWORD();
  2010. DWORD destination = Msg->ReadDWORD();
  2011. eColor color = (eColor) Msg->ReadDWORD();
  2012. // store the name
  2013. m_treeNameIDCache[ sourceName ] = source;
  2014. m_Interface->OutputString(color, "%s tells you, \"%s\"", sourceName, text);
  2015. delete []text;
  2016. delete []sourceName;
  2017. break;
  2018. }
  2019. case 0x02C1:
  2020. {
  2021. //add spell to spellbook
  2022. m_CharInfo->AddSpellToBook(Msg->ReadDWORD());
  2023. WORD unknown = Msg->ReadWORD();
  2024. break;
  2025. }
  2026. case 0x02C2:
  2027. {
  2028. //add enchantment
  2029. cEnchantment *tpench = new cEnchantment();
  2030. tpench->Unpack(Msg);
  2031. m_CharInfo->AddEnchantment(tpench);
  2032. break;
  2033. }
  2034. case 0x02C3:
  2035. {
  2036. //remove enchantment
  2037. WORD spell = Msg->ReadWORD();
  2038. WORD layer = Msg->ReadWORD();
  2039. m_CharInfo->RemoveEnchantment(spell, layer);
  2040. break;
  2041. }
  2042. case 0x02C6:
  2043. {
  2044. //remove ALL enchantments...
  2045. m_CharInfo->RemoveAllEnchantments();
  2046. break;
  2047. }
  2048. case 0x02C5: case 0x02C8:
  2049. {
  2050. //remove multiple enchantment, 2C8 is silently but whatever
  2051. DWORD count = Msg->ReadDWORD();
  2052. for (int i=0;i<(int)count;i++)
  2053. {
  2054. WORD spell = Msg->ReadWORD();
  2055. WORD layer = Msg->ReadWORD();
  2056. m_CharInfo->RemoveEnchantment(spell, layer);
  2057. }
  2058. break;
  2059. }
  2060. default:
  2061. {
  2062. {
  2063. WORD dataSize = Msg->GetLength() - 4 - 12;
  2064. const BYTE *data = Msg->ReadGroup(dataSize);
  2065. m_Interface->OutputConsoleString("Unhandled Packet: F7B0/%04X Contents:", event);
  2066. for (int i = 0; i <= ((dataSize - (dataSize % 16)) / 16); i++)
  2067. {
  2068. char valbuff[128]; memset(valbuff, 0, 128);
  2069. char linebuff[128]; memset(linebuff, 0, 128);
  2070. char strbuff[128]; memset(strbuff, 0, 128);
  2071. strcat(strbuff, "; ");
  2072. for (int j = i * 16; (j < ((i+1)*16)) && (j < dataSize); j++)
  2073. {
  2074. sprintf(valbuff, "%.1s", &data[j]);
  2075. strcat(strbuff, valbuff);
  2076. sprintf(valbuff, "%02X ", data[j]);
  2077. strcat(linebuff, valbuff);
  2078. }
  2079. strcat(linebuff, strbuff);
  2080. m_Interface->OutputConsoleString("%s", linebuff);
  2081. }
  2082. break;
  2083. }
  2084. break;
  2085. }
  2086. };
  2087. break;
  2088. }
  2089. ///---- Stuff below here hasn't been updated post-TOD!!! ----
  2090. /* case 0xF7B7://.DAT patch file
  2091. {
  2092. break;
  2093. }
  2094. case 0xF7B8://.DAT patching status
  2095. {
  2096. break;
  2097. }
  2098. case 0x0229:
  2099. {
  2100. //set coverage (misnamed)
  2101. BYTE sequence = Msg->ReadByte();
  2102. DWORD object = Msg->ReadDWORD();
  2103. DWORD unknown = Msg->ReadDWORD();
  2104. DWORD coverage = Msg->ReadDWORD();
  2105. cWObject *tpObj = m_ObjectDB->FindObject(object);
  2106. m_ObjectDB->Lock();
  2107. tpObj->Set229(unknown, coverage);
  2108. m_ObjectDB->Unlock();
  2109. break;
  2110. }
  2111. case 0x022D:
  2112. {
  2113. //set wielder/container
  2114. BYTE sequence = Msg->ReadByte();
  2115. DWORD object = Msg->ReadDWORD();
  2116. DWORD equipType = Msg->ReadDWORD();
  2117. DWORD container = Msg->ReadDWORD();
  2118. DWORD sequence2 = Msg->ReadDWORD();
  2119. cWObject *tpObj = m_ObjectDB->FindObject(object);
  2120. m_ObjectDB->Lock();
  2121. tpObj->Set22D(equipType, container);
  2122. m_ObjectDB->Unlock();
  2123. break;
  2124. }
  2125. case 0xF7AB:
  2126. {
  2127. //landblock+objects download
  2128. for (int i=0;i<2;i++)
  2129. {
  2130. DWORD landcell = Msg->ReadDWORD();
  2131. if (landcell)
  2132. {
  2133. DWORD bytesCompressed = Msg->ReadDWORD();
  2134. DWORD bytesUncompressed = Msg->ReadDWORD();
  2135. cPortalFile * pfTemp = new cPortalFile();
  2136. pfTemp->data = new BYTE[bytesUncompressed];
  2137. pfTemp->length = bytesUncompressed;
  2138. pfTemp->pos = 0;
  2139. pfTemp->id = landcell;
  2140. BYTE *tpCompLB = Msg->ReadGroup(bytesCompressed);
  2141. uncompress(pfTemp->data, (uLongf *) &bytesUncompressed, tpCompLB, bytesCompressed);
  2142. m_Interface->AddLandblock(pfTemp);
  2143. }
  2144. m_Interface->OutputString(eRed, "F7AB Downloaded Landblock: %08X", landcell);
  2145. }
  2146. break;
  2147. }
  2148. case 0xF7AC:
  2149. {
  2150. //is this ever used anymore?
  2151. //landblock download
  2152. DWORD landcell = Msg->ReadDWORD();
  2153. DWORD bytesCompressed = Msg->ReadDWORD();
  2154. DWORD bytesUncompressed = Msg->ReadDWORD();
  2155. // BYTE *tpCompLB = Msg->ReadGroup(bytesCompressed);
  2156. // cInterface::stLandblock tpLB;
  2157. // uncompress((BYTE *) &tpLB, (uLongf *) &bytesUncompressed, tpCompLB, bytesCompressed);
  2158. // m_Interface->AddLandblock(tpLB);
  2159. m_Interface->OutputString(eRed, "F7AC Downloaded Landblock: %08X", landcell);
  2160. break;
  2161. }*/
  2162. default:
  2163. {
  2164. WORD dataSize = Msg->GetLength() - 4;
  2165. const BYTE *data = Msg->ReadGroup(dataSize);
  2166. m_Interface->OutputConsoleString("Unhandled Packet: %04X Contents:", dwType);
  2167. for (int i = 0; i <= ((dataSize - (dataSize % 16)) / 16); i++)
  2168. {
  2169. char valbuff[128]; memset(valbuff, 0, 128);
  2170. char linebuff[128]; memset(linebuff, 0, 128);
  2171. char strbuff[128]; memset(strbuff, 0, 128);
  2172. strcat(strbuff, "; ");
  2173. for (int j = i * 16; (j < ((i+1)*16)) && (j < dataSize); j++)
  2174. {
  2175. sprintf(valbuff, "%.1s", &data[j]);
  2176. strcat(strbuff, valbuff);
  2177. sprintf(valbuff, "%02X ", data[j]);
  2178. strcat(linebuff, valbuff);
  2179. }
  2180. strcat(linebuff, strbuff);
  2181. m_Interface->OutputConsoleString("%s", linebuff);
  2182. }
  2183. break;
  2184. }
  2185. }
  2186. delete Msg;
  2187. }
  2188. void cNetwork::SendLSMessage(cPacket *Packet, WORD wGroup)
  2189. {
  2190. cPacket *Msg = new cPacket();
  2191. stTransitHeader TransHead;
  2192. stFragmentHeader FragHead;
  2193. TransHead.m_dwFlags = kLogonServerAddr;
  2194. TransHead.m_wSize = (WORD)sizeof(stFragmentHeader) + Packet->GetLength();
  2195. Lock();
  2196. FragHead.m_dwSequence = ++m_dwFragmentSequenceOut;
  2197. Unlock();
  2198. FragHead.m_dwID = 0x80000000;
  2199. FragHead.m_wIndex = 0;
  2200. FragHead.m_wCount = 1;
  2201. FragHead.m_wSize = (WORD)sizeof(stFragmentHeader) + Packet->GetLength();
  2202. FragHead.m_wGroup = wGroup;
  2203. Msg->Add(&TransHead);
  2204. Msg->Add(&FragHead);
  2205. Msg->Add(Packet->GetData(), Packet->GetLength());
  2206. SendLSPacket(Msg, true, true);
  2207. delete Packet;
  2208. }
  2209. void cNetwork::SendWSMessage(cPacket *Packet, WORD wGroup)
  2210. {
  2211. cPacket *Msg = new cPacket();
  2212. stTransitHeader TransHead;
  2213. stFragmentHeader FragHead;
  2214. TransHead.m_dwFlags = kEncryptedChecksum | kBlobFragments; // all world server packets have fragment flag?
  2215. TransHead.m_wSize = (WORD)sizeof(stFragmentHeader) + Packet->GetLength();
  2216. // XXX: no lock?
  2217. FragHead.m_dwSequence = ++m_dwFragmentSequenceOut;
  2218. FragHead.m_dwID = 0x80000000;
  2219. FragHead.m_wIndex = 0;
  2220. FragHead.m_wCount = 1;
  2221. FragHead.m_wSize = (WORD)sizeof(stFragmentHeader) + Packet->GetLength();
  2222. FragHead.m_wGroup = wGroup;
  2223. Msg->Add(&TransHead);
  2224. Msg->Add(&FragHead);
  2225. Msg->Add(Packet->GetData(), Packet->GetLength());
  2226. SendPacket(Msg, m_pActiveWorld, true, true);
  2227. delete Packet;
  2228. }
  2229. void cNetwork::SendLSGameEvent(cPacket *Packet, WORD wGroup)
  2230. {
  2231. cPacket *Event = new cPacket();
  2232. Event->Add(0xF7B1UL);
  2233. Event->Add(++m_dwGameEventOut);
  2234. Event->Add(Packet->GetData(), Packet->GetLength());
  2235. delete Packet;
  2236. SendLSMessage(Event, wGroup);
  2237. }
  2238. void cNetwork::SendWSGameEvent(cPacket *Packet, WORD wGroup)
  2239. {
  2240. cPacket *Event = new cPacket();
  2241. Event->Add(0xF7B1UL);
  2242. Event->Add(++m_dwGameEventOut);
  2243. Event->Add(Packet->GetData(), Packet->GetLength());
  2244. delete Packet;
  2245. SendWSMessage(Event, wGroup);
  2246. }
  2247. void cNetwork::DownloadLandblock(DWORD Landblock)
  2248. {
  2249. cPacket *LBReq = new cPacket();
  2250. LBReq->Add((DWORD) 0xF7E3);
  2251. LBReq->Add((DWORD) 0);
  2252. LBReq->Add(Landblock);
  2253. SendWSMessage(LBReq, 7);
  2254. }
  2255. void cNetwork::SendDDDInterrogationResponse() {
  2256. //stTransitHeader header;
  2257. cPacket *DDDResponsePacket = new cPacket();
  2258. //DDDResponsePacket->Add(&header, sizeof(header));
  2259. DDDResponsePacket->Add((DWORD)0xF7E6);
  2260. //SendLSPacket(DDDResponsePacket, false, false);
  2261. SendWSMessage(DDDResponsePacket, 0x0014); // 0x0014 from pcap
  2262. }
  2263. void cNetwork::SendDDDEndMessage() {
  2264. //stTransitHeader header;
  2265. cPacket *DDDEndPacket = new cPacket();
  2266. //DDDEndPacket->Add(&header, sizeof(header));
  2267. DDDEndPacket->Add((DWORD)0xF7EA);
  2268. //SendLSPacket(DDDEndPacket, false, false);
  2269. SendWSMessage(DDDEndPacket, 0x0014); // 0x0014 from pcap
  2270. }
  2271. void cNetwork::SendEnterWorldRequest(DWORD GUID)
  2272. {
  2273. bPortalMode = true;
  2274. m_dwGUIDLogin = GUID;
  2275. //send character enter world request
  2276. //stTransitHeader header;
  2277. //header.m_dwFlags = kEncryptedChecksum;
  2278. cPacket *EnterWorldReqPacket = new cPacket();
  2279. //EnterWorldReqPacket->Add(&header, sizeof(header));
  2280. EnterWorldReqPacket->Add((DWORD) 0xF7C8);
  2281. //SendLSPacket(EnterWorldReqPacket, false, false);
  2282. SendWSMessage(EnterWorldReqPacket, 0x0014); // 0x0014 from pcap
  2283. m_Interface->SetInterfaceMode(eEnteringGame);
  2284. // TODO: start timeout waiting for 0xF7DF message
  2285. }
  2286. void cNetwork::SendEnterWorldMessage(DWORD GUID, char* account_name)
  2287. {
  2288. //stTransitHeader header;
  2289. //header.m_dwFlags = kEncryptedChecksum;
  2290. cPacket *EnterWorldPacket = new cPacket();
  2291. //EnterWorldPacket->Add(&header, sizeof(header));
  2292. EnterWorldPacket->Add((DWORD)0xF657); // opcode for character enter world
  2293. EnterWorldPacket->Add(GUID); // character ID
  2294. EnterWorldPacket->Add(std::string(account_name));
  2295. EnterWorldPacket->Add((WORD)0x0000);
  2296. //SendLSPacket(EnterWorldPacket, false, false);
  2297. SendWSMessage(EnterWorldPacket, 0x0014); // 0x0014 from pcap
  2298. }
  2299. void cNetwork::SendPositionUpdate(stLocation *Location, stMoveInfo *MoveInfo)
  2300. {
  2301. cPacket *PosUpdate = new cPacket();
  2302. PosUpdate->Add((DWORD) 0xF753);
  2303. PosUpdate->Add(Location, sizeof(stLocation));
  2304. PosUpdate->Add(MoveInfo, sizeof(stMoveInfo));
  2305. PosUpdate->Add((DWORD) 0x00000001);
  2306. SendWSGameEvent(PosUpdate, 5);
  2307. }
  2308. void cNetwork::SendAnimUpdate(int iFB, int iStrafe, int iTurn, bool bRunning)
  2309. {
  2310. cWObject *woMyself = m_ObjectDB->FindObject(m_dwGUIDLogin);
  2311. if (!woMyself)
  2312. return;
  2313. stLocation *lTemp = woMyself->GetLocation();
  2314. stMoveInfo mTemp = woMyself->GetMoveInfo();
  2315. WORD wMyStance = woMyself->GetStance();
  2316. cPacket *CS = new cPacket();
  2317. CS->Add((DWORD) 0xF61C);
  2318. DWORD dwFlags = 0;
  2319. if (wMyStance == 0x49)
  2320. {
  2321. dwFlags |= 2;
  2322. }
  2323. if (iFB != 0)
  2324. {
  2325. dwFlags |= 4;
  2326. if (bRunning) dwFlags |= 1;
  2327. }
  2328. if (iTurn != 0)
  2329. {
  2330. dwFlags |= 0x102;
  2331. }
  2332. if (iStrafe != 0)
  2333. {
  2334. dwFlags |= 0x22;
  2335. }
  2336. CS->Add((DWORD) dwFlags);
  2337. if (dwFlags & 1)
  2338. CS->Add((DWORD) 2); //flag 1 - running
  2339. if (dwFlags & 2)
  2340. {
  2341. CS->Add((WORD) wMyStance);
  2342. CS->Add((WORD) 0x8000);
  2343. }
  2344. if (dwFlags & 4)
  2345. {
  2346. if (iFB > 0)
  2347. CS->Add((DWORD) 0x45000005); //flag 4 - forwards
  2348. else
  2349. CS->Add((DWORD) 0x45000006); //flag 4 - backwards
  2350. }
  2351. if (dwFlags & 0x20)
  2352. {
  2353. if (iStrafe > 0)
  2354. CS->Add((DWORD) 0x6500000F); //flag 20 - right
  2355. else
  2356. CS->Add((DWORD) 0x65000010); //flag 20 - left
  2357. }
  2358. if (dwFlags & 0x100)
  2359. {
  2360. if (iTurn > 0)
  2361. CS->Add((DWORD) 0x6500000D); //flag 100 - right
  2362. else
  2363. CS->Add((DWORD) 0x6500000E); //flag 100 - left
  2364. }
  2365. CS->Add(lTemp, sizeof(stLocation)); //full location
  2366. mTemp.moveCount = woMyself->GetAnimCount(); //f74ccount;
  2367. CS->Add(&mTemp, sizeof(stMoveInfo)); //movement info
  2368. CS->Add((DWORD) 1); //? also seen as 0 for just position updates...
  2369. SendWSGameEvent(CS, 5); //definitely group 5
  2370. }
  2371. void cNetwork::SetCombatMode(bool CombatMode)
  2372. {
  2373. cPacket *PosUpdate = new cPacket();
  2374. PosUpdate->Add((DWORD) 0x0053);
  2375. PosUpdate->Add((DWORD) (CombatMode ? 2 : 1));
  2376. SendWSGameEvent(PosUpdate, 5);
  2377. }
  2378. void cNetwork::CastSpell(DWORD Target, DWORD Spell)
  2379. {
  2380. cPacket *CS = new cPacket();
  2381. CS->Add((DWORD) 0x004A);
  2382. CS->Add(Target);
  2383. CS->Add(Spell);
  2384. SendWSGameEvent(CS, 5);
  2385. }
  2386. void cNetwork::UseItem(DWORD Item, DWORD Target)
  2387. {
  2388. //......
  2389. cPacket *UI = new cPacket();
  2390. UI->Add((DWORD) 0x0036);
  2391. UI->Add(Item);
  2392. SendWSGameEvent(UI, 5);
  2393. }
  2394. void cNetwork::SendAllegianceRecall()
  2395. {
  2396. cPacket *SPM = new cPacket();
  2397. SPM->Add( (DWORD) 0x0278 );
  2398. SendWSGameEvent( SPM, 5 );
  2399. }
  2400. void cNetwork::SendHouseRecall()
  2401. {
  2402. cPacket *SPM = new cPacket();
  2403. SPM->Add( (DWORD) 0x0262 );
  2404. SendWSGameEvent( SPM, 5 );
  2405. }
  2406. void cNetwork::SendLifestoneRecall()
  2407. {
  2408. cPacket *SPM = new cPacket();
  2409. SPM->Add( (DWORD) 0x0063 );
  2410. SendWSGameEvent( SPM, 5 );
  2411. }
  2412. void cNetwork::SendMarketplaceRecall()
  2413. {
  2414. cPacket *SPM = new cPacket();
  2415. SPM->Add( (DWORD) 0x28D );
  2416. SendWSGameEvent( SPM, 5 );
  2417. }
  2418. void cNetwork::SendPublicMessage(std::string & Message)
  2419. {
  2420. cPacket *SPM = new cPacket();
  2421. SPM->Add( (DWORD) 0x0015 );
  2422. SPM->Add( Message );
  2423. SendWSGameEvent( SPM, 5 );
  2424. }
  2425. void cNetwork::SendTell(std::string & Name, std::string & Message)
  2426. {
  2427. std::map< std::string, DWORD >::iterator i = m_treeNameIDCache.find( Name );
  2428. if( i != m_treeNameIDCache.end() )
  2429. SendTell( i->second, Message );
  2430. cPacket *SPM = new cPacket();
  2431. SPM->Add( (DWORD) 0x005D );
  2432. SPM->Add( Message );
  2433. SPM->Add( Name );
  2434. SendWSGameEvent( SPM, 5 );
  2435. }
  2436. void cNetwork::SendTell(DWORD dwGUID, std::string & Message)
  2437. {
  2438. cPacket *SPM = new cPacket();
  2439. SPM->Add( (DWORD) 0x0032 );
  2440. SPM->Add( Message );
  2441. SPM->Add( dwGUID );
  2442. SendWSGameEvent( SPM, 5 );
  2443. }
  2444. stServerInfo * cNetwork::AddWorldServer(SOCKADDR_IN NewServer)
  2445. {
  2446. Lock();
  2447. bool bFound = false;
  2448. stServerInfo *ToRet = NULL;
  2449. for (std::list<stServerInfo>::iterator i = m_siWorldServers.begin(); i != m_siWorldServers.end(); i++)
  2450. {
  2451. if (SockCompare(&NewServer, &(*i).m_saServer))
  2452. {
  2453. ToRet = &*i;
  2454. bFound = true;
  2455. break;
  2456. }
  2457. }
  2458. if (bFound) {
  2459. //don't duplicate or we'll end up resetting an existing server.
  2460. Unlock();
  2461. return ToRet;
  2462. }
  2463. stServerInfo tpNewServer;
  2464. //fill in tpNewServer struct...
  2465. memcpy(&tpNewServer.m_saServer, &NewServer, sizeof(SOCKADDR_IN));
  2466. tpNewServer.m_lSentPackets.clear();
  2467. tpNewServer.m_dwSendSequence = 1;
  2468. tpNewServer.m_wLogicalID = 0;
  2469. tpNewServer.m_wTable = 0;
  2470. tpNewServer.m_dwFlags = 0;
  2471. tpNewServer.m_dwLastPing = GetTickCount();
  2472. tpNewServer.m_dwLastSyncSent = 0;
  2473. tpNewServer.m_dwRecvSequence = 0; // should we start this at 2?
  2474. tpNewServer.m_dwLastPacketSent = GetTickCount();
  2475. tpNewServer.m_dwLastConnectAttempt = GetTickCount();
  2476. tpNewServer.m_dwLastPacketAck = GetTickCount();
  2477. // if we don't set the base port, the edge case handler for connect response will clobber our port!
  2478. tpNewServer.m_wBasePort = ntohs(NewServer.sin_port);
  2479. m_siWorldServers.push_back(tpNewServer);
  2480. m_Interface->OutputConsoleString("Added World Server: %s:%i",
  2481. inet_ntoa(tpNewServer.m_saServer.sin_addr),
  2482. (int)ntohs(tpNewServer.m_saServer.sin_port));
  2483. Unlock();
  2484. // race condition? shouldn't this return a pointer to tpNewServer instead, since back may have changed?
  2485. return &m_siWorldServers.back();
  2486. }
  2487. void cNetwork::DumpWorldServerList() {
  2488. for (std::list<stServerInfo>::iterator i = m_siWorldServers.begin(); i != m_siWorldServers.end(); i++)
  2489. {
  2490. m_Interface->OutputConsoleString("World server #%d -- %s:%d", i, inet_ntoa((*i).m_saServer.sin_addr), (int)ntohs((*i).m_saServer.sin_port));
  2491. }
  2492. }
  2493. void cNetwork::SetActiveWorldServer(SOCKADDR_IN NewServer)
  2494. {
  2495. bool foundServer = false;
  2496. m_Interface->OutputConsoleString("Selecting World Server: %s:%i...",
  2497. inet_ntoa(NewServer.sin_addr),
  2498. (int)ntohs(NewServer.sin_port));
  2499. Lock();
  2500. for (std::list<stServerInfo>::iterator i = m_siWorldServers.begin(); i != m_siWorldServers.end(); i++)
  2501. {
  2502. if (SockCompare(&NewServer, &(*i).m_saServer))
  2503. {
  2504. foundServer = true;
  2505. m_pActiveWorld = &(*i);
  2506. break;
  2507. }
  2508. }
  2509. Unlock();
  2510. if (!foundServer) {
  2511. m_Interface->OutputConsoleString("Couldn't set active world server -- specified server not found in list");
  2512. }
  2513. else {
  2514. m_Interface->OutputConsoleString("Selected world server.");
  2515. }
  2516. }
  2517. void cNetwork::SendMaterialize()
  2518. {
  2519. m_Interface->OutputConsoleString("Materialize!");
  2520. bPortalMode = false;
  2521. cPacket *Mat = new cPacket();
  2522. Mat->Add((DWORD) 0x00A1);
  2523. SendWSGameEvent(Mat, 5);
  2524. }
  2525. void cNetwork::SendHouseInfoQuery()
  2526. {
  2527. //Asks for housing info -- server responds with house info packet
  2528. cPacket *TestOut = new cPacket();
  2529. TestOut->Add((DWORD) 0x021E);
  2530. SendWSGameEvent(TestOut, 5);
  2531. }
  2532. void cNetwork::RequestAllegianceUpdate()
  2533. {
  2534. cPacket *AllegUpdate = new cPacket();
  2535. AllegUpdate->Add((DWORD) 0x1F);
  2536. AllegUpdate->Add((DWORD) 0x01); //seems to be ignored..?
  2537. SendLSGameEvent(AllegUpdate, 5);
  2538. }