Fix the crash when removing object from an unloaded grid. Object should always be unlinked from grid no matter if the grid is loaded.

This commit is contained in:
megamage
2011-11-10 17:31:45 -05:00
parent 23b3f16f3a
commit 31a88d4fe5
6 changed files with 51 additions and 95 deletions

View File

@@ -527,9 +527,11 @@ template<class T>
class GridObject
{
public:
GridReference<T> &GetGridRef() { return m_gridRef; }
protected:
GridReference<T> m_gridRef;
bool IsInGrid() const { return _gridRef.isValid(); }
void AddToGrid(GridRefManager<T>& m) { ASSERT(!IsInGrid()); _gridRef.link(&m, (T*)this); }
void RemoveFromGrid() { ASSERT(IsInGrid()); _gridRef.unlink(); }
private:
GridReference<T> _gridRef;
};
template <class T_VALUES, class T_FLAGS, class FLAG_TYPE, uint8 ARRAY_SIZE>

View File

@@ -58,20 +58,19 @@ class Grid
*/
template<class SPECIFIC_OBJECT> void AddWorldObject(SPECIFIC_OBJECT *obj)
{
ASSERT(!obj->GetGridRef().isValid());
i_objects.template insert<SPECIFIC_OBJECT>(obj);
ASSERT(obj->GetGridRef().isValid());
ASSERT(obj->IsInGrid());
}
/** an object of interested exits the grid
*/
//Actually an unlink is enough, no need to go through the container
template<class SPECIFIC_OBJECT> void RemoveWorldObject(SPECIFIC_OBJECT *obj)
{
ASSERT(obj->GetGridRef().isValid());
i_objects.template remove<SPECIFIC_OBJECT>(obj);
ASSERT(!obj->GetGridRef().isValid());
}
//template<class SPECIFIC_OBJECT> void RemoveWorldObject(SPECIFIC_OBJECT *obj)
//{
// ASSERT(obj->GetGridRef().isValid());
// i_objects.template remove<SPECIFIC_OBJECT>(obj);
// ASSERT(!obj->GetGridRef().isValid());
//}
/** Refreshes/update the grid. This required for remote grids.
*/
@@ -107,19 +106,18 @@ class Grid
*/
template<class SPECIFIC_OBJECT> void AddGridObject(SPECIFIC_OBJECT *obj)
{
ASSERT(!obj->GetGridRef().isValid());
i_container.template insert<SPECIFIC_OBJECT>(obj);
ASSERT(obj->GetGridRef().isValid());
ASSERT(obj->IsInGrid());
}
/** Removes a containter type object from the grid
*/
template<class SPECIFIC_OBJECT> void RemoveGridObject(SPECIFIC_OBJECT *obj)
{
ASSERT(obj->GetGridRef().isValid());
i_container.template remove<SPECIFIC_OBJECT>(obj);
ASSERT(!obj->GetGridRef().isValid());
}
//template<class SPECIFIC_OBJECT> void RemoveGridObject(SPECIFIC_OBJECT *obj)
//{
// ASSERT(obj->GetGridRef().isValid());
// i_container.template remove<SPECIFIC_OBJECT>(obj);
// ASSERT(!obj->GetGridRef().isValid());
//}
/*bool NoWorldObjectInGrid() const
{

View File

@@ -77,7 +77,7 @@ template<> void ObjectGridLoader::SetObjectCell(Creature* obj, CellCoord const&
template <class T>
void AddObjectHelper(CellCoord &cell, GridRefManager<T> &m, uint32 &count, Map* map, T *obj)
{
obj->GetGridRef().link(&m, obj);
obj->AddToGrid(m);
ObjectGridLoader::SetObjectCell(obj, cell);
obj->AddToWorld();
if (obj->isActiveObject())

View File

@@ -255,17 +255,6 @@ void Map::AddToGrid(Creature* obj, Cell const& cell)
obj->SetCurrentCell(cell);
}
//TODO: cell is not needed. Just an unlink is enough.
template<class T>
void Map::RemoveFromGrid(T* obj, Cell const& cell)
{
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
if (obj->m_isWorldObject)
grid->GetGridType(cell.CellX(), cell.CellY()).template RemoveWorldObject<T>(obj);
else
grid->GetGridType(cell.CellX(), cell.CellY()).template RemoveGridObject<T>(obj);
}
template<class T>
void Map::SwitchGridContainers(T* obj, bool on)
{
@@ -286,16 +275,11 @@ void Map::SwitchGridContainers(T* obj, bool on)
GridType &grid = ngrid->GetGridType(cell.CellX(), cell.CellY());
obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
if (on)
{
grid.RemoveGridObject<T>(obj); //not really necessary if there were no ASSERT in remove/add
grid.AddWorldObject<T>(obj);
}
else
{
grid.RemoveWorldObject<T>(obj); //not really necessary if there were no ASSERT in remove/add
grid.AddGridObject<T>(obj);
}
obj->m_isWorldObject = on;
}
@@ -662,21 +646,8 @@ void Map::RemoveFromMap(Player* player, bool remove)
player->RemoveFromWorld();
SendRemoveTransports(player);
CellCoord p = Trinity::ComputeCellCoord(player->GetPositionX(), player->GetPositionY());
if (!p.IsCoordValid())
sLog->outCrash("Map::Remove: Player is in invalid cell!");
else
{
Cell cell(p);
if (!getNGrid(cell.data.Part.grid_x, cell.data.Part.grid_y))
sLog->outError("Map::Remove() i_grids was NULL x:%d, y:%d", cell.data.Part.grid_x, cell.data.Part.grid_y);
else
{
sLog->outStaticDebug("Remove player %s from grid[%u, %u]", player->GetName(), cell.GridX(), cell.GridY());
player->UpdateObjectVisibility(true);
RemoveFromGrid(player, cell);
}
}
player->UpdateObjectVisibility(true);
player->RemoveFromGrid();
if (remove)
DeleteFromWorld(player);
@@ -692,19 +663,8 @@ Map::RemoveFromMap(T *obj, bool remove)
if (obj->isActiveObject())
RemoveFromActive(obj);
CellCoord p = Trinity::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
if (!p.IsCoordValid())
sLog->outError("Map::Remove: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
else
{
Cell cell(p);
if (IsGridLoaded(GridCoord(cell.data.Part.grid_x, cell.data.Part.grid_y)))
{
sLog->outStaticDebug("Remove object " UI64FMTD " from grid[%u, %u]", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y);
obj->UpdateObjectVisibility(true);
RemoveFromGrid(obj, cell);
}
}
obj->UpdateObjectVisibility(true);
obj->RemoveFromGrid();
obj->ResetMap();
@@ -731,7 +691,7 @@ Map::PlayerRelocation(Player* player, float x, float y, float z, float orientati
{
sLog->outStaticDebug("Player %s relocation grid[%u, %u]cell[%u, %u]->grid[%u, %u]cell[%u, %u]", player->GetName(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
RemoveFromGrid(player, old_cell);
player->RemoveFromGrid();
if (old_cell.DiffGrid(new_cell))
EnsureGridLoadedForActiveObject(new_cell, player);
@@ -857,7 +817,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
sLog->outDebug(LOG_FILTER_MAPS, "Creature (GUID: %u Entry: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
#endif
RemoveFromGrid(c, old_cell);
c->RemoveFromGrid();
AddToGrid(c, new_cell);
}
else
@@ -879,7 +839,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
sLog->outDebug(LOG_FILTER_MAPS, "Active creature (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
#endif
RemoveFromGrid(c, old_cell);
c->RemoveFromGrid();
AddToGrid(c, new_cell);
return true;
@@ -892,7 +852,7 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
sLog->outDebug(LOG_FILTER_MAPS, "Creature (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
#endif
RemoveFromGrid(c, old_cell);
c->RemoveFromGrid();
EnsureGridCreated(GridCoord(new_cell.GridX(), new_cell.GridY()));
AddToGrid(c, new_cell);

View File

@@ -525,9 +525,6 @@ class Map : public GridRefManager<NGridType>
template<class T>
void AddToGrid(T* object, Cell const& cell);
template<class T>
void RemoveFromGrid(T* object, Cell const& cell);
template<class T>
void DeleteFromWorld(T*);

View File

@@ -62,7 +62,7 @@ namespace Trinity
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE> &elements, SPECIFIC_TYPE *obj)
{
//elements._element[hdl] = obj;
obj->GetGridRef().link(&elements._element, obj);
obj->AddToGrid(elements._element);
return obj;
};
@@ -84,31 +84,30 @@ namespace Trinity
return (t != NULL ? t : Insert(elements._TailElements, obj));
}
// non-const remove method
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Remove(ContainerMapList<SPECIFIC_TYPE> & /*elements*/, SPECIFIC_TYPE *obj)
{
obj->GetGridRef().unlink();
return obj;
}
//// non-const remove method
//template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Remove(ContainerMapList<SPECIFIC_TYPE> & /*elements*/, SPECIFIC_TYPE *obj)
//{
// obj->GetGridRef().unlink();
// return obj;
//}
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Remove(ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE * /*obj*/)
{
return NULL;
}
//template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Remove(ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE * /*obj*/)
//{
// return NULL;
//}
// this is a missed
template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Remove(ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE * /*obj*/)
{
return NULL; // a missed
}
template<class SPECIFIC_TYPE, class T, class H> SPECIFIC_TYPE* Remove(ContainerMapList<TypeList<H, T> > &elements, SPECIFIC_TYPE *obj)
{
// The head element is bad
SPECIFIC_TYPE* t = Remove(elements._elements, obj);
return ( t != NULL ? t : Remove(elements._TailElements, obj) );
}
//// this is a missed
//template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Remove(ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE * /*obj*/)
//{
// return NULL; // a missed
//}
//template<class SPECIFIC_TYPE, class T, class H> SPECIFIC_TYPE* Remove(ContainerMapList<TypeList<H, T> > &elements, SPECIFIC_TYPE *obj)
//{
// // The head element is bad
// SPECIFIC_TYPE* t = Remove(elements._elements, obj);
// return ( t != NULL ? t : Remove(elements._TailElements, obj) );
//}
}
#endif