Core/Objects: Unify WorldObjectSearcher classes into one common implementation

This commit is contained in:
Shauren
2023-05-28 16:07:34 +02:00
parent 3790c1e3da
commit 261eb201bf
3 changed files with 114 additions and 462 deletions

View File

@@ -33,6 +33,18 @@
namespace Trinity
{
template<typename ObjectType>
struct GridMapTypeMaskForType : std::integral_constant<GridMapTypeMask, GridMapTypeMask(0)> { };
template<> struct GridMapTypeMaskForType<Corpse> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_CORPSE> { };
template<> struct GridMapTypeMaskForType<Creature> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_CREATURE> { };
template<> struct GridMapTypeMaskForType<DynamicObject> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_DYNAMICOBJECT> { };
template<> struct GridMapTypeMaskForType<GameObject> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_GAMEOBJECT> { };
template<> struct GridMapTypeMaskForType<Player> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_PLAYER> { };
template<> struct GridMapTypeMaskForType<AreaTrigger> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_AREATRIGGER> { };
template<> struct GridMapTypeMaskForType<SceneObject> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_SCENEOBJECT> { };
template<> struct GridMapTypeMaskForType<Conversation> : std::integral_constant<GridMapTypeMask, GRID_MAP_TYPE_MASK_CONVERSATION> { };
struct TC_GAME_API VisibleNotifier
{
Player &i_player;
@@ -220,10 +232,53 @@ namespace Trinity
// SEARCHERS & LIST SEARCHERS & WORKERS
// WorldObject searchers & workers
enum class WorldObjectSearcherContinuation
{
Continue,
Return
};
template<typename Type>
class SearcherFirstObjectResult
{
Type& result;
protected:
explicit SearcherFirstObjectResult(Type& ref_) : result(ref_) { }
WorldObjectSearcherContinuation ShouldContinue() const
{
return result ? WorldObjectSearcherContinuation::Return : WorldObjectSearcherContinuation::Continue;
}
void Insert(Type object)
{
result = object;
}
};
template<typename Type>
class SearcherLastObjectResult
{
Type& result;
protected:
explicit SearcherLastObjectResult(Type& ref_) : result(ref_) { }
WorldObjectSearcherContinuation ShouldContinue() const
{
return WorldObjectSearcherContinuation::Continue;
}
void Insert(Type object)
{
result = object;
}
};
// Generic base class to insert elements into arbitrary containers using push_back
template<typename Type>
class ContainerInserter
class SearcherContainerResult
{
using InserterType = void(*)(void*, Type&&);
@@ -232,7 +287,7 @@ namespace Trinity
protected:
template<typename T>
ContainerInserter(T& ref_) : ref(&ref_)
explicit SearcherContainerResult(T& ref_) : ref(&ref_)
{
inserter = [](void* containerRaw, Type&& object)
{
@@ -241,80 +296,52 @@ namespace Trinity
};
}
WorldObjectSearcherContinuation ShouldContinue() const
{
return WorldObjectSearcherContinuation::Continue;
}
void Insert(Type object)
{
inserter(ref, std::move(object));
}
};
template<class Check>
struct WorldObjectSearcher
template<class Check, class Result>
struct WorldObjectSearcherBase : Result
{
uint32 i_mapTypeMask;
PhaseShift const* i_phaseShift;
WorldObject* &i_object;
Check &i_check;
WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: i_mapTypeMask(mapTypeMask), i_phaseShift(&searcher->GetPhaseShift()), i_object(result), i_check(check) { }
void Visit(GameObjectMapType &m);
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
void Visit(AreaTriggerMapType &m);
void Visit(SceneObjectMapType &m);
void Visit(ConversationMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
};
template<class Check>
struct WorldObjectLastSearcher
{
uint32 i_mapTypeMask;
PhaseShift const* i_phaseShift;
WorldObject* &i_object;
Check &i_check;
WorldObjectLastSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: i_mapTypeMask(mapTypeMask), i_phaseShift(&searcher->GetPhaseShift()), i_object(result), i_check(check) { }
void Visit(GameObjectMapType &m);
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
void Visit(AreaTriggerMapType &m);
void Visit(SceneObjectMapType &m);
void Visit(ConversationMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
};
template<class Check>
struct WorldObjectListSearcher : ContainerInserter<WorldObject*>
{
uint32 i_mapTypeMask;
PhaseShift const* i_phaseShift;
Check& i_check;
template<typename Container>
WorldObjectSearcherBase(WorldObject const* searcher, Container& result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: Result(result), i_mapTypeMask(mapTypeMask), i_phaseShift(&searcher->GetPhaseShift()), i_check(check) { }
template<class T>
void Visit(GridRefManager<T>&);
};
template<class Check>
struct WorldObjectSearcher : WorldObjectSearcherBase<Check, SearcherFirstObjectResult<WorldObject*>>
{
WorldObjectSearcher(WorldObject const* searcher, WorldObject*& result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: WorldObjectSearcherBase<Check, SearcherFirstObjectResult<WorldObject*>>(searcher, result, check, mapTypeMask) { }
};
template<class Check>
struct WorldObjectLastSearcher : WorldObjectSearcherBase<Check, SearcherLastObjectResult<WorldObject*>>
{
WorldObjectLastSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: WorldObjectSearcherBase<Check, SearcherLastObjectResult<WorldObject*>>(searcher, result, check, mapTypeMask) { }
};
template<class Check>
struct WorldObjectListSearcher : WorldObjectSearcherBase<Check, SearcherContainerResult<WorldObject*>>
{
template<typename Container>
WorldObjectListSearcher(WorldObject const* searcher, Container& container, Check & check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: ContainerInserter<WorldObject*>(container),
i_mapTypeMask(mapTypeMask), i_phaseShift(&searcher->GetPhaseShift()), i_check(check) { }
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(GameObjectMapType &m);
void Visit(DynamicObjectMapType &m);
void Visit(AreaTriggerMapType &m);
void Visit(SceneObjectMapType &m);
void Visit(ConversationMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
: WorldObjectSearcherBase<Check, SearcherContainerResult<WorldObject*>>(searcher, container, check, mapTypeMask) { }
};
template<class Do>
@@ -435,14 +462,14 @@ namespace Trinity
};
template<class Check>
struct GameObjectListSearcher : ContainerInserter<GameObject*>
struct GameObjectListSearcher : SearcherContainerResult<GameObject*>
{
PhaseShift const* i_phaseShift;
Check& i_check;
template<typename Container>
GameObjectListSearcher(WorldObject const* searcher, Container& container, Check & check)
: ContainerInserter<GameObject*>(container),
: SearcherContainerResult<GameObject*>(container),
i_phaseShift(&searcher->GetPhaseShift()), i_check(check) { }
void Visit(GameObjectMapType &m);
@@ -508,14 +535,14 @@ namespace Trinity
// All accepted by Check units if any
template<class Check>
struct UnitListSearcher : ContainerInserter<Unit*>
struct UnitListSearcher : SearcherContainerResult<Unit*>
{
PhaseShift const* i_phaseShift;
Check& i_check;
template<typename Container>
UnitListSearcher(WorldObject const* searcher, Container& container, Check& check)
: ContainerInserter<Unit*>(container),
: SearcherContainerResult<Unit*>(container),
i_phaseShift(&searcher->GetPhaseShift()), i_check(check) { }
void Visit(PlayerMapType &m);
@@ -558,14 +585,14 @@ namespace Trinity
};
template<class Check>
struct CreatureListSearcher : ContainerInserter<Creature*>
struct CreatureListSearcher : SearcherContainerResult<Creature*>
{
PhaseShift const* i_phaseShift;
Check& i_check;
template<typename Container>
CreatureListSearcher(WorldObject const* searcher, Container& container, Check & check)
: ContainerInserter<Creature*>(container),
: SearcherContainerResult<Creature*>(container),
i_phaseShift(&searcher->GetPhaseShift()), i_check(check) { }
void Visit(CreatureMapType &m);
@@ -610,19 +637,19 @@ namespace Trinity
};
template<class Check>
struct PlayerListSearcher : ContainerInserter<Player*>
struct PlayerListSearcher : SearcherContainerResult<Player*>
{
PhaseShift const* i_phaseShift;
Check& i_check;
template<typename Container>
PlayerListSearcher(WorldObject const* searcher, Container& container, Check & check)
: ContainerInserter<Player*>(container),
: SearcherContainerResult<Player*>(container),
i_phaseShift(&searcher->GetPhaseShift()), i_check(check) { }
template<typename Container>
PlayerListSearcher(PhaseShift const& phaseShift, Container& container, Check & check)
: ContainerInserter<Player*>(container),
: SearcherContainerResult<Player*>(container),
i_phaseShift(&phaseShift), i_check(check) { }
void Visit(PlayerMapType &m);

View File

@@ -180,406 +180,28 @@ void Trinity::MessageDistDelivererToHostile<PacketSender>::Visit(DynamicObjectMa
// WorldObject searchers & workers
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
template <class Check, class Result>
template <class T>
void Trinity::WorldObjectSearcherBase<Check, Result>::Visit(GridRefManager<T>& m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
if (!(i_mapTypeMask & GridMapTypeMaskForType<T>::value))
return;
// already found
if (i_object)
if (this->ShouldContinue() == WorldObjectSearcherContinuation::Return)
return;
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
for (auto itr = m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
this->Insert(itr->GetSource());
if (this->ShouldContinue() == WorldObjectSearcherContinuation::Return)
return;
}
}
}
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
return;
// already found
if (i_object)
return;
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
}
}
}
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
return;
// already found
if (i_object)
return;
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
}
}
}
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
return;
// already found
if (i_object)
return;
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
}
}
}
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
return;
// already found
if (i_object)
return;
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
}
}
}
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(AreaTriggerMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
return;
// already found
if (i_object)
return;
for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
}
}
}
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(SceneObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_SCENEOBJECT))
return;
// already found
if (i_object)
return;
for (SceneObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
}
}
}
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(ConversationMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CONVERSATION))
return;
// already found
if (i_object)
return;
for (ConversationMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
{
i_object = itr->GetSource();
return;
}
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
return;
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(PlayerMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
return;
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(CreatureMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
return;
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(CorpseMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
return;
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(DynamicObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
return;
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(AreaTriggerMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
return;
for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(SceneObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_SCENEOBJECT))
return;
for (SceneObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(ConversationMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CONVERSATION))
return;
for (ConversationMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
if (!itr->GetSource()->InSamePhase(*i_phaseShift))
continue;
if (i_check(itr->GetSource()))
i_object = itr->GetSource();
}
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
return;
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
return;
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
return;
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
return;
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
return;
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(AreaTriggerMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
return;
for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(SceneObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_SCENEOBJECT))
return;
for (SceneObjectMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(ConversationMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CONVERSATION))
return;
for (ConversationMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (i_check(itr->GetSource()))
Insert(itr->GetSource());
}
// Gameobject searchers
template<class Check>

View File

@@ -2146,9 +2146,11 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objec
uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
if (!containerTypeMask)
return nullptr;
Trinity::WorldObjectSpellNearbyTargetCheck check(range, m_caster, m_spellInfo, selectionType, condList, objectType);
Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> searcher(m_caster, target, check, containerTypeMask);
SearchTargets<Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range);
searcher.i_phaseShift = &PhasingHandler::GetAlwaysVisiblePhaseShift();
SearchTargets<Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck>>(searcher, containerTypeMask, m_caster, m_caster, range);
return target;
}
@@ -2161,7 +2163,8 @@ void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Pos
float extraSearchRadius = range > 0.0f ? EXTRA_CELL_SEARCH_RADIUS : 0.0f;
Trinity::WorldObjectSpellAreaTargetCheck check(range, position, m_caster, referer, m_spellInfo, selectionType, condList, objectType);
Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(m_caster, targets, check, containerTypeMask);
SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> > (searcher, containerTypeMask, m_caster, position, range + extraSearchRadius);
searcher.i_phaseShift = &PhasingHandler::GetAlwaysVisiblePhaseShift();
SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck>>(searcher, containerTypeMask, m_caster, position, range + extraSearchRadius);
}
void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, SpellEffectInfo const& spellEffectInfo, bool isChainHeal)