/* * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it * and/or modify it under version 2 of the License, or (at your option), any later version. */ #ifndef _PLAYERBOT_NAMEDOBJECTCONEXT_H #define _PLAYERBOT_NAMEDOBJECTCONEXT_H #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(std::vector qualifiers, const std::string& separator, const std::string_view brackets = "{}"); static std::vector getMultiQualifiers(std::string const qualifier1); static int32 getMultiQualifier(std::string const qualifier1, uint32 pos); protected: std::string qualifier; }; template class NamedObjectFactory { public: typedef T* (*ObjectCreator)(PlayerbotAI* botAI); std::unordered_map creators; public: 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]; if (!creator) return nullptr; 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::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(); } T* create(std::string const name, PlayerbotAI* botAI) { if (created.find(name) == created.end()) return created[name] = NamedObjectFactory::create(name, botAI); return created[name]; } void Clear() { for (typename std::unordered_map::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: typedef T* (*ObjectCreator)(PlayerbotAI* botAI); std::unordered_map creators; std::vector*> contexts; ~SharedNamedObjectContextList() { for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) delete *i; } void Add(NamedObjectContext* context) { contexts.push_back(context); for (const auto& iter : context->creators) { creators[iter.first] = iter.second; } } }; template class NamedObjectContextList { public: typedef T* (*ObjectCreator)(PlayerbotAI* botAI); 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::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; ObjectCreator creator = creators.at(name); if (!creator) return nullptr; T* object = (*creator)(botAI); Qualified* q = dynamic_cast(object); if (q && found != std::string::npos) q->Qualify(qualifier); return object; } T* GetContextObject(std::string const 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(std::string const 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::iterator j = supported.begin(); j != supported.end(); j++) result.insert(*j); } return result; } std::set GetCreated() { std::set result; for (typename std::unordered_map::iterator i = created.begin(); i != created.end(); i++) { result.insert(i->first); } return result; } }; template class NamedObjectFactoryList { public: typedef T* (*ObjectCreator)(PlayerbotAI* botAI); std::vector*> factories; std::unordered_map creators; virtual ~NamedObjectFactoryList() { for (typename std::vector*>::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; ObjectCreator creator = creators[name]; if (!creator) return nullptr; 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 (const auto& iter : context->creators) { creators[iter.first] = iter.second; } } T* GetContextObject(std::string const name, PlayerbotAI* botAI) { if (T* object = create(name, botAI)) return object; return nullptr; } }; #endif