#pragma once #include #include #include #include #include #include #include #include #include "../Networking/NetClient.hpp" #include "../Networking/NetServer.hpp" #include "../Networking/NetLibrary.hpp" #include "Helpers/NetworkingObjects/NetObjID.hpp" #include "NetObjManagerTypeList.hpp" #include "NetObjPtr.decl.hpp" #include "../Networking/NetServer.hpp" namespace NetworkingObjects { class NetObjManager { public: NetObjManager(std::shared_ptr initTypeList, bool initIsServer); void read_update_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr& clientReceivedFrom); void set_client(std::shared_ptr initClient, MessageCommandType initUpdateCommandID); void set_server(std::shared_ptr initServer, MessageCommandType initUpdateCommandID); bool is_server() const; template NetObjPtr read_create_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr& clientReceivedFrom) { NetObjID id; NetTypeIDType typeID; a(id, typeID); auto& netTypeIDData = typeList->netTypeIDData[typeID]; NetObjPtr newPtr = make_obj_with_id(id); if(isServer) netTypeIDData.readConstructorFuncServer(newPtr.template cast(), a, clientReceivedFrom); else netTypeIDData.readConstructorFuncClient(newPtr.template cast(), a, clientReceivedFrom); return newPtr; } template NetObjPtr read_get_obj_from_message(cereal::PortableBinaryInputArchive& a) { NetObjID id; a(id); auto it = objectData.find(id); if(it == objectData.end()) return NetObjPtr(); return NetObjPtr(this, id, std::static_pointer_cast(it->second.p)); } template NetObjPtr make_obj() { auto sharedPtr = std::static_pointer_cast(isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T*))].allocatorFunc() : typeList->typeIndexDataClient[std::type_index(typeid(T*))].allocatorFunc()); NetObjID newID = NetObjID::random_gen(); if(!objectData.emplace(newID, SingleObjectData{.netTypeID = isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T*))].netTypeID : typeList->typeIndexDataClient[std::type_index(typeid(T*))].netTypeID, .p = std::static_pointer_cast(sharedPtr)}).second) throw std::runtime_error("[NetObjManager::make_obj] ID Collision"); return NetObjPtr(this, newID, sharedPtr); } // Don't use this function unless you're sure that class T isn't a base class template NetObjPtr make_obj_direct(Args&&... items) { auto sharedPtr = std::make_shared(items...); NetObjID newID = NetObjID::random_gen(); if(!objectData.emplace(newID, SingleObjectData{.netTypeID = isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T*))].netTypeID : typeList->typeIndexDataClient[std::type_index(typeid(T*))].netTypeID, .p = std::static_pointer_cast(sharedPtr)}).second) throw std::runtime_error("[NetObjManager::make_obj] ID Collision"); return NetObjPtr(this, newID, sharedPtr); } template NetObjPtr obj_from_ptr(T* p) { std::shared_ptr sharedPtr(p); NetObjID newID = NetObjID::random_gen(); if(!objectData.emplace(newID, SingleObjectData{.netTypeID = isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T*))].netTypeID : typeList->typeIndexDataClient[std::type_index(typeid(T*))].netTypeID, .p = std::static_pointer_cast(sharedPtr)}).second) throw std::runtime_error("[NetObjManager::obj_from_ptr] ID Collision"); return NetObjPtr(this, newID, sharedPtr); } template NetObjPtr get_obj_from_id(NetObjID id) { auto it = objectData.find(id); if(it == objectData.end()) throw std::runtime_error("[NetObjManager::get_obj_from_id] ID doesn't exist"); return NetObjPtr(this, id, std::static_pointer_cast(it->second.p)); } private: template NetObjPtr make_obj_with_id(NetObjID id) { auto sharedPtr = std::static_pointer_cast(isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T*))].allocatorFunc() : typeList->typeIndexDataClient[std::type_index(typeid(T*))].allocatorFunc()); if(!objectData.emplace(id, SingleObjectData{.netTypeID = isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T*))].netTypeID : typeList->typeIndexDataClient[std::type_index(typeid(T*))].netTypeID, .p = std::static_pointer_cast(sharedPtr)}).second) throw std::runtime_error("[NetObjManager::make_obj] ID Collision"); return NetObjPtr(this, id, sharedPtr); } template friend class NetObjPtr; struct SingleObjectData { NetTypeIDType netTypeID; std::shared_ptr p; }; bool isServer; std::shared_ptr client; std::shared_ptr server; MessageCommandType updateCommandID; std::unordered_map objectData; std::shared_ptr typeList; NetTypeIDType nextTypeID; }; }