From e72a13c3dd10922a18d9ee59a7f62fbfb6b69c03 Mon Sep 17 00:00:00 2001 From: w12x Date: Mon, 27 Oct 2008 08:41:55 -0500 Subject: [PATCH] [svn] * Allow WorldObjects to keep the grid active, and prevent it from being unloaded. This can be done through calling WorldObject::setActive(bool) from the scripting library. Note that entire instances are still unloaded if no player is present on that map to save resources. This behavior can be changed if the need arises. --HG-- branch : trunk --- src/game/DynamicObject.cpp | 4 +-- src/game/GameObject.cpp | 4 +-- src/game/GridStates.cpp | 2 +- src/game/Map.cpp | 2 +- src/game/Object.cpp | 37 +++++++++++++++++++++++++++ src/game/Object.h | 10 +++++++- src/game/ObjectAccessor.cpp | 50 +++++++++++++++++++++++-------------- src/game/ObjectAccessor.h | 6 ++++- src/game/Pet.cpp | 1 + src/game/Pet.h | 2 ++ src/game/Player.cpp | 2 ++ src/game/Player.h | 2 ++ src/game/Unit.cpp | 4 +-- 13 files changed, 97 insertions(+), 29 deletions(-) diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 97ae5a75dd..c1f5212ca0 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -47,14 +47,14 @@ void DynamicObject::AddToWorld() { ///- Register the dynamicObject for guid lookup if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); - Object::AddToWorld(); + WorldObject::AddToWorld(); } void DynamicObject::RemoveFromWorld() { ///- Remove the dynamicObject from the accessor if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); - Object::RemoveFromWorld(); + WorldObject::RemoveFromWorld(); } bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 effIndex, float x, float y, float z, int32 duration, float radius ) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index fb29c2f56a..2a5b9fb186 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -82,14 +82,14 @@ void GameObject::AddToWorld() { ///- Register the gameobject for guid lookup if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); - Object::AddToWorld(); + WorldObject::AddToWorld(); } void GameObject::RemoveFromWorld() { ///- Remove the gameobject from the accessor if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); - Object::RemoveFromWorld(); + WorldObject::RemoveFromWorld(); } bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit) diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp index 4f27eae026..1f2df5e7c5 100644 --- a/src/game/GridStates.cpp +++ b/src/game/GridStates.cpp @@ -36,7 +36,7 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, c info.UpdateTimeTracker(t_diff); if( info.getTimeTracker().Passed() ) { - if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().PlayersNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) + if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().ActiveObjectsNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) { ObjectGridStoper stoper(grid); stoper.StopN(); diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 9deb86855a..04d7e02847 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -878,7 +878,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce) assert( grid != NULL); { - if(!pForce && ObjectAccessor::Instance().PlayersNearGrid(x, y, i_id, i_InstanceId) ) + if(!pForce && ObjectAccessor::Instance().ActiveObjectsNearGrid(x, y, i_id, i_InstanceId) ) return false; DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id); diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 304320f8ac..4486b03d80 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -974,6 +974,43 @@ WorldObject::WorldObject() m_name = ""; mSemaphoreTeleport = false; + + m_isActive = false; +} + +WorldObject::~WorldObject() +{ + if(m_isActive && IsInWorld()) + ObjectAccessor::Instance().RemoveActiveObject(this); +} + +void WorldObject::setActive(bool isActive) +{ + // if already in the same activity state as we try to set, do nothing + if(isActive == m_isActive) + return; + m_isActive = isActive; + if(IsInWorld()) + { + if(isActive) + ObjectAccessor::Instance().AddActiveObject(this); + else + ObjectAccessor::Instance().RemoveActiveObject(this); + } +} + +void WorldObject::AddToWorld() +{ + Object::AddToWorld(); + if(m_isActive) + ObjectAccessor::Instance().AddActiveObject(this); +} + +void WorldObject::RemoveFromWorld() +{ + if(m_isActive) + ObjectAccessor::Instance().RemoveActiveObject(this); + Object::RemoveFromWorld(); } void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid ) diff --git a/src/game/Object.h b/src/game/Object.h index 2fea4cefaa..65e7ea0b84 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -27,6 +27,7 @@ #include "UpdateData.h" #include "GameSystem/GridReference.h" #include "ObjectDefines.h" +#include "GridDefines.h" #include #include @@ -323,7 +324,11 @@ class TRINITY_DLL_SPEC Object class TRINITY_DLL_SPEC WorldObject : public Object { public: - virtual ~WorldObject ( ) {} + virtual ~WorldObject ( ); + + virtual void AddToWorld(); + + virtual void RemoveFromWorld(); virtual void Update ( uint32 /*time_diff*/ ) { } @@ -448,9 +453,12 @@ class TRINITY_DLL_SPEC WorldObject : public Object Map const* GetBaseMap() const; Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime); + bool isActive() const { return m_isActive; } + virtual void setActive(bool isActive); protected: explicit WorldObject(); std::string m_name; + bool m_isActive; private: uint32 m_mapId; diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index ecfff85d05..631ccc7fe6 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -504,23 +504,41 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid) return bones; } +void +ObjectAccessor::AddActiveObject( WorldObject * obj ) +{ + i_activeobjects.insert(obj); +} + +void +ObjectAccessor::RemoveActiveObject( WorldObject * obj ) +{ + i_activeobjects.erase(obj); +} + void ObjectAccessor::Update(uint32 diff) { { - typedef std::multimap CreatureLocationHolderType; - CreatureLocationHolderType creature_locations; - //TODO: Player guard + // player update might remove the player from grid, and that causes crashes. We HAVE to update players first, and then the active objects. HashMapHolder::MapType& playerMap = HashMapHolder::GetContainer(); for(HashMapHolder::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter) { if(iter->second->IsInWorld()) { iter->second->Update(diff); - creature_locations.insert( CreatureLocationHolderType::value_type(iter->second->GetMapId(), iter->second) ); } } + // clone the active object list, because update might remove from it + std::set activeobjects(i_activeobjects); + + std::set::const_iterator itr; + for(itr = activeobjects.begin(); itr != activeobjects.end(); ++itr) + { + (*itr)->GetMap()->resetMarkedCells(); + } + Map *map; Trinity::ObjectUpdater updater(diff); @@ -529,17 +547,12 @@ ObjectAccessor::Update(uint32 diff) // for pets TypeContainerVisitor world_object_update(updater); - for(CreatureLocationHolderType::iterator iter=creature_locations.begin(); iter != creature_locations.end(); ++iter) + for(itr = activeobjects.begin(); itr != activeobjects.end(); ++itr) { - MapManager::Instance().GetMap((*iter).first, (*iter).second)->resetMarkedCells(); - } + WorldObject *obj = (*itr); + map = obj->GetMap(); - for(CreatureLocationHolderType::iterator iter=creature_locations.begin(); iter != creature_locations.end(); ++iter) - { - Player *player = (*iter).second; - map = MapManager::Instance().GetMap((*iter).first, player); - - CellPair standing_cell(Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY())); + CellPair standing_cell(Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY())); // Check for correctness of standing_cell, it also avoids problems with update_cell if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) @@ -576,7 +589,7 @@ ObjectAccessor::Update(uint32 diff) } bool -ObjectAccessor::PlayersNearGrid(uint32 x, uint32 y, uint32 m_id, uint32 i_id) const +ObjectAccessor::ActiveObjectsNearGrid(uint32 x, uint32 y, uint32 m_id, uint32 i_id) const { CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); @@ -585,17 +598,16 @@ ObjectAccessor::PlayersNearGrid(uint32 x, uint32 y, uint32 m_id, uint32 i_id) co cell_max >> 2; cell_max += 2; - //TODO: Guard player - HashMapHolder::MapType& playerMap = HashMapHolder::GetContainer(); - for(HashMapHolder::MapType::const_iterator iter=playerMap.begin(); iter != playerMap.end(); ++iter) + for(std::set::const_iterator itr = i_activeobjects.begin(); itr != i_activeobjects.end(); ++itr) { - if( m_id != iter->second->GetMapId() || i_id != iter->second->GetInstanceId() ) + if( m_id != (*itr)->GetMapId() || i_id != (*itr)->GetInstanceId() ) continue; - CellPair p = Trinity::ComputeCellPair(iter->second->GetPositionX(), iter->second->GetPositionY()); + CellPair p = Trinity::ComputeCellPair((*itr)->GetPositionX(), (*itr)->GetPositionY()); if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) ) return true; + } return false; diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index 6e8b7f6d4c..b4ff57001a 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -193,13 +193,16 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton i_objects; + std::set i_activeobjects; LockType i_playerGuard; LockType i_updateGuard; LockType i_corpseGuard; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 99b10372bd..8505454274 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -96,6 +96,7 @@ Pet::Pet(PetType type) : Creature() m_CreatureCategoryCooldowns.clear(); m_autospells.clear(); m_declinedname = NULL; + m_isActive = true; } Pet::~Pet() diff --git a/src/game/Pet.h b/src/game/Pet.h index c34f06f2cc..e5beb3a388 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -122,6 +122,8 @@ class Pet : public Creature void AddToWorld(); void RemoveFromWorld(); + // always active + void setActive() {} PetType getPetType() const { return m_petType; } void setPetType(PetType type) { m_petType = type; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f28b763a0c..39ac45bde4 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -425,6 +425,8 @@ Player::Player (WorldSession *session): Unit() m_contestedPvPTimer = 0; m_declinedname = NULL; + + m_isActive = true; } Player::~Player () diff --git a/src/game/Player.h b/src/game/Player.h index a708c97399..0b927c60df 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -902,6 +902,8 @@ class TRINITY_DLL_SPEC Player : public Unit void AddToWorld(); void RemoveFromWorld(); + // always active + void setActive() {} bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 786ee62daf..d079219588 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9826,7 +9826,7 @@ uint32 Unit::GetCreatePowers( Powers power ) const void Unit::AddToWorld() { - Object::AddToWorld(); + WorldObject::AddToWorld(); } void Unit::RemoveFromWorld() @@ -9837,7 +9837,7 @@ void Unit::RemoveFromWorld() RemoveNotOwnSingleTargetAuras(); } - Object::RemoveFromWorld(); + WorldObject::RemoveFromWorld(); } void Unit::CleanupsBeforeDelete()