123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 |
- #include "StdAfx.h"
- #include "World.h"
- /*
- FAQ:
- Why track players and entities separatedly?
- Because players received network messages.
- */
- CLandBlock::CLandBlock(CWorld *pWorld, WORD wHeader)
- {
- m_pWorld = pWorld;
- m_wHeader = wHeader;
- m_bThinking = FALSE;
- m_fDeathTime = 0;
- }
- CLandBlock::~CLandBlock()
- {
- EntityVector::iterator eit = m_vSpawnEnts.begin();
- EntityVector::iterator eend = m_vSpawnEnts.end();
- while (eit != eend)
- {
- CPhysicsObj *pEntity = *eit;
- if (pEntity)
- {
- if (this == pEntity->GetBlock())
- {
- pEntity->Save();
- DELETE_ENTITY(pEntity);
- }
- }
- eit++;
- }
- eit = m_vLiveEnts.begin();
- eend = m_vLiveEnts.end();
- while (eit != eend)
- {
- CPhysicsObj *pEntity = *eit;
- if (pEntity)
- {
- if (this == pEntity->GetBlock())
- {
- pEntity->Save();
- DELETE_ENTITY(pEntity);
- }
- }
- eit++;
- }
- eit = m_vDormantEnts.begin();
- eend = m_vDormantEnts.end();
- while (eit != eend)
- {
- CPhysicsObj *pEntity = *eit;
- if (pEntity)
- {
- if (this == pEntity->GetBlock())
- {
- pEntity->Save();
- DELETE_ENTITY(pEntity);
- }
- }
- eit++;
- }
- m_mPlayers.clear();
- m_mEntities.clear();
- m_vPlayers.clear();
- m_vSpawnEnts.clear();
- m_vLiveEnts.clear();
- m_vDormantEnts.clear();
- }
- WORD CLandBlock::GetHeader()
- {
- return m_wHeader;
- }
- void CLandBlock::Insert(CPhysicsObj *pEntity, WORD wOld, BOOL bNew)
- {
- DWORD dwGUID = pEntity->m_dwGUID;
- if (pEntity->IsPlayer())
- {
- m_mPlayers.insert(std::pair<DWORD, CBasePlayer *>(dwGUID, (CBasePlayer *)pEntity));
- m_vPlayers.push_back((CBasePlayer *)pEntity);
- }
- m_mEntities.insert(std::pair<DWORD, CPhysicsObj *>(dwGUID, pEntity));
- m_vSpawnEnts.push_back(pEntity);
- pEntity->Attach(this);
- if (bNew)
- pEntity->RemovePreviousInstance();
- ExchangePVS(pEntity, wOld);
- }
- CPhysicsObj *CLandBlock::FindEntity(DWORD dwGUID)
- {
- EntityMap::iterator eit = m_mEntities.find(dwGUID);
- if (eit == m_mEntities.end())
- return NULL;
- return eit->second;
- }
- CBasePlayer *CLandBlock::FindPlayer(DWORD dwGUID)
- {
- PlayerMap::iterator pit = m_mPlayers.find(dwGUID);
- if (pit == m_mPlayers.end())
- return NULL;
- return pit->second;
- }
- /*
- ExchangeData --
- Makes all entities mutually aware of the source.
- */
- void CLandBlock::ExchangeData(CPhysicsObj *pSource)
- {
- EntityVector::iterator eit = m_vSpawnEnts.begin();
- EntityVector::iterator eend = m_vSpawnEnts.end();
- while (eit != eend)
- {
- CPhysicsObj *pEntity = (*eit);
- if (pEntity)
- {
- if (pEntity != pSource)
- {
- pEntity->MakeAware(pSource);
- pSource->MakeAware(pEntity);
- }
- //else
- // pEntity->MakeAware(pSource);
- eit++;
- continue;
- }
- eit = m_vSpawnEnts.erase(eit);
- eend = m_vSpawnEnts.end();
- }
- eit = m_vLiveEnts.begin();
- eend = m_vLiveEnts.end();
- while (eit != eend)
- {
- CPhysicsObj *pEntity = (*eit);
- if (pEntity)
- {
- if (pEntity != pSource)
- {
- pEntity->MakeAware(pSource);
- pSource->MakeAware(pEntity);
- }
- //else
- // pEntity->MakeAware(pSource);
- eit++;
- continue;
- }
- eit = m_vLiveEnts.erase(eit);
- eend = m_vLiveEnts.end();
- }
- eit = m_vDormantEnts.begin();
- eend = m_vDormantEnts.end();
- while (eit != eend)
- {
- CPhysicsObj *pEntity = (*eit);
- if (pEntity)
- {
- if (pEntity != pSource)
- {
- pEntity->MakeAware(pSource);
- pSource->MakeAware(pEntity);
- }
- //else
- // pEntity->MakeAware(pSource);
- eit++;
- continue;
- }
- eit = m_vDormantEnts.erase(eit);
- eend = m_vDormantEnts.end();
- }
- }
- void CLandBlock::ExchangePVS(CPhysicsObj *pSource, WORD wOld)
- {
- if (!pSource)
- return;
- BYTE xold, xstart, xend;
- BYTE yold, ystart, yend;
- xold = (wOld >> 8);
- xstart = (m_wHeader >> 8) - 1; if (xstart == (BYTE)-1) xstart = 0;
- xend = (m_wHeader >> 8) + 1; if (xend == (BYTE)0) xend = 0xFF;
- yold = (wOld & 0xFF);
- ystart = (m_wHeader & 0xFF) - 1; if (ystart == (BYTE)-1) ystart = 0;
- yend = (m_wHeader & 0xFF) + 1; if (yend == (BYTE)0) yend = 0xFF;
- for (WORD xit = xstart; xit <= xend; xit++)
- {
- for (WORD yit = ystart; yit <= yend; yit++)
- {
- if (wOld)
- {
- if ((xold >= (xit - 1)) && (xold <= (xit + 1)))
- {
- if ((yold >= (yit - 1)) && (yold <= (yit + 1)))
- continue;
- }
- }
- WORD wHeader = ((WORD)xit << 8) | yit;
- CLandBlock *pBlock = m_pWorld->GetLandblock(wHeader);
- if (pBlock)
- pBlock->ExchangeData(pSource);
- }
- }
- }
- void CLandBlock::Broadcast(void *_data, DWORD _len, WORD _group, DWORD ignore_ent, BOOL _game_event)
- {
- PlayerVector::iterator pit = m_vPlayers.begin();
- PlayerVector::iterator pend = m_vPlayers.end();
- while (pit != pend)
- {
- CBasePlayer *pPlayer = (*pit);
- if (pPlayer)
- {
- if (!ignore_ent || (ignore_ent != pPlayer->m_dwGUID))
- {
- pPlayer->SendNetMessage(_data, _len, _group, _game_event);
- }
- pit++;
- continue;
- }
- //remove NULL entries.
- pit = m_vPlayers.erase(pit);
- pend = m_vPlayers.end();
- }
- }
- void CLandBlock::Release(CPhysicsObj *pEntity)
- {
- if (pEntity->GetBlock() == this)
- pEntity->Detach();
- if (pEntity->IsPlayer())
- {
- m_mPlayers.erase(pEntity->m_dwGUID);
- PlayerVector::iterator pit = m_vPlayers.begin();
- PlayerVector::iterator pend = m_vPlayers.end();
- while (pit != pend)
- {
- if (pEntity == (*pit))
- {
- if (!m_bThinking)
- {
- pit = m_vPlayers.erase(pit);
- pend = m_vPlayers.end();
- continue;
- }
- else
- *pit = NULL;
- }
- pit++;
- }
- }
- m_mEntities.erase(pEntity->m_dwGUID);
- EntityVector::iterator eit = m_vSpawnEnts.begin();
- EntityVector::iterator eend = m_vSpawnEnts.end();
- while (eit != eend)
- {
- if (pEntity == (*eit))
- {
- if (!m_bThinking)
- {
- eit = m_vSpawnEnts.erase(eit);
- eend = m_vSpawnEnts.end();
- continue;
- }
- else
- *eit = NULL;
- }
- eit++;
- }
- eit = m_vLiveEnts.begin();
- eend = m_vLiveEnts.end();
- while (eit != eend)
- {
- if (pEntity == (*eit))
- {
- if (!m_bThinking)
- {
- eit = m_vLiveEnts.erase(eit);
- eend = m_vLiveEnts.end();
- continue;
- }
- else
- *eit = NULL;
- }
- eit++;
- }
- eit = m_vDormantEnts.begin();
- eend = m_vDormantEnts.end();
- while (eit != eend)
- {
- if (pEntity == (*eit))
- {
- if (!m_bThinking)
- {
- eit = m_vDormantEnts.erase(eit);
- eend = m_vDormantEnts.end();
- continue;
- }
- else
- *eit = NULL;
- }
- eit++;
- }
- }
- void CLandBlock::Destroy(CPhysicsObj *pEntity)
- {
- Release(pEntity);
- pEntity->Save();
- #if FALSE
- DWORD DestroyObject[2];
- DestroyObject[0] = 0x0024;
- DestroyObject[1] = pEntity->m_dwGUID;
- m_pWorld->BroadcastPVS(pEntity->GetLandcell(), DestroyObject, sizeof(DestroyObject), OBJECT_MSG, 0);
- #else
- DWORD RemoveObject[3];
- RemoveObject[0] = 0xF747;
- RemoveObject[1] = pEntity->m_dwGUID;
- RemoveObject[2] = pEntity->m_wInstance;
- m_pWorld->BroadcastPVS(pEntity->GetLandcell(), RemoveObject, sizeof(RemoveObject));
- // LOG(Temp, Normal, "Removing entity %08X %04X @ %08X \n", pEntity->m_dwGUID, pEntity->m_wInstance, pEntity->GetLandcell());
- #endif
- DELETE_ENTITY(pEntity);
- }
- void CLandBlock::SetEntityLive(CPhysicsObj *pEntity)
- {
- EntityVector::iterator eit = m_vLiveEnts.begin();
- EntityVector::iterator eend = m_vLiveEnts.end();
- while (eit != eend)
- {
- if (pEntity == (*eit))
- break;
- eit++;
- }
- if (eit == eend)
- {
- if (m_bThinking)
- OutputDebugString("Entity going live during think phase! AHH!\n");
- m_vLiveEnts.push_back(pEntity);
- }
- eit = m_vDormantEnts.begin();
- eend = m_vDormantEnts.end();
- while (eit != eend)
- {
- if (pEntity != (*eit))
- {
- eit++;
- continue;
- }
- eit = m_vDormantEnts.erase(eit);
- eend = m_vDormantEnts.end();
- }
- }
- BOOL CLandBlock::Think()
- {
- m_bThinking = TRUE;
- EntityVector::iterator eit = m_vLiveEnts.begin();
- EntityVector::iterator eend = m_vLiveEnts.end();
- while (eit != eend)
- {
- CPhysicsObj *pEntity = (*eit);
- if (!pEntity || pEntity->GetBlock() != this)
- {
- //remove NULL entries.
- eit = m_vLiveEnts.erase(eit);
- eend = m_vLiveEnts.end();
- continue;
- }
- //This entity *is* under our control
- WORD wHeader = BLOCK_WORD(pEntity->GetLandcell());
- if (wHeader == m_wHeader && !pEntity->HasOwner())
- {
- if (!pEntity->Think())
- {
- //This entity is going dormant.
- eit = m_vLiveEnts.erase(eit);
- eend = m_vLiveEnts.end();
- m_vDormantEnts.push_back(pEntity);
- }
- else
- eit++;
- continue;
- }
- //The entity should shift control.
- if (pEntity->IsPlayer())
- {
- m_mPlayers.erase(pEntity->m_dwGUID);
- PlayerVector::iterator pit = m_vPlayers.begin();
- PlayerVector::iterator pend = m_vPlayers.end();
- while (pit != pend)
- {
- if (pEntity == (*pit))
- {
- pit = m_vPlayers.erase(pit);
- pend = m_vPlayers.end();
- }
- else
- pit++;
- }
- }
- if (pEntity->GetBlock() == this)
- pEntity->Detach();
- m_mEntities.erase(pEntity->m_dwGUID);
- eit = m_vLiveEnts.erase(eit);
- eend = m_vLiveEnts.end();
- m_pWorld->JuggleEntity(m_wHeader, pEntity);
- }
- m_bThinking = FALSE;
- std::copy(m_vSpawnEnts.begin(), m_vSpawnEnts.end(), std::back_inserter(m_vLiveEnts));
- m_vSpawnEnts.clear();
- //This should be changed to be based off the death time.
- if (m_vLiveEnts.empty() && m_vDormantEnts.empty())
- {
- return FALSE;
- }
- return TRUE;
- }
- void CLandBlock::ClearSpawns()
- {
- EntityVector::iterator eit = m_vDormantEnts.begin();
- EntityVector::iterator eend = m_vDormantEnts.end();
- CPhysicsObj *pEntity;
- while (eit != eend)
- {
- pEntity = *eit;
- if (pEntity && !pEntity->m_bDontClear)
- {
- if (pEntity)
- {
- Destroy(pEntity);
- eit = m_vDormantEnts.begin();
- eend = m_vDormantEnts.end();
- }
- else
- {
- eit = m_vDormantEnts.erase(eit);
- eend = m_vDormantEnts.end();
- }
- }
- else
- {
- eit++;
- }
- }
- }
- void CLandBlock::EnumNearby(CPhysicsObj *pSource, float fRange, std::list<CPhysicsObj *> *pResults)
- {
- for (EntityMap::iterator i = m_mEntities.begin(); i != m_mEntities.end(); i++)
- {
- CPhysicsObj *pOther = i->second;
- if (pSource == pOther)
- continue;
- if ((Vector(pSource->m_Origin) - Vector(pOther->m_Origin)).Length() <= fRange)
- {
- pResults->push_back(pOther);
- }
- }
- }
|