feat(Core/Maps): Improve map object updater (#22392)

This commit is contained in:
Takenbacon
2025-07-11 07:00:16 -07:00
committed by GitHub
parent 9d6c7ad7ea
commit 1c3cbd3d9e
16 changed files with 285 additions and 181 deletions

View File

@@ -2772,11 +2772,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
//Load Path
if (cainfo->path_id != 0)
{
if (sWorld->getBoolConfig(CONFIG_SET_ALL_CREATURES_WITH_WAYPOINT_MOVEMENT_ACTIVE))
setActive(true);
m_path_id = cainfo->path_id;
}
if (!cainfo->auras.empty())
{
@@ -3896,3 +3892,27 @@ std::string Creature::GetDebugInfo() const
<< " WaypointPath: " << GetWaypointPath() << " SpawnId: " << GetSpawnId();
return sstr.str();
}
// Note: This is called in a tight (heavy) loop, is it critical that all checks are FAST and are hopefully only simple conditionals.
bool Creature::IsUpdateNeeded()
{
if (WorldObject::IsUpdateNeeded())
return true;
if (GetMap()->isCellMarked(GetCurrentCell().GetCellCoord().GetId()))
return true;
if (IsInCombat())
return true;
if (IsVisibilityOverridden())
return true;
if (GetMotionMaster()->HasMovementGeneratorType(WAYPOINT_MOTION_TYPE))
return true;
if (HasUnitState(UNIT_STATE_EVADE))
return true;
return false;
}

View File

@@ -39,7 +39,7 @@ class CreatureGroup;
#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
class Creature : public Unit, public GridObject<Creature>, public MovableMapObject
class Creature : public Unit, public GridObject<Creature>, public MovableMapObject, public UpdatableMapObject
{
public:
explicit Creature(bool isWorldObject = false);
@@ -436,6 +436,8 @@ public:
std::string GetDebugInfo() const override;
bool IsUpdateNeeded() override;
protected:
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 Entry, uint32 vehId, const CreatureData* data = nullptr);
bool InitEntry(uint32 entry, const CreatureData* data = nullptr);

View File

@@ -31,7 +31,7 @@ enum DynamicObjectType
DYNAMIC_OBJECT_FARSIGHT_FOCUS = 0x2,
};
class DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MovableMapObject
class DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MovableMapObject, public UpdatableMapObject
{
public:
DynamicObject(bool isWorldObject);

View File

@@ -3076,3 +3076,21 @@ std::string GameObject::GetDebugInfo() const
<< "SpawnId: " << GetSpawnId() << " GoState: " << std::to_string(GetGoState()) << " ScriptId: " << GetScriptId() << " AIName: " << GetAIName();
return sstr.str();
}
// Note: This is called in a tight (heavy) loop, is it critical that all checks are FAST and are hopefully only simple conditionals.
bool GameObject::IsUpdateNeeded()
{
if (WorldObject::IsUpdateNeeded())
return true;
if (GetMap()->isCellMarked(GetCurrentCell().GetCellCoord().GetId()))
return true;
if (IsVisibilityOverridden())
return true;
if (IsTransport())
return true;
return false;
}

View File

@@ -116,7 +116,7 @@ enum LootState
// 5 sec for bobber catch
#define FISHING_BOBBER_READY_TIME 5
class GameObject : public WorldObject, public GridObject<GameObject>, public MovableMapObject
class GameObject : public WorldObject, public GridObject<GameObject>, public MovableMapObject, public UpdatableMapObject
{
public:
explicit GameObject();
@@ -362,6 +362,8 @@ public:
void SaveStateToDB();
std::string GetDebugInfo() const override;
bool IsUpdateNeeded() override;
protected:
bool AIM_Initialize();
GameObjectModel* CreateModel();

View File

@@ -1188,6 +1188,7 @@ void WorldObject::AddToWorld()
{
Object::AddToWorld();
GetMap()->GetZoneAndAreaId(GetPhaseMask(), _zoneId, _areaId, GetPositionX(), GetPositionY(), GetPositionZ());
GetMap()->AddObjectToPendingUpdateList(this);
}
void WorldObject::RemoveFromWorld()
@@ -3220,3 +3221,27 @@ void WorldObject::RemoveAllowedLooter(ObjectGuid guid)
{
_allowedLooters.erase(guid);
}
bool WorldObject::IsUpdateNeeded()
{
if (isActiveObject())
return true;
return false;
}
bool WorldObject::CanBeAddedToMapUpdateList()
{
switch (GetTypeId())
{
case TYPEID_UNIT:
return IsCreature();
case TYPEID_DYNAMICOBJECT:
case TYPEID_GAMEOBJECT:
return true;
default:
return false;
}
return false;
}

View File

@@ -405,14 +405,58 @@ class MovableMapObject
protected:
MovableMapObject() = default;
private:
[[nodiscard]] Cell const& GetCurrentCell() const { return _currentCell; }
private:
void SetCurrentCell(Cell const& cell) { _currentCell = cell; }
Cell _currentCell;
MapObjectCellMoveState _moveState{MAP_OBJECT_CELL_MOVE_NONE};
};
class UpdatableMapObject
{
friend class Map;
public:
enum UpdateState : uint8
{
NotUpdating,
PendingAdd,
Updating
};
protected:
UpdatableMapObject() : _mapUpdateListOffset(0), _mapUpdateState(NotUpdating) { }
private:
void SetMapUpdateListOffset(std::size_t const offset)
{
ASSERT(_mapUpdateState == Updating, "Attempted to set update list offset when object is not in map update list");
_mapUpdateListOffset = offset;
}
size_t GetMapUpdateListOffset() const
{
ASSERT(_mapUpdateState == Updating, "Attempted to get update list offset when object is not in map update list");
return _mapUpdateListOffset;
}
void SetUpdateState(UpdateState state)
{
_mapUpdateState = state;
}
UpdateState GetUpdateState() const
{
return _mapUpdateState;
}
private:
std::size_t _mapUpdateListOffset;
UpdateState _mapUpdateState;
};
class WorldObject : public Object, public WorldLocation
{
protected:
@@ -639,6 +683,9 @@ public:
[[nodiscard]] GuidUnorderedSet const& GetAllowedLooters() const;
void RemoveAllowedLooter(ObjectGuid guid);
virtual bool IsUpdateNeeded();
bool CanBeAddedToMapUpdateList();
std::string GetDebugInfo() const override;
// Event handler

View File

@@ -1683,6 +1683,8 @@ template <class T>
void Player::UpdateVisibilityOf(T* target, UpdateData& data,
std::vector<Unit*>& visibleNow)
{
GetMap()->AddObjectToPendingUpdateList(target);
if (HaveAtClient(target))
{
if (!CanSeeOrDetect(target, false, true))