/* * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it * and/or modify it under version 3 of the License, or (at your option), any later version. */ #ifndef _PLAYERBOT_NAMEDOBJECTCONEXT_H #define _PLAYERBOT_NAMEDOBJECTCONEXT_H #include #include #include #include #include #include #include "Common.h" class PlayerbotAI; class Qualified { public: Qualified(){}; Qualified(std::string const qualifier) : qualifier(qualifier) {} Qualified(int32 qualifier1) { Qualify(qualifier1); } virtual void Qualify(int qual); virtual void Qualify(std::string const qual) { qualifier = qual; } std::string const getQualifier() { return qualifier; } static std::string const MultiQualify(const std::vector& qualifiers, const std::string& separator, const std::string_view brackets = "{}"); static std::vector getMultiQualifiers(const std::string& qualifier1); static int32 getMultiQualifier(const std::string& qualifier1, uint32 pos); protected: std::string qualifier; }; template class NamedObjectFactory { public: using ObjectCreator = std::function; std::unordered_map creators; public: virtual ~NamedObjectFactory() = default; virtual T* create(std::string name, PlayerbotAI* botAI) { size_t found = name.find("::"); std::string qualifier; if (found != std::string::npos) { qualifier = name.substr(found + 2); name = name.substr(0, found); } if (creators.find(name) == creators.end()) return nullptr; ObjectCreator& creator = creators[name]; T* object = creator(botAI); Qualified* q = dynamic_cast(object); if (q && found != std::string::npos) q->Qualify(qualifier); return object; } std::set supports() { std::set keys; for (typename std::unordered_map::const_iterator it = creators.begin(); it != creators.end(); it++) keys.insert(it->first); return keys; } }; template class NamedObjectContext : public NamedObjectFactory { public: NamedObjectContext(bool shared = false, bool supportsSiblings = false) : NamedObjectFactory(), shared(shared), supportsSiblings(supportsSiblings) { } virtual ~NamedObjectContext() { Clear(); } virtual T* create(std::string name, PlayerbotAI* botAI) override { if (created.find(name) == created.end()) return created[name] = NamedObjectFactory::create(name, botAI); return created[name]; } void Clear() { for (typename std::unordered_map::const_iterator i = created.begin(); i != created.end(); i++) { if (i->second) delete i->second; } created.clear(); } bool IsShared() { return shared; } bool IsSupportsSiblings() { return supportsSiblings; } std::set GetCreated() { std::set keys; for (typename std::unordered_map::iterator it = created.begin(); it != created.end(); it++) keys.insert(it->first); return keys; } protected: std::unordered_map created; bool shared; bool supportsSiblings; }; template class SharedNamedObjectContextList { public: using ObjectCreator = std::function; std::unordered_map creators; std::vector*> contexts; ~SharedNamedObjectContextList() { for (typename std::vector*>::const_iterator i = contexts.begin(); i != contexts.end(); i++) delete *i; } void Add(NamedObjectContext* context) { contexts.push_back(context); for (auto const& iter : context->creators) creators[iter.first] = iter.second; } }; template class NamedObjectContextList { public: using ObjectCreator = std::function; const std::unordered_map& creators; const std::vector*>& contexts; std::unordered_map created; NamedObjectContextList(const SharedNamedObjectContextList& shared) : creators(shared.creators), contexts(shared.contexts) { } ~NamedObjectContextList() { for (typename std::unordered_map::const_iterator i = created.begin(); i != created.end(); i++) { if (i->second) delete i->second; } created.clear(); } T* create(std::string name, PlayerbotAI* botAI) { size_t found = name.find("::"); std::string qualifier; if (found != std::string::npos) { qualifier = name.substr(found + 2); name = name.substr(0, found); } if (creators.find(name) == creators.end()) return nullptr; const ObjectCreator& creator = creators.at(name); T* object = creator(botAI); Qualified* q = dynamic_cast(object); if (q && found != std::string::npos) q->Qualify(qualifier); return object; } T* GetContextObject(const std::string& name, PlayerbotAI* botAI) { if (created.find(name) == created.end()) { if (T* object = create(name, botAI)) return created[name] = object; } return created[name]; } std::set GetSiblings(const std::string& name) { for (auto i = contexts.begin(); i != contexts.end(); i++) { if (!(*i)->IsSupportsSiblings()) continue; std::set supported = (*i)->supports(); std::set::iterator found = supported.find(name); if (found == supported.end()) continue; supported.erase(found); return supported; } return std::set(); } std::set supports() { std::set result; for (auto i = contexts.begin(); i != contexts.end(); i++) { std::set supported = (*i)->supports(); for (std::set::const_iterator j = supported.begin(); j != supported.end(); ++j) result.insert(*j); } return result; } std::set GetCreated() { std::set result; for (typename std::unordered_map::const_iterator i = created.begin(); i != created.end(); i++) result.insert(i->first); return result; } }; template class NamedObjectFactoryList { public: using ObjectCreator = std::function; std::vector*> factories; std::unordered_map creators; virtual ~NamedObjectFactoryList() { for (typename std::vector*>::const_iterator i = factories.begin(); i != factories.end(); i++) delete *i; } T* create(std::string name, PlayerbotAI* botAI) { size_t found = name.find("::"); std::string qualifier; if (found != std::string::npos) { qualifier = name.substr(found + 2); name = name.substr(0, found); } if (creators.find(name) == creators.end()) return nullptr; const ObjectCreator& creator = creators[name]; T* object = creator(botAI); Qualified* q = dynamic_cast(object); if (q && found != std::string::npos) q->Qualify(qualifier); return object; } void Add(NamedObjectFactory* context) { factories.push_back(context); for (auto const& iter : context->creators) creators[iter.first] = iter.second; } T* GetContextObject(const std::string& name, PlayerbotAI* botAI) { if (T* object = create(name, botAI)) return object; return nullptr; } }; #endif