00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00025 #ifndef __WORLDMANAGER_H
00026 #define __WORLDMANAGER_H
00027
00028 #pragma warning(disable:4786) //warning: identifier was truncated to '255' characters in the browser information
00029
00030 #include <winsock2.h>
00031 #include <algorithm>
00032 #include <stack>
00033
00034 #include "Avatar.h"
00035 #include "Client.h"
00036 #include "Object.h"
00037
00038 #define CELLSECSIZE 64
00039 #define NUMFILELOC 0x03F
00040 #define ROOTDIRPTRLOC 0x148
00041
00042 class cLandBlock
00043 {
00044 friend class cWorldManager;
00045
00046 public:
00047 cLandBlock( WORD wLandBlock, BOOL fAddToHash = TRUE )
00048 : m_wLandBlock( wLandBlock ),
00049 m_pcPrev ( NULL ),
00050 m_pcNext ( NULL )
00051 {
00052 if ( fAddToHash )
00053 Hash_Add( this );
00054 Load_LandBlockZ( this );
00055 }
00056
00057 ~cLandBlock( )
00058 {
00059 const WORD wSum = HIBYTE( m_wLandBlock ) + LOBYTE( m_wLandBlock );
00060 if ( m_pcPrev ) m_pcPrev->m_pcNext = m_pcNext;
00061 else m_lpcHashTable[wSum] = m_pcNext;
00062 if ( m_pcNext ) m_pcNext->m_pcPrev = m_pcPrev;
00063 }
00064
00065 static inline void Hash_Load( )
00066 {
00067 ZeroMemory( m_lpcHashTable, sizeof( m_lpcHashTable ) );
00068 }
00069
00070 static inline void Hash_Unload( )
00071 {
00072 cLandBlock *pcLB, *pcPrevLB;
00073 for ( int i = 0; i < 510; ++i )
00074 {
00075 pcLB = m_lpcHashTable[i];
00076 while ( pcLB )
00077 {
00078 pcPrevLB = pcLB;
00079 pcLB = pcLB->m_pcNext;
00080
00081 while ( !pcPrevLB->m_lstObjects.empty( ) )
00082 {
00083 SAFEDELETE( pcPrevLB->m_lstObjects.front( ) )
00084 pcPrevLB->m_lstObjects.pop_front( );
00085 }
00086
00087 SAFEDELETE( pcPrevLB )
00088 }
00089 }
00090 }
00091
00092 static inline cLandBlock *Hash_New( WORD wLandBlock )
00093 {
00094 cLandBlock *pcLB = Hash_Find( wLandBlock );
00095 if ( pcLB )
00096 return pcLB;
00097
00098 return new cLandBlock( wLandBlock );
00099 }
00100
00101 static inline void Hash_Remove( cLandBlock *pcLB )
00102 {
00103 SAFEDELETE( pcLB )
00104 }
00105
00106 static inline cLandBlock *Hash_Find( WORD wLandBlock )
00107 {
00108 const WORD wSum = HIBYTE( wLandBlock ) + LOBYTE( wLandBlock );
00109 cLandBlock *pcLB = m_lpcHashTable[wSum];
00110 while ( pcLB )
00111 {
00112 if ( pcLB->m_wLandBlock == wLandBlock ) return pcLB;
00113 else pcLB = pcLB->m_pcNext;
00114
00115 }
00116
00117 return NULL;
00118 }
00119
00120 WORD m_wLandBlock;
00121 float m_flLandBlockZ[9][9];
00122
00123 private:
00124 static cLandBlock *m_lpcHashTable[510];
00125
00126 static inline void Hash_Add( cLandBlock *pcLB )
00127 {
00128 const WORD wSum = HIBYTE( pcLB->m_wLandBlock ) + LOBYTE( pcLB->m_wLandBlock );
00129 if ( !m_lpcHashTable[wSum] )
00130 m_lpcHashTable[wSum] = pcLB;
00131 else
00132 {
00133 pcLB->m_pcNext = m_lpcHashTable[wSum];
00134 m_lpcHashTable[wSum]->m_pcPrev = pcLB;
00135 m_lpcHashTable[wSum] = pcLB;
00136 }
00137 }
00138
00147 static inline void Load_LandBlockZ( cLandBlock *pcLB )
00148 {
00149 FILE *inFile;
00150 int read;
00151 UINT rootDirPtr, id, filePos, len;
00152 UCHAR *buf, *zData;
00153
00154 inFile = fopen("cell.dat", "rb");
00155 if (inFile == NULL)
00156 {
00157 UpdateConsole(" Cell.dat: Open failed.\r\n");
00158 return;
00159 }
00160 read = fseek(inFile, ROOTDIRPTRLOC, SEEK_SET);
00161 if (read != 0)
00162 {
00163 UpdateConsole(" Cell.dat: Read error.\r\n");
00164 fclose(inFile);
00165 return;
00166 }
00167
00168 read = fread(&rootDirPtr, sizeof(UINT), 1, inFile);
00169 if (read != 1)
00170 {
00171 UpdateConsole(" Cell.dat: End of file reached.\r\n");
00172 fclose(inFile);
00173 return;
00174 }
00175
00176 id = pcLB->m_wLandBlock * 0x10000 + 0xFFFF;
00177
00178 if (!cLandBlock::FetchFilePos(inFile, rootDirPtr, id, &filePos, &len))
00179 {
00180 UpdateConsole(" Cell.dat: File not found.\r\n");
00181 fclose(inFile);
00182 return;
00183 }
00184
00185 buf = (UCHAR *)malloc(len);
00186 if (!cLandBlock::FetchFile(inFile, filePos, len, buf))
00187 {
00188 free(buf);
00189 fclose(inFile);
00190 return;
00191 }
00192
00193 zData = &buf[170];
00194 char Command[100];
00195 for (int x = 0; x < 9; x++)
00196 {
00197 for (int y = 0; y < 9; y++)
00198 {
00199 pcLB->m_flLandBlockZ[x][y] = zData[x * 9 + y];
00200 sprintf(Command,"zData: %f\r\n", pcLB->m_flLandBlockZ[x][y]);
00201
00202 }
00203 }
00204
00205 free(buf);
00206 fclose(inFile);
00207 }
00208
00218 static inline int FetchFilePos(FILE *inFile, UINT dirPos, UINT id, UINT *filePos, UINT *len)
00219 {
00220 UINT dir[4 * CELLSECSIZE];
00221 UINT i;
00222 UINT numFiles;
00223 int read;
00224
00225 while (1)
00226 {
00227 if (dirPos == 0)
00228 {
00229 UpdateConsole(" Cell.dat: NULL directory entry found.\r\n");
00230 return 0;
00231 }
00232
00233 read = fseek(inFile, dirPos, SEEK_SET);
00234 if (read != 0)
00235 {
00236 UpdateConsole(" Cell.dat: Sector is beyond end of file.\r\n");
00237 return 0;
00238 }
00239
00240 read = fread(dir, sizeof(UINT), CELLSECSIZE, inFile);
00241 if (read != CELLSECSIZE)
00242 {
00243 UpdateConsole(" Cell.dat: Sector doesn't contain enough words.\r\n");
00244 return 0;
00245 }
00246
00247 dirPos = dir[0];
00248
00249 if (dirPos != 0)
00250 {
00251 read = fseek(inFile, dirPos, SEEK_SET);
00252 if (read != 0)
00253 {
00254 UpdateConsole(" Cell.dat: Seek is beyond end of file.\r\n");
00255 return 0;
00256 }
00257
00258 read = fread(&dirPos, sizeof(UINT), 1, inFile);
00259 if (read != 1)
00260 {
00261 UpdateConsole(" Cell.dat: Sector does not exist.\r\n");
00262 return 0;
00263 }
00264
00265 read = fread(&dir[CELLSECSIZE], sizeof(UINT), CELLSECSIZE - 1, inFile);
00266 if (read != CELLSECSIZE - 1)
00267 {
00268 UpdateConsole(" Cell.dat: Sector doesn't contain enough words.\r\n");
00269 return 0;
00270 }
00271 }
00272
00273 if (dirPos != 0)
00274 {
00275 read = fseek(inFile, dirPos, SEEK_SET);
00276 if (read != 0)
00277 {
00278 UpdateConsole(" Cell.dat: Seek is beyond end of file.\r\n");
00279 return 0;
00280 }
00281
00282 read = fread(&dirPos, sizeof(UINT), 1, inFile);
00283 if (read != 1)
00284 {
00285 UpdateConsole(" Cell.dat: Sector does not exist.\r\n");
00286 return 0;
00287 }
00288
00289 read = fread(&dir[CELLSECSIZE * 2 - 1], sizeof(UINT), CELLSECSIZE - 1, inFile);
00290 if (read != CELLSECSIZE - 1)
00291 {
00292 UpdateConsole(" Cell.dat: Sector doesn't contain enough words.\r\n");
00293 return 0;
00294 }
00295 }
00296
00297 if (dirPos != 0)
00298 {
00299 read = fseek(inFile, dirPos, SEEK_SET);
00300 if (read != 0)
00301 {
00302 UpdateConsole(" Cell.dat: Seek is beyond end of file\r\n");
00303 return 0;
00304 }
00305
00306 read = fread(&dirPos, sizeof(UINT), 1, inFile);
00307 if (read != 1)
00308 {
00309 UpdateConsole(" Cell.dat: Sector does not exist.\r\n");
00310 return 0;
00311 }
00312
00313 read = fread(&dir[CELLSECSIZE * 3 - 2], sizeof(UINT), CELLSECSIZE - 1, inFile);
00314 if (read != CELLSECSIZE - 1)
00315 {
00316 UpdateConsole(" Cell.dat: Sector doesn't contain enough words\r\n");
00317 return 0;
00318 }
00319 }
00320
00321 numFiles = dir[NUMFILELOC];
00322 if (numFiles >= NUMFILELOC)
00323 {
00324 UpdateConsole(" Cell.dat: Number of files exceeds directory entries.\r\n");
00325 return 0;
00326 }
00327
00328 i = 0;
00329 while ((i < numFiles) && (id > dir[i * 3 + NUMFILELOC + 1]))
00330 {
00331 i++;
00332 }
00333 if (i < numFiles)
00334 {
00335 if (id == dir[i*3 + NUMFILELOC + 1])
00336 {
00337 *filePos = dir[i * 3 + NUMFILELOC + 2];
00338 *len = dir[i * 3 + NUMFILELOC + 3];
00339 return 1;
00340 }
00341 }
00342
00343 if (dir[1] == 0)
00344 {
00345 filePos = 0;
00346 len = 0;
00347 return 0;
00348 }
00349
00350 dirPos = dir[i + 1];
00351 }
00352 return 0;
00353 }
00354
00363 static inline int FetchFile(FILE *inFile, UINT filePos, UINT len, UCHAR *buf)
00364 {
00365 int read, doChain;
00366 UINT sec[CELLSECSIZE];
00367
00368 if (filePos == 0)
00369 {
00370 UpdateConsole(" Cell.dat: Null file pointer found.\r\n");
00371 return 0;
00372 }
00373
00374 doChain = 1;
00375 while (doChain)
00376 {
00377 read = fseek(inFile, filePos, SEEK_SET);
00378 if (read != 0)
00379 {
00380 UpdateConsole(" Cell.dat: Seek failed.\r\n");
00381 return 0;
00382 }
00383
00384 read = fread(sec, sizeof(UINT), CELLSECSIZE, inFile);
00385 if (read != CELLSECSIZE)
00386 {
00387 UpdateConsole(" Cell.dat: Sector doesn't contain enough words.\r\n");
00388 return 0;
00389 }
00390
00391 filePos = sec[0] * 0x7FFFFFFF;
00392
00393 if (len > (CELLSECSIZE - 1) * sizeof(UINT))
00394 {
00395 memcpy(buf, &sec[1], (CELLSECSIZE - 1) * sizeof(UINT));
00396 buf += (CELLSECSIZE - 1) * sizeof(UINT);
00397 len -= (CELLSECSIZE - 1) * sizeof(UINT);
00398 }
00399 else
00400 {
00401 memcpy(buf, &sec[1], len);
00402 len = 0;
00403 }
00404
00405 if (filePos == 0)
00406 doChain = 0;
00407 }
00408
00409 return 1;
00410 }
00411
00412 std::list< cClient * > m_lstClients;
00413 std::list< cClient * > m_lstFocusedClients;
00414 std::list< cObject * > m_lstObjects;
00415 cLandBlock *m_pcPrev;
00416 cLandBlock *m_pcNext;
00417 };
00418
00419 class cWorldManager
00420 {
00421 friend class cMasterServer;
00422
00423 public:
00424 cWorldManager ( ) {}
00425 ~cWorldManager ( ) {}
00426
00427 typedef std::vector< ConfirmPanel >::iterator iterConfirmPanel_lst;
00428
00429 static void Load( );
00430
00431 static void Unload( );
00432
00433 static BOOL RemoveClient ( cClient *pcClient, BOOL fRemoveAvatar = TRUE, BOOL fDeleteAvatar = TRUE );
00434 static BOOL AddClient ( cClient *pcClient, BOOL fSpawnAvatar = TRUE );
00435 static BOOL MoveAvatar ( cClient *pcClient, cLocation& NewLoc, WORD wAnim = 0, float flPlaySpeed = 1.0f );
00436 static BOOL TeleportAvatar ( cClient *pcClient, cLocation& NewLoc );
00437
00438 static BOOL RemoveObject ( cObject *pcObject, BOOL fRemoveObject = TRUE, BOOL fDeleteObject = TRUE );
00439
00440 static BOOL AddObject ( cObject *pcObject, BOOL fSpawnObject = TRUE );
00441 static BOOL MoveAddObject ( cObject *pcObject );
00442 static BOOL MoveRemObject ( cObject *pcObject );
00443
00444 static void RemoveAllObjects( );
00445
00446 static inline void SendToAllInLandBlock( cLocation& Loc, cMessage& cmPacket, WORD wGroup )
00447 {
00448 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( Loc.m_dwLandBlock ) );
00449
00450 if ( pcLB )
00451 SendToAllInLandBlock( pcLB, cmPacket, wGroup );
00452 }
00453
00454 static inline void SendToAllInFocus( cLocation& Loc, cMessage& cmPacket, WORD wGroup )
00455 {
00456 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( Loc.m_dwLandBlock ) );
00457
00458 if ( pcLB )
00459 SendToAllInFocus( pcLB, cmPacket, wGroup );
00460 }
00461
00462 static inline void SendToAllWithin( BYTE bDistance, cLocation& Loc, cMessage& cmPacket, WORD wGroup )
00463 {
00464 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( Loc.m_dwLandBlock ) );
00465
00466 if ( pcLB )
00467 SendToAllWithin( bDistance, pcLB, cmPacket, wGroup );
00468 }
00469
00470 static inline void SendToOthersInLandBlock( cLocation& Loc, cClient *pcClient, cMessage& cmPacket, WORD wGroup )
00471 {
00472 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( Loc.m_dwLandBlock ) );
00473
00474 if ( pcLB )
00475 SendToOthersInLandBlock( pcLB, pcClient, cmPacket, wGroup );
00476 }
00477
00478 static inline void SendToOthersInFocus( cLocation& Loc, cClient *pcClient, cMessage& cmPacket, WORD wGroup )
00479 {
00480 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( Loc.m_dwLandBlock ) );
00481
00482 if ( pcLB )
00483 SendToOthersInFocus( pcLB, pcClient, cmPacket, wGroup );
00484 }
00485
00486 static inline void SendToOthersWithin( BYTE bDistance, cLocation& Loc, cClient *pcClient, cMessage& cmPacket, WORD wGroup )
00487 {
00488 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( Loc.m_dwLandBlock ) );
00489
00490 if ( pcLB )
00491 SendToOthersWithin( bDistance, pcLB, pcClient, cmPacket, wGroup );
00492 }
00493
00494 static inline cObject *GetCollisionPortal( cLocation OldLoc, cLocation NewLoc )
00495 {
00496 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( OldLoc.m_dwLandBlock ) );
00497
00498
00499 for ( iterObject_lst itObject = pcLB->m_lstObjects.begin( ); itObject != pcLB->m_lstObjects.end( ); ++itObject )
00500
00501 {
00502
00503 if ( (*itObject)->GetType() == 1000 )
00504 {
00505 float flDist = cPhysics::Get3DLineDistance( OldLoc, NewLoc, (*itObject)->m_Location );
00506 float flOldDist = cPhysics::Get3DRange( OldLoc, (*itObject)->m_Location );
00507
00508
00509
00510
00511
00512 if ( flDist < .05 && flOldDist >= .05)
00513 return *itObject;
00514 }
00515 }
00516
00517 return NULL;
00518 }
00519
00520 static inline cObject *GetCollisionMonster( DWORD SpellGUID, cLocation SpellLoc )
00521 {
00522 cLandBlock *pcLB = cLandBlock::Hash_Find( HIWORD( SpellLoc.m_dwLandBlock ) );
00523
00524 for ( iterObject_lst itObject = pcLB->m_lstObjects.begin( ); itObject != pcLB->m_lstObjects.end( ); ++itObject )
00525 {
00526
00527 if ( SpellGUID != (*itObject)->GetGUID() )
00528 {
00529
00530 float flDist = cPhysics::GetRange( SpellLoc, (*itObject)->m_Location );
00531
00532
00533 char szPortalInfo[100];
00534 sprintf( szPortalInfo, "Collision Target: %s, Range: %f\r\n", (*itObject)->Name(), flDist );
00535
00536
00537 if ( flDist < .05 && (*itObject)->m_dwObjectFlags1 & 0x00000010 && (*itObject)->m_fDeadOrAlive == true)
00538 return *itObject;
00539 }
00540 }
00541 return NULL;
00542 }
00543
00544 static inline cObject *FindObject( DWORD dwGUID )
00545 {
00546 cLandBlock *pcLB;
00547 for ( int i = 0; i < 510; ++i )
00548 {
00549 pcLB = cLandBlock::m_lpcHashTable[i];
00550 while ( pcLB )
00551 {
00552 for ( iterObject_lst itObject = pcLB->m_lstObjects.begin( ); itObject != pcLB->m_lstObjects.end( ); ++itObject )
00553 {
00554 if ( dwGUID == (*itObject)->GetGUID( ) )
00555 return *itObject;
00556 }
00557 pcLB = pcLB->m_pcNext;
00558 }
00559 }
00560 return NULL;
00561 }
00562
00563
00564 static inline cCorpse *FindCorpse( DWORD dwGUID )
00565 {
00566 cLandBlock *pcLB;
00567 for ( int i = 0; i < 510; ++i )
00568 {
00569 pcLB = cLandBlock::m_lpcHashTable[i];
00570 while ( pcLB )
00571 {
00572 for ( iterObject_lst itObject = pcLB->m_lstObjects.begin( ); itObject != pcLB->m_lstObjects.end( ); ++itObject )
00573 {
00574 if ( dwGUID == (*itObject)->GetGUID( ) )
00575 return reinterpret_cast<cCorpse *>(*itObject);
00576 }
00577 pcLB = pcLB->m_pcNext;
00578 }
00579 }
00580 return NULL;
00581 }
00582
00583
00584
00585 static inline cAvatar *FindAvatar( DWORD dwGUID )
00586 {
00587 cLandBlock *pcLB;
00588 for ( int i = 0; i < 510; ++i )
00589 {
00590 pcLB = cLandBlock::m_lpcHashTable[i];
00591 while ( pcLB )
00592 {
00593 for ( iterClient_lst itClient = pcLB->m_lstClients.begin( ); itClient != pcLB->m_lstClients.end( ); ++itClient )
00594 {
00595
00596
00597
00598 if ( dwGUID == (*itClient)->m_pcAvatar->m_dwGUID )
00599 return reinterpret_cast<cAvatar *>((*itClient)->m_pcAvatar);
00600 }
00601 pcLB = pcLB->m_pcNext;
00602 }
00603 }
00604 return NULL;
00605 }
00606
00607
00608 static inline cNPC *FindNPC( DWORD dwGUID )
00609 {
00610 cLandBlock *pcLB;
00611 for ( int i = 0; i < 510; ++i )
00612 {
00613 pcLB = cLandBlock::m_lpcHashTable[i];
00614 while ( pcLB )
00615 {
00616 for ( iterObject_lst itObject = pcLB->m_lstObjects.begin( ); itObject != pcLB->m_lstObjects.end( ); ++itObject )
00617 {
00618 if ( dwGUID == (*itObject)->GetGUID( ) )
00619 return reinterpret_cast<cNPC *>(*itObject);
00620 }
00621 pcLB = pcLB->m_pcNext;
00622 }
00623 }
00624 return NULL;
00625 }
00626
00627
00628
00629 static inline UINT NewGUID_Avatar ( ) { return ++m_dwGUIDCycle_Avatar; }
00630 static inline UINT NewGUID_Object ( ) { return ++m_dwGUIDCycle_Object; }
00631 static inline void AddUnusedAvatarGUID ( DWORD dwGUID ) { m_lstUnusedAvatarGUIDs.push_back(dwGUID); }
00632 static inline void AddUnusedObjectGUID ( DWORD dwGUID ) { m_lstUnusedObjectGUIDs.push_back(dwGUID); }
00633 static inline DWORD GetUnusedAvatarGUID ( ) { return m_lstUnusedAvatarGUIDs.back(); }
00634 static inline DWORD GetUnusedObjectGUID ( ) { return m_lstUnusedObjectGUIDs.back(); }
00635
00636 static char g_szAccessFile[MAX_PATH+20];
00637
00638 static inline DWORD CurrentConfirmSeq ( ) { return m_dwConfirmSequence; }
00639 static inline DWORD NewConfirmSeq ( ) { return ++m_dwConfirmSequence; }
00640
00641 static void AddPendingConfirm ( DWORD sequence, DWORD type, std::string szText, DWORD senderGUID, DWORD receiptGUID = NULL );
00642 static void FindPendingConfirm ( DWORD dwSeq, DWORD dwReply );
00643
00644 private:
00645 static inline void RemoveAvatar( cClient *pcClient, cLandBlock *pcLB, WORD wAnim = 0, float flPlaySpeed = 1.0f )
00646 {
00647 if ( wAnim )
00648 {
00649 pcClient->m_pcAvatar->LogoutCharacter();
00650 cMessage cmAnim = pcClient->m_pcAvatar->Animation( wAnim, flPlaySpeed );
00651 SendToAllInFocus( pcLB, cmAnim, 3 );
00652 }
00653
00654 cMessage cmRemModel;
00655 cmRemModel << 0xF747L << pcClient->m_pcAvatar->GetGUID( ) << DWORD( pcClient->m_pcAvatar->m_wNumLogins );
00656 SendToOthersInFocus( pcLB, pcClient, cmRemModel, 3 );
00657 }
00658
00659 static inline void RemoveObject( cObject *pcObject, cLandBlock *pcLB )
00660 {
00661 cMessage cmRemModel;
00662 cmRemModel << 0xF747L << pcObject->GetGUID( ) << DWORD( pcObject->m_wNumLogins );
00663 SendToAllInFocus( pcLB, cmRemModel, 3 );
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673 static inline void SpawnAvatar( cClient *pcClient, cLandBlock *pcLB )
00674 {
00675 cMessage cmLogin;
00676
00677 *((DWORD *)&MSG_00000002[4]) = pcClient->m_pcAvatar->GetGUID( );
00678 cmLogin.CannedData( MSG_00000002, sizeof( MSG_00000002 ) );
00679
00680
00681 ReceiveAllObjectsInFocus( pcClient, pcLB );
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 SendToOthersInFocus( pcLB, pcClient, pcClient->m_pcAvatar->CreatePacket( ), 3 );
00695 SendToAllInFocus( pcLB, cmLogin, 3 );
00696
00697 }
00698
00699 static inline void SpawnObject( cObject *pcObject, cLandBlock *pcLB, cClient *pcClient = NULL )
00700 {
00701 if( pcClient )
00702 SendToOthersInFocus( pcLB, pcClient, pcObject->CreatePacket( ), 3 );
00703 else
00704 SendToAllInFocus( pcLB, pcObject->CreatePacket( ), 3 );
00705 }
00706
00707 static inline void SendToAllInLandBlock( cLandBlock *pcLB, cMessage& cmPacket, WORD wGroup )
00708 {
00709 for ( iterClient_lst itClient = pcLB->m_lstClients.begin( ); itClient != pcLB->m_lstClients.end( ); ++itClient )
00710 (*itClient)->AddPacket( WORLD_SERVER, cmPacket, wGroup );
00711 }
00712
00713 static inline void SendToAllInFocus( cLandBlock *pcLB, cMessage& cmPacket, WORD wGroup )
00714 {
00715 SendToAllInLandBlock( pcLB, cmPacket, wGroup );
00716 for ( iterClient_lst itClient = pcLB->m_lstFocusedClients.begin( ); itClient != pcLB->m_lstFocusedClients.end( ); ++itClient )
00717 (*itClient)->AddPacket( WORLD_SERVER, cmPacket, wGroup );
00718
00719 }
00720 static inline void SendToAllWithin( BYTE bDistance, cLandBlock *pcLB, cMessage& cmPacket, WORD wGroup )
00721 {
00722 const WORD wDiameter = (bDistance * 2 + 1) * (bDistance * 2 + 1);
00723 WORD *pwLBs = new WORD[wDiameter];
00724 LandBlocksWithin( bDistance, pcLB->m_wLandBlock, pwLBs );
00725
00726 SendToAllInLandBlock( pcLB, cmPacket, wGroup );
00727 for ( int i = 0; i < wDiameter - 1; ++i )
00728 {
00729 pcLB = cLandBlock::Hash_Find( pwLBs[i] );
00730 if ( pcLB )
00731 SendToAllInLandBlock( pcLB, cmPacket, wGroup );
00732 }
00733 SAFEDELETE_ARRAY( pwLBs )
00734 }
00735
00736 static inline void SendToOthersInLandBlock( cLandBlock *pcLB, cClient *pcClient, cMessage& cmPacket, WORD wGroup )
00737 {
00738 for ( iterClient_lst itClient = pcLB->m_lstClients.begin( ); itClient != pcLB->m_lstClients.end( ); ++itClient )
00739 {
00740 if ( pcClient != *itClient )
00741 (*itClient)->AddPacket( WORLD_SERVER, cmPacket, wGroup );
00742 }
00743 }
00744
00745 static inline void SendToOthersInFocus( cLandBlock *pcLB, cClient *pcClient, cMessage& cmPacket, WORD wGroup )
00746 {
00747 SendToOthersInLandBlock( pcLB, pcClient, cmPacket, wGroup );
00748
00749 for ( iterClient_lst itClient = pcLB->m_lstFocusedClients.begin( ); itClient != pcLB->m_lstFocusedClients.end( ); ++itClient )
00750 {
00751 if ( pcClient != *itClient )
00752 {
00753 try
00754 {
00755 (*itClient)->AddPacket( WORLD_SERVER, cmPacket, wGroup );
00756 }
00757 catch ( char * str )
00758 {
00759 UpdateConsole(" Exception occured: %s", str);
00760 }
00761 }
00762 }
00763 }
00764
00765 static inline void SendToOthersWithin( BYTE bDistance, cLandBlock *pcLB, cClient *pcClient, cMessage& cmPacket, WORD wGroup )
00766 {
00767 const WORD wDiameter = (bDistance * 2 + 1) * (bDistance * 2 + 1);
00768 WORD *pwLBs = new WORD[wDiameter];
00769 LandBlocksWithin( bDistance, pcLB->m_wLandBlock, pwLBs );
00770
00771 SendToOthersInLandBlock( pcLB, pcClient, cmPacket, wGroup );
00772 for ( int i = 0; i < wDiameter - 1; ++i )
00773 {
00774 pcLB = cLandBlock::Hash_Find( pwLBs[i] );
00775 if ( pcLB )
00776 SendToOthersInLandBlock( pcLB, pcClient, cmPacket, wGroup );
00777 }
00778 SAFEDELETE_ARRAY( pwLBs )
00779 }
00780
00781 static inline void AddClient( cLandBlock *pcLB, cClient *pcClient )
00782 {
00783 iterClient_lst itClient = std::find( pcLB->m_lstClients.begin( ), pcLB->m_lstClients.end( ), pcClient );
00784
00785 if ( itClient == pcLB->m_lstClients.end( ) )
00786 pcLB->m_lstClients.push_back( pcClient );
00787 }
00788
00789 static inline void AddFocus( cLandBlock *pcLB, cClient *pcClient )
00790 {
00791 iterClient_lst itClient = std::find( pcLB->m_lstFocusedClients.begin( ), pcLB->m_lstFocusedClients.end( ), pcClient );
00792
00793 if ( itClient == pcLB->m_lstFocusedClients.end( ) )
00794 pcLB->m_lstFocusedClients.push_back( pcClient );
00795 }
00796
00797 static inline void AddObject( cLandBlock *pcLB, cObject *pcObject )
00798 {
00799 iterObject_lst itObject = std::find( pcLB->m_lstObjects.begin( ), pcLB->m_lstObjects.end( ), pcObject );
00800
00801 if ( itObject == pcLB->m_lstObjects.end( ) )
00802 pcLB->m_lstObjects.push_back( pcObject );
00803 }
00804
00805 static inline BOOL RemClient( cLandBlock *pcLB, cClient *pcClient )
00806 {
00807 iterClient_lst itClient = std::find( pcLB->m_lstClients.begin( ), pcLB->m_lstClients.end( ), pcClient );
00808
00809 if ( itClient == pcLB->m_lstClients.end( ) )
00810 return FALSE;
00811
00812 pcLB->m_lstClients.erase( itClient );
00813 if ( pcLB->m_lstClients.empty( ) && pcLB->m_lstFocusedClients.empty( ) && pcLB->m_lstObjects.empty( ) )
00814 cLandBlock::Hash_Remove( pcLB );
00815
00816 return TRUE;
00817 }
00818
00819 static inline BOOL RemFocus( cLandBlock *pcLB, cClient *pcClient)
00820 {
00821 iterClient_lst itClient = std::find( pcLB->m_lstFocusedClients.begin( ), pcLB->m_lstFocusedClients.end( ), pcClient );
00822
00823 if ( itClient == pcLB->m_lstFocusedClients.end( ) )
00824 return FALSE;
00825
00826 pcLB->m_lstFocusedClients.erase( itClient );
00827
00828 if ( pcLB->m_lstClients.empty( ) && pcLB->m_lstFocusedClients.empty( ) && pcLB->m_lstObjects.empty( ) )
00829 cLandBlock::Hash_Remove( pcLB );
00830
00831 return TRUE;
00832 }
00833
00834 static inline BOOL RemObject( cLandBlock *pcLB, cObject *pcObject )
00835 {
00836 iterObject_lst itObject = std::find( pcLB->m_lstObjects.begin( ), pcLB->m_lstObjects.end( ), pcObject );
00837
00838 if ( itObject == pcLB->m_lstObjects.end( ) )
00839 return FALSE;
00840
00841 pcLB->m_lstObjects.erase( itObject );
00842 return TRUE;
00843 }
00844
00845 static void ReceiveAllObjectsInFocus ( cClient *pcClient, cLandBlock *pcLB );
00846 static void ReceiveAllObjectsInLandBlock( cClient *pcClient, cLandBlock *pcLB );
00847
00848 static void LandBlocksWithin( BYTE bDistance, WORD wCenterLB, WORD *pwStore );
00849
00850 static DWORD m_dwGUIDCycle_Avatar;
00851 static DWORD m_dwGUIDCycle_Object;
00852 static std::list< DWORD > m_lstUnusedAvatarGUIDs;
00853 static std::list< DWORD > m_lstUnusedObjectGUIDs;
00854
00855 static DWORD m_dwConfirmSequence;
00856 static std::vector< ConfirmPanel > m_lstConfirmsPending;
00857 };
00858
00859 #endif // #ifndef __WORLDMANAGER_H