mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[11193] Optimize visibility update and AI notification code. Optimization decreases amount of visibility and AI notification operations in 8-10 times, and as a result, lowers CPU usage by 30-40%
You need to update your config file, new "Visibility.RelocationLowerLimit" and "Visibility.AIRelocationNotifyDelay' options added Special thanks to Ambal for code hints and advices Thanks to Undergarun and kero99 for making tests
This commit is contained in:
parent
60b2e2c8ba
commit
724092d9e5
10 changed files with 117 additions and 62 deletions
|
|
@ -125,7 +125,7 @@ m_lootMoney(0), m_lootGroupRecipientId(0),
|
|||
m_corpseDecayTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(5.0f),
|
||||
m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
|
||||
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
|
||||
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_needNotify(false),
|
||||
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
|
||||
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
|
||||
m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)
|
||||
{
|
||||
|
|
@ -426,15 +426,6 @@ uint32 Creature::ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData *
|
|||
|
||||
void Creature::Update(uint32 update_diff, uint32 diff)
|
||||
{
|
||||
if (m_needNotify)
|
||||
{
|
||||
m_needNotify = false;
|
||||
RelocationNotify();
|
||||
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
}
|
||||
|
||||
switch( m_deathState )
|
||||
{
|
||||
case JUST_ALIVED:
|
||||
|
|
@ -2352,13 +2343,6 @@ void Creature::SendAreaSpiritHealerQueryOpcode(Player *pl)
|
|||
pl->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
void Creature::RelocationNotify()
|
||||
{
|
||||
MaNGOS::CreatureRelocationNotifier relocationNotifier(*this);
|
||||
float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
|
||||
Cell::VisitAllObjects(this, relocationNotifier, radius);
|
||||
}
|
||||
|
||||
void Creature::ApplyGameEventSpells(GameEventCreatureData const* eventData, bool activated)
|
||||
{
|
||||
uint32 cast_spell = activated ? eventData->spell_id_start : eventData->spell_id_end;
|
||||
|
|
|
|||
|
|
@ -647,14 +647,11 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
|
||||
void SetActiveObjectState(bool on);
|
||||
|
||||
void SetNeedNotify() { m_needNotify = true; }
|
||||
|
||||
void SendAreaSpiritHealerQueryOpcode(Player *pl);
|
||||
|
||||
protected:
|
||||
bool CreateFromProto(uint32 guidlow,uint32 Entry, Team team, const CreatureData *data = NULL, GameEventCreatureData const* eventData =NULL);
|
||||
bool InitEntry(uint32 entry, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL);
|
||||
void RelocationNotify();
|
||||
|
||||
uint32 m_groupLootTimer; // (msecs)timer used for group loot
|
||||
uint32 m_groupLootId; // used to find group which is looting corpse
|
||||
|
|
@ -691,7 +688,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
bool m_regenHealth;
|
||||
bool m_AI_locked;
|
||||
bool m_isDeadByDefault;
|
||||
bool m_needNotify;
|
||||
|
||||
SpellSchoolMask m_meleeDamageSchoolMask;
|
||||
uint32 m_originalEntry;
|
||||
|
|
|
|||
|
|
@ -47,11 +47,8 @@ inline void MaNGOS::ObjectUpdater::Visit(CreatureMapType &m)
|
|||
}
|
||||
}
|
||||
|
||||
inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPoint, Creature* c)
|
||||
inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c)
|
||||
{
|
||||
// update creature visibility at player/creature move
|
||||
pl->UpdateVisibilityOf(viewPoint,c);
|
||||
|
||||
// Creature AI reaction
|
||||
if (!c->hasUnitState(UNIT_STAT_LOST_CONTROL))
|
||||
{
|
||||
|
|
@ -80,11 +77,12 @@ inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
|
|||
if (!i_player.isAlive() || i_player.IsTaxiFlying())
|
||||
return;
|
||||
|
||||
WorldObject const* viewPoint = i_player.GetCamera().GetBody();
|
||||
|
||||
for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
|
||||
if (iter->getSource()->isAlive())
|
||||
PlayerCreatureRelocationWorker(&i_player, viewPoint, iter->getSource());
|
||||
{
|
||||
Creature* c = iter->getSource();
|
||||
if (c->isAlive())
|
||||
PlayerCreatureRelocationWorker(&i_player, c);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
@ -94,9 +92,11 @@ inline void MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m)
|
|||
return;
|
||||
|
||||
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
|
||||
if (Player* player = iter->getSource())
|
||||
{
|
||||
Player* player = iter->getSource();
|
||||
if (player->isAlive() && !player->IsTaxiFlying())
|
||||
PlayerCreatureRelocationWorker(player, player->GetCamera().GetBody(), &i_creature);
|
||||
PlayerCreatureRelocationWorker(player, &i_creature);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
|
|||
|
|
@ -207,13 +207,13 @@ void Map::AddNotifier(T* , Cell const& , CellPair const& )
|
|||
template<>
|
||||
void Map::AddNotifier(Player* obj, Cell const& cell, CellPair const& cellpair)
|
||||
{
|
||||
PlayerRelocationNotify(obj,cell,cellpair);
|
||||
obj->SheduleAINotify(0);
|
||||
}
|
||||
|
||||
template<>
|
||||
void Map::AddNotifier(Creature* obj, Cell const&, CellPair const&)
|
||||
{
|
||||
obj->SetNeedNotify();
|
||||
obj->SheduleAINotify(0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -708,10 +708,7 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati
|
|||
player->GetViewPoint().Event_GridChanged(&(*newGrid)(new_cell.CellX(),new_cell.CellY()));
|
||||
}
|
||||
|
||||
player->GetViewPoint().Call_UpdateVisibilityForOwner();
|
||||
// if move then update what player see and who seen
|
||||
UpdateObjectVisibility(player, new_cell, new_val);
|
||||
PlayerRelocationNotify(player,new_cell,new_val);
|
||||
player->OnRelocated();
|
||||
|
||||
NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY());
|
||||
if( !same_cell && newGrid->GetGridState()!= GRID_STATE_ACTIVE )
|
||||
|
|
@ -731,7 +728,6 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang
|
|||
CellPair new_val = MaNGOS::ComputeCellPair(x, y);
|
||||
Cell new_cell(new_val);
|
||||
|
||||
// delay creature move for grid/cell to grid/cell moves
|
||||
if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
|
||||
{
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u) added to moving list from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", creature->GetGUIDLow(), creature->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());
|
||||
|
|
@ -741,29 +737,22 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang
|
|||
{
|
||||
// update pos
|
||||
creature->Relocate(x, y, z, ang);
|
||||
|
||||
// in diffcell/diffgrid case notifiers called in Creature::Update
|
||||
creature->SetNeedNotify();
|
||||
creature->OnRelocated();
|
||||
}
|
||||
else
|
||||
{
|
||||
// if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid
|
||||
// creature coordinates will be updated and notifiers send
|
||||
if(!CreatureRespawnRelocation(creature))
|
||||
else if (!CreatureRespawnRelocation(creature))
|
||||
{
|
||||
// ... or unload (if respawn grid also not loaded)
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u ) can't be move to unloaded respawn grid.",creature->GetGUIDLow(),creature->GetEntry());
|
||||
creature->SetNeedNotify();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
creature->Relocate(x, y, z, ang);
|
||||
creature->SetNeedNotify();
|
||||
creature->OnRelocated();
|
||||
}
|
||||
|
||||
creature->GetViewPoint().Call_UpdateVisibilityForOwner();
|
||||
MANGOS_ASSERT(CheckGridIntegrity(creature,true));
|
||||
}
|
||||
|
||||
|
|
@ -847,7 +836,7 @@ bool Map::CreatureRespawnRelocation(Creature *c)
|
|||
{
|
||||
c->Relocate(resp_x, resp_y, resp_z, resp_o);
|
||||
c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators
|
||||
c->SetNeedNotify();
|
||||
c->OnRelocated();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ Unit::Unit()
|
|||
m_AuraFlags = 0;
|
||||
|
||||
m_Visibility = VISIBILITY_ON;
|
||||
m_AINotifySheduled = false;
|
||||
|
||||
m_detectInvisibilityMask = 0;
|
||||
m_invisibilityMask = 0;
|
||||
|
|
@ -8089,12 +8090,9 @@ void Unit::SetVisibility(UnitVisibility x)
|
|||
}
|
||||
}
|
||||
|
||||
Map *m = GetMap();
|
||||
|
||||
if(GetTypeId()==TYPEID_PLAYER)
|
||||
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
|
||||
else
|
||||
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
|
||||
GetViewPoint().Call_UpdateVisibilityForOwner();
|
||||
UpdateObjectVisibility();
|
||||
SheduleAINotify(0);
|
||||
|
||||
GetViewPoint().Event_ViewPointVisibilityChanged();
|
||||
}
|
||||
|
|
@ -10827,3 +10825,62 @@ bool Unit::IsAllowedDamageInArea(Unit* pVictim) const
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
class RelocationNotifyEvent : public BasicEvent
|
||||
{
|
||||
public:
|
||||
RelocationNotifyEvent(Unit& owner) : BasicEvent(), m_owner(owner)
|
||||
{
|
||||
m_owner._SetAINotifySheduled(true);
|
||||
}
|
||||
|
||||
bool Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
{
|
||||
float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
|
||||
if (m_owner.GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
MaNGOS::PlayerRelocationNotifier notify((Player&)m_owner);
|
||||
Cell::VisitAllObjects(&m_owner,notify,radius);
|
||||
}
|
||||
else //if(m_owner.GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
MaNGOS::CreatureRelocationNotifier notify((Creature&)m_owner);
|
||||
Cell::VisitAllObjects(&m_owner,notify,radius);
|
||||
}
|
||||
m_owner._SetAINotifySheduled(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Abort(uint64)
|
||||
{
|
||||
m_owner._SetAINotifySheduled(false);
|
||||
}
|
||||
|
||||
private:
|
||||
Unit& m_owner;
|
||||
};
|
||||
|
||||
void Unit::SheduleAINotify(uint32 delay)
|
||||
{
|
||||
if (!IsAINotifySheduled())
|
||||
m_Events.AddEvent(new RelocationNotifyEvent(*this), m_Events.CalculateTime(delay));
|
||||
}
|
||||
|
||||
void Unit::OnRelocated()
|
||||
{
|
||||
// switch to use G3D::Vector3 is good idea, maybe
|
||||
float dx = m_last_notified_position.x - GetPositionX();
|
||||
float dy = m_last_notified_position.y - GetPositionY();
|
||||
float dz = m_last_notified_position.z - GetPositionZ();
|
||||
float distsq = dx*dx+dy*dy+dz*dz;
|
||||
if (distsq > World::GetRelocationLowerLimitSq())
|
||||
{
|
||||
m_last_notified_position.x = GetPositionX();
|
||||
m_last_notified_position.y = GetPositionY();
|
||||
m_last_notified_position.z = GetPositionZ();
|
||||
|
||||
GetViewPoint().Call_UpdateVisibilityForOwner();
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
SheduleAINotify(World::GetRelocationAINotifyDelay());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1954,6 +1954,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
// Movement info
|
||||
MovementInfo m_movementInfo;
|
||||
|
||||
void SheduleAINotify(uint32 delay);
|
||||
bool IsAINotifySheduled() const { return m_AINotifySheduled;}
|
||||
void _SetAINotifySheduled(bool on) { m_AINotifySheduled = on;} // only for call from RelocationNotifyEvent class code
|
||||
void OnRelocated();
|
||||
|
||||
protected:
|
||||
explicit Unit ();
|
||||
|
||||
|
|
@ -2020,6 +2025,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
uint32 m_castCounter; // count casts chain of triggered spells for prevent infinity cast crashes
|
||||
|
||||
UnitVisibility m_Visibility;
|
||||
Position m_last_notified_position;
|
||||
bool m_AINotifySheduled;
|
||||
|
||||
Diminishing m_Diminishing;
|
||||
// Manage all Units threatening us
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
|
|||
float World::m_VisibleUnitGreyDistance = 0;
|
||||
float World::m_VisibleObjectGreyDistance = 0;
|
||||
|
||||
float World::m_relocation_lower_limit_sq = 10.f * 10.f;
|
||||
uint32 World::m_relocation_ai_notify_delay = 1000u;
|
||||
|
||||
/// World constructor
|
||||
World::World()
|
||||
{
|
||||
|
|
@ -768,6 +771,9 @@ void World::LoadConfigSettings(bool reload)
|
|||
|
||||
setConfig(CONFIG_BOOL_PET_UNSUMMON_AT_MOUNT, "PetUnsummonAtMount", true);
|
||||
|
||||
m_relocation_ai_notify_delay = sConfig.GetIntDefault("Visibility.AIRelocationNotifyDelay", 1000u);
|
||||
m_relocation_lower_limit_sq = pow(sConfig.GetFloatDefault("Visibility.RelocationLowerLimit",10), 2);
|
||||
|
||||
m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1);
|
||||
if(m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -565,6 +565,9 @@ class World
|
|||
static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; }
|
||||
static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; }
|
||||
|
||||
static float GetRelocationLowerLimitSq() { return m_relocation_lower_limit_sq; }
|
||||
static uint32 GetRelocationAINotifyDelay() { return m_relocation_ai_notify_delay; }
|
||||
|
||||
void ProcessCliCommands();
|
||||
void QueueCliCommand(CliCommandHolder* commandHolder) { cliCmdQueue.add(commandHolder); }
|
||||
|
||||
|
|
@ -654,6 +657,9 @@ class World
|
|||
static float m_VisibleUnitGreyDistance;
|
||||
static float m_VisibleObjectGreyDistance;
|
||||
|
||||
static float m_relocation_lower_limit_sq;
|
||||
static uint32 m_relocation_ai_notify_delay;
|
||||
|
||||
// CLI command holder to be thread safe
|
||||
ACE_Based::LockedQueue<CliCommandHolder*,ACE_Thread_Mutex> cliCmdQueue;
|
||||
|
||||
|
|
|
|||
|
|
@ -1138,6 +1138,14 @@ GM.AllowAchievementGain = 1
|
|||
# Visibility grey distance for dynobjects/gameobjects/corpses/creature bodies
|
||||
# Default: 10 (yards)
|
||||
#
|
||||
# Visibility.RelocationLowerLimit
|
||||
# Object's visibility update called, when distance between current object's position and position,
|
||||
# where visiblity was updated last time, reaches RelocationLoverLimit value
|
||||
# Default: 10 (yards)
|
||||
#
|
||||
# Visibility.AIRelocationNotifyDelay
|
||||
# Delay time between creature AI reactions on nearby movements
|
||||
# Default: 1000 (milliseconds)
|
||||
#
|
||||
###################################################################################################################
|
||||
|
||||
|
|
@ -1148,6 +1156,8 @@ Visibility.Distance.BGArenas = 180
|
|||
Visibility.Distance.InFlight = 100
|
||||
Visibility.Distance.Grey.Unit = 1
|
||||
Visibility.Distance.Grey.Object = 10
|
||||
Visibility.RelocationLowerLimit = 10
|
||||
Visibility.AIRelocationNotifyDelay = 1000
|
||||
|
||||
###################################################################################################################
|
||||
# SERVER RATES
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "11192"
|
||||
#define REVISION_NR "11193"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue