diff --git a/src/game/Item.cpp b/src/game/Item.cpp index eb755b0221d..644c13dfa78 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -996,6 +996,14 @@ bool Item::IsBindedNotWith( Player const* player ) const } } +void Item::BuildUpdateData(UpdateDataMapType& update_players) +{ + if (Player* pl = GetOwner()) + BuildUpdateDataForPlayer(pl, update_players); + + ClearUpdateMask(false); +} + bool ItemRequiredTarget::IsFitToRequirements( Unit* pUnitTarget ) const { if(pUnitTarget->GetTypeId() != TYPEID_UNIT) diff --git a/src/game/Item.h b/src/game/Item.h index 5f92232bd18..a1b4440070d 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -313,6 +313,7 @@ class MANGOS_DLL_SPEC Item : public Object bool IsPotion() const { return GetProto()->IsPotion(); } bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); } + void BuildUpdateData(UpdateDataMapType& update_players); private: uint8 m_slot; Bag *m_container; diff --git a/src/game/Object.cpp b/src/game/Object.cpp index d7260cd8e20..08fcee5b454 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -128,7 +128,7 @@ void Object::BuildMovementUpdateBlock(UpdateData * data, uint32 flags ) const buf << uint8( UPDATETYPE_MOVEMENT ); buf.append(GetPackGUID()); - _BuildMovementUpdate(&buf, flags, 0x00000000); + BuildMovementUpdate(&buf, flags, 0x00000000); data->AddUpdateBlock(buf); } @@ -189,12 +189,12 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c buf.append(GetPackGUID()); buf << (uint8)m_objectTypeId; - _BuildMovementUpdate(&buf, flags, flags2); + BuildMovementUpdate(&buf, flags, flags2); UpdateMask updateMask; updateMask.SetCount( m_valuesCount ); _SetCreateBits( &updateMask, target ); - _BuildValuesUpdate(updatetype, &buf, &updateMask, target); + BuildValuesUpdate(updatetype, &buf, &updateMask, target); data->AddUpdateBlock(buf); } @@ -220,7 +220,7 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) c updateMask.SetCount( m_valuesCount ); _SetUpdateBits( &updateMask, target ); - _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target); + BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target); data->AddUpdateBlock(buf); } @@ -240,7 +240,7 @@ void Object::DestroyForPlayer( Player *target, bool anim ) const target->GetSession()->SendPacket( &data ); } -void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2) const +void Object::BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2) const { uint16 unk_flags = ((GetTypeId() == TYPEID_PLAYER) ? ((Player*)this)->m_movementInfo.unk1 : 0); @@ -567,7 +567,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 } } -void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const +void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const { if(!target) return; @@ -1065,6 +1065,20 @@ bool Object::PrintIndexError(uint32 index, bool set) const return false; } +void Object::BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_players) +{ + UpdateDataMapType::iterator iter = update_players.find(pl); + + if (iter == update_players.end()) + { + std::pair p = update_players.insert( UpdateDataMapType::value_type(pl, UpdateData()) ); + assert(p.second); + iter = p.first; + } + + BuildValuesUpdateBlockForPlayer(&iter->second, iter->first); +} + WorldObject::WorldObject() : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL) @@ -1857,3 +1871,33 @@ void WorldObject::UpdateObjectVisibility() GetMap()->UpdateObjectVisibility(this, cell, p); } +struct WorldObjectChangeAccumulator +{ + UpdateDataMapType &i_updateDatas; + WorldObject &i_object; + WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {} + void Visit(PlayerMapType &m) + { + for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if(iter->getSource()->HaveAtClient(&i_object)) + i_object.BuildUpdateDataForPlayer(iter->getSource(), i_updateDatas); + } + + template void Visit(GridRefManager &) {} +}; + +void WorldObject::BuildUpdateData( UpdateDataMapType & update_players) +{ + CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + WorldObjectChangeAccumulator notifier(*this, update_players); + TypeContainerVisitor player_notifier(notifier); + CellLock cell_lock(cell, p); + Map* aMap = GetMap(); + //we must build packets for all visible players + cell_lock->Visit(cell_lock, player_notifier, *aMap, *this, aMap->GetVisibilityDistance()); + + ClearUpdateMask(false); +} diff --git a/src/game/Object.h b/src/game/Object.h index f74e9659100..20b543eabee 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -148,6 +148,7 @@ class MANGOS_DLL_SPEC Object virtual void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const; void SendCreateUpdateToPlayer(Player* player); + virtual void BuildUpdateData(UpdateDataMapType& update_players) =0; void BuildValuesUpdateBlockForPlayer( UpdateData *data, Player *target ) const; void BuildOutOfRangeUpdateBlock( UpdateData *data ) const; void BuildMovementUpdateBlock( UpdateData * data, uint32 flags = 0 ) const; @@ -307,8 +308,9 @@ class MANGOS_DLL_SPEC Object virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const; - void _BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 ) const; - void _BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; + void BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 ) const; + void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; + void BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_players); uint16 m_objectType; @@ -339,8 +341,12 @@ class MANGOS_DLL_SPEC Object Object& operator=(Object const&); // prevent generation assigment operator }; +struct WorldObjectChangeAccumulator; + class MANGOS_DLL_SPEC WorldObject : public Object { + friend struct WorldObjectChangeAccumulator; + public: virtual ~WorldObject ( ) {} @@ -488,11 +494,11 @@ class MANGOS_DLL_SPEC WorldObject : public Object //this function should be removed in nearest time... Map const* GetBaseMap() const; - Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); + void BuildUpdateData(UpdateDataMapType &); + Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); protected: explicit WorldObject(); - std::string m_name; //these functions are used mostly for Relocate() and Corpse/Player specific stuff... //use them ONLY in LoadFromDB()/Create() funcs and nowhere else! @@ -500,6 +506,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; } void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; } + std::string m_name; + private: Map * m_currMap; //current object's Map location diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 1eb61903e16..dc377cd12db 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -182,49 +182,6 @@ ObjectAccessor::SaveAllPlayers() itr->second->SaveToDB(); } -void -ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players) -{ - if(obj->isType(TYPEMASK_ITEM)) - { - Item *item = static_cast(obj); - if (Player* pl = item->GetOwner()) - _buildPacket(pl, obj, update_players); - } - else - _buildChangeObjectForPlayer(static_cast(obj), update_players); -} - -void -ObjectAccessor::_buildPacket(Player *pl, Object *obj, UpdateDataMapType &update_players) -{ - UpdateDataMapType::iterator iter = update_players.find(pl); - - if( iter == update_players.end() ) - { - std::pair p = update_players.insert( UpdateDataValueType(pl, UpdateData()) ); - assert(p.second); - iter = p.first; - } - - obj->BuildValuesUpdateBlockForPlayer(&iter->second, iter->first); -} - -void -ObjectAccessor::_buildChangeObjectForPlayer(WorldObject *obj, UpdateDataMapType &update_players) -{ - CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - WorldObjectChangeAccumulator notifier(*obj, update_players); - TypeContainerVisitor player_notifier(notifier); - CellLock cell_lock(cell, p); - Map& map = *obj->GetMap(); - //we must build packets for all visible players - cell_lock->Visit(cell_lock, player_notifier, map, *obj, map.GetVisibilityDistance()); -} - Pet* ObjectAccessor::GetPet(uint64 guid) { @@ -386,8 +343,7 @@ ObjectAccessor::Update(uint32 diff) i_objects.erase(i_objects.begin()); if (!obj) continue; - _buildUpdateObject(obj, update_players); - obj->ClearUpdateMask(false); + obj->BuildUpdateData(update_players); } } @@ -400,14 +356,6 @@ ObjectAccessor::Update(uint32 diff) } } -void -ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m) -{ - for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if(iter->getSource()->HaveAtClient(&i_object)) - ObjectAccessor::_buildPacket(iter->getSource(), &i_object, i_updateDatas); -} - /// Define the static member of HashMapHolder template UNORDERED_MAP< uint64, T* > HashMapHolder::m_objectMap; diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index 7f6027dc137..5778732c765 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -89,7 +89,6 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton Player2CorpsesMapType; - typedef UNORDERED_MAP::value_type UpdateDataValueType; template static T* GetObjectInWorld(uint64 guid, T* /*fake*/) { @@ -180,21 +179,10 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton void Visit(GridRefManager &) {} - }; - // TODO: This methods will need lock in MT environment // Theoreticaly multiple threads can enter and search in this method but // in that case linking/delinking other map should be guarded @@ -213,14 +201,11 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton i_mapList; - friend struct WorldObjectChangeAccumulator; Player2CorpsesMapType i_player2corpse; typedef ACE_Thread_Mutex LockType; typedef MaNGOS::GeneralLock Guard; - static void _buildChangeObjectForPlayer(WorldObject *, UpdateDataMapType &); - static void _buildPacket(Player *, Object *, UpdateDataMapType &); std::set i_objects; LockType i_playerGuard; LockType i_updateGuard; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5f38308c827..d993e1e040d 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8676" + #define REVISION_NR "8677" #endif // __REVISION_NR_H__