- Main Page
- Classes
- Files

- File List
- File Members

# E:/uas2/Server/WorldManager.h

Go to the documentation of this file.

    00001 /*
    00002 * This file is part of UAS2.
    00003 *
    00004 * UAS2 is free software; you can redistribute it and/or modify
    00005 * it under the terms of the GNU General Public License as published by
    00006 * the Free Software Foundation; either version 2 of the License, or
    00007 * (at your option) any later version.
    00008 *
    00009 * UAS2 is distributed in the hope that it will be useful,
    00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00012 * GNU General Public License for more details.
    00013
    00014 * You should have received a copy of the GNU General Public License
    00015 * along with UASv1; if not, write to the Free Software
    00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00017 */
    00018
    00019 /* Special thanks to David Simpson for his work on the cell.dat and portal.dat extraction code */
    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                 { //crash occurs here
    00112                         if ( pcLB->m_wLandBlock == wLandBlock ) return pcLB;
    00113                         else  pcLB = pcLB->m_pcNext;
    00114
    00115                 }
    00116                 //UpdateConsole(" Landblock hash checked...%d\n",&wLandBlock);
    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                                 //UpdateConsole(Command);
    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 ); // Object changes landblock location
    00442         static BOOL MoveRemObject       ( cObject *pcObject ); // Object changes landblock location
    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                                 //UpdateConsole(" Item Checked: %s Type: %d\r\n", (*itObject)->Name(), (*itObject)->GetType());
    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                                         char szPortalInfo[100];
    00509                                         sprintf( szPortalInfo, "Portal Found:  %s, Range: %f, OldRange: %f\r\n", (*itObject)->Name(), flDist, flOldDist );
    00510                                         UpdateConsole((char *)szPortalInfo);
    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                         //UpdateConsole("Item Checked: %s Type: %d\r\n", (*itObject)->Name(), (*itObject)->GetType());
    00527                         if ( SpellGUID != (*itObject)->GetGUID() ) //(*itObject)->GetType() == 0 )
    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                                 //UpdateConsole((char *)szPortalInfo);
    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         //Test to find corpses
    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         //Find avatars
    00584         //Fix: Search within landblock focus.
    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 //                                              char szCharInfo[100];
    00596 //                                              sprintf( szCharInfo, "Client Avatar %d\n",(*itClient)->m_pcAvatar->m_dwGUID );
    00597 //                                              UpdateConsole ((char *)szCharInfo);
    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         //k109:  Added this to try and implement item ID in npc inventory.
    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         //TODO: Create list to hold recycled ObjectGUIDs (GUIDs of objects that have ceased existing).
    00628         //Preference would be given to using rec        ycled GUIDs from this list over creating new ones.
    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         static inline void RemoveObjectContainer( cClient *pcClient, cObject *pcObject, DWORD dwContainer )
    00667         {
    00668                 cMessage cmRemoveItem;
    00669                 cmRemoveItem << 0x0024L << pcObject->GetGUID( );
    00670                 pcClient->AddPacket(WORLD_SERVER,cmRemoveItem,4);
    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                 // Receive the create messages for all other object in focus range.
    00681                 ReceiveAllObjectsInFocus( pcClient, pcLB );
    00682                 // Send this avatar's create and materialize messages to others.
    00683                 /*
    00684                 BOOL fContinue;
    00685
    00686                 do
    00687                 {
    00688                         cMessage cmChildren = pcClient->m_pcAvatar->CreateChildren( fContinue );
    00689                         if( fContinue )
    00690                                 SendToAllInFocus( pcLB, cmChildren, 3 );
    00691                 } while ( fContinue );
    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