Move object update from ObjectAccessor to Map update.

This commit is contained in:
hunuza 2008-11-15 00:31:51 +01:00
parent d287a17597
commit 0d1b8038f5
6 changed files with 204 additions and 89 deletions

View file

@ -562,6 +562,63 @@ bool Map::loaded(const GridPair &p) const
void Map::Update(const uint32 &t_diff) void Map::Update(const uint32 &t_diff)
{ {
resetMarkedCells();
//TODO: Player guard
HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer();
for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter)
{
WorldObject* obj = iter->second;
if(!obj->IsInWorld())
continue;
if(obj->GetMapId() != GetId())
continue;
if(obj->GetInstanceId() != GetInstanceId())
continue;
CellPair standing_cell(MaNGOS::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)
continue;
// the overloaded operators handle range checking
// so ther's no need for range checking inside the loop
CellPair begin_cell(standing_cell), end_cell(standing_cell);
begin_cell << 1; begin_cell -= 1; // upper left
end_cell >> 1; end_cell += 1; // lower right
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x)
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y)
markCell(x,y);
}
MaNGOS::ObjectUpdater updater(t_diff);
// for creature
TypeContainerVisitor<MaNGOS::ObjectUpdater, GridTypeMapContainer > grid_object_update(updater);
// for pets
TypeContainerVisitor<MaNGOS::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater);
for(int x = 0; x < TOTAL_NUMBER_OF_CELLS_PER_MAP; ++x)
{
for(int y = 0; y < TOTAL_NUMBER_OF_CELLS_PER_MAP; ++y)
{
if(isCellMarked(x,y))
{
CellPair pair(x,y);
Cell cell(pair);
cell.data.Part.reserved = CENTER_DISTRICT;
cell.SetNoCreate();
CellLock<NullGuard> cell_lock(cell, pair);
cell_lock->Visit(cell_lock, grid_object_update, *this);
cell_lock->Visit(cell_lock, world_object_update, *this);
}
}
}
// Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load !
// This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
if (IsBattleGroundOrArena()) if (IsBattleGroundOrArena())

View file

@ -230,8 +230,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair); void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair);
void resetMarkedCells() { marked_cells.reset(); } void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } bool isCellMarked(uint32 x, uint32 y) { return marked_cells.test(y * TOTAL_NUMBER_OF_CELLS_PER_MAP + x); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); } void markCell(uint32 x, uint32 y) { marked_cells.set(y * TOTAL_NUMBER_OF_CELLS_PER_MAP + x); }
private: private:
void LoadVMap(int pX, int pY); void LoadVMap(int pX, int pY);
void LoadMap(uint32 mapid, uint32 instanceid, int x,int y); void LoadMap(uint32 mapid, uint32 instanceid, int x,int y);

View file

@ -244,6 +244,8 @@ MapManager::Update(time_t diff)
if( !i_timer.Passed() ) if( !i_timer.Passed() )
return; return;
ObjectAccessor::Instance().UpdatePlayers(i_timer.GetCurrent());
for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter)
{ {
checkAndCorrectGridStatesArray(); // debugging code, should be deleted some day checkAndCorrectGridStatesArray(); // debugging code, should be deleted some day

View file

@ -245,32 +245,6 @@ ObjectAccessor::SaveAllPlayers()
itr->second->SaveToDB(); itr->second->SaveToDB();
} }
void
ObjectAccessor::_update()
{
UpdateDataMapType update_players;
{
Guard guard(i_updateGuard);
while(!i_objects.empty())
{
Object* obj = *i_objects.begin();
i_objects.erase(i_objects.begin());
if (!obj)
continue;
_buildUpdateObject(obj, update_players);
obj->ClearUpdateMask(false);
}
}
WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
for(UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
{
iter->second.BuildPacket(&packet);
iter->first->GetSession()->SendPacket(&packet);
packet.clear(); // clean the string
}
}
void void
ObjectAccessor::UpdateObject(Object* obj, Player* exceptPlayer) ObjectAccessor::UpdateObject(Object* obj, Player* exceptPlayer)
{ {
@ -505,72 +479,36 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid)
void void
ObjectAccessor::Update(uint32 diff) ObjectAccessor::Update(uint32 diff)
{ {
UpdateDataMapType update_players;
{ {
typedef std::multimap<uint32, Player *> CreatureLocationHolderType; Guard guard(i_updateGuard);
CreatureLocationHolderType creature_locations; while(!i_objects.empty())
//TODO: Player guard
HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer();
for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter)
{ {
if(iter->second->IsInWorld()) Object* obj = *i_objects.begin();
{ i_objects.erase(i_objects.begin());
iter->second->Update(diff); if (!obj)
creature_locations.insert( CreatureLocationHolderType::value_type(iter->second->GetMapId(), iter->second) );
}
}
Map *map;
MaNGOS::ObjectUpdater updater(diff);
// for creature
TypeContainerVisitor<MaNGOS::ObjectUpdater, GridTypeMapContainer > grid_object_update(updater);
// for pets
TypeContainerVisitor<MaNGOS::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater);
for(CreatureLocationHolderType::iterator iter=creature_locations.begin(); iter != creature_locations.end(); ++iter)
{
MapManager::Instance().GetMap((*iter).first, (*iter).second)->resetMarkedCells();
}
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(MaNGOS::ComputeCellPair(player->GetPositionX(), player->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)
continue; continue;
_buildUpdateObject(obj, update_players);
// the overloaded operators handle range checking obj->ClearUpdateMask(false);
// so ther's no need for range checking inside the loop
CellPair begin_cell(standing_cell), end_cell(standing_cell);
begin_cell << 1; begin_cell -= 1; // upper left
end_cell >> 1; end_cell += 1; // lower right
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++)
{
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++)
{
uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
if( !map->isCellMarked(cell_id) )
{
CellPair cell_pair(x,y);
map->markCell(cell_id);
Cell cell(cell_pair);
cell.data.Part.reserved = CENTER_DISTRICT;
cell.SetNoCreate();
CellLock<NullGuard> cell_lock(cell, cell_pair);
cell_lock->Visit(cell_lock, grid_object_update, *map);
cell_lock->Visit(cell_lock, world_object_update, *map);
}
}
}
} }
} }
_update(); WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
for(UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
{
iter->second.BuildPacket(&packet);
iter->first->GetSession()->SendPacket(&packet);
packet.clear(); // clean the string
}
}
void
ObjectAccessor::UpdatePlayers(uint32 diff)
{
HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer();
for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter)
if(iter->second->IsInWorld())
iter->second->Update(diff);
} }
bool bool

View file

@ -184,6 +184,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
void RemoveUpdateObject(Object *obj); void RemoveUpdateObject(Object *obj);
void Update(uint32 diff); void Update(uint32 diff);
void UpdatePlayers(uint32 diff);
Corpse* GetCorpseForPlayerGUID(uint64 guid); Corpse* GetCorpseForPlayerGUID(uint64 guid);
void RemoveCorpse(Corpse *corpse); void RemoveCorpse(Corpse *corpse);
@ -216,7 +217,6 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
static void _buildChangeObjectForPlayer(WorldObject *, UpdateDataMapType &); static void _buildChangeObjectForPlayer(WorldObject *, UpdateDataMapType &);
static void _buildPacket(Player *, Object *, UpdateDataMapType &); static void _buildPacket(Player *, Object *, UpdateDataMapType &);
void _update(void);
std::set<Object *> i_objects; std::set<Object *> i_objects;
LockType i_playerGuard; LockType i_playerGuard;
LockType i_updateGuard; LockType i_updateGuard;

118
src/game/PetitionMgr.h Normal file
View file

@ -0,0 +1,118 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _PETITIONMGR_H
#define _PETITIONMGR_H
#include "Policies/Singleton.h"
#include "Database/DatabaseEnv.h"
#include "Util.h"
#include <map>
class Petition
{
public:
explicit Petition()
{
}
GMTicket(uint32 guid, std::string text, time_t update) : m_guid(guid), m_text(text), m_lastUpdate(update)
{
}
const char* GetText() const
{
return m_text.c_str();
}
uint64 GetLastUpdate() const
{
return m_lastUpdate;
}
void SetText(const char* text)
{
m_text = text ? text : "";
m_lastUpdate = time(NULL);
CharacterDatabase.PExecute("UPDATE character_ticket SET ticket_text = '%s' WHERE guid = '%u'", m_text.c_str(), m_guid);
}
void DeleteFromDB() const
{
CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u' LIMIT 1", m_guid);
}
void SaveToDB() const
{
CharacterDatabase.BeginTransaction();
DeleteFromDB();
CharacterDatabase.PExecute("INSERT INTO character_ticket (guid, ticket_text) VALUES ('%u', '%s')", m_guid, GetText());
CharacterDatabase.CommitTransaction();
}
private:
uint32 m_guid;
std::string m_text;
time_t m_lastUpdate;
};
typedef std::map<uint32, Petition> PetitionMap;
class PetitionMgr
{
public:
PetitionMgr() { }
~PetitionMgr() { }
void LoadGMTickets();
GMTicket* GetGMTicket(uint32 guid)
{
GMTicketMap::iterator itr = m_GMTicketMap.find(guid);
if(itr == m_GMTicketMap.end())
return NULL;
return &(itr->second);
}
size_t GetTicketCount() const
{
return m_GMTicketMap.size();
}
void Delete(uint32 guid)
{
GMTicketMap::iterator itr = m_GMTicketMap.find(guid);
if(itr == m_GMTicketMap.end())
return;
itr->second.DeleteFromDB();
m_GMTicketMap.erase(itr);
}
void DeleteAll();
void Create(uint32 guid, const char* text)
{
GMTicket t = GMTicket(guid, text, time(NULL));
t.SaveToDB();
m_GMTicketMap[guid] = t;
}
private:
PetitionMap m_PetitionMap;
};
#define petitionmgr MaNGOS::Singleton<PetitionMgr>::Instance()
#endif