diff --git a/include/Helpers/NetworkingObjects/NetObjManager.cpp b/include/Helpers/NetworkingObjects/NetObjManager.cpp index 3509b99..73f57fd 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.cpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.cpp @@ -1,19 +1,24 @@ #include "NetObjManager.hpp" +#include "NetObjPtr.hpp" namespace NetworkingObjects { - NetObjManager::NetObjManager(std::shared_ptr initIDGen, std::shared_ptr initTypeList): + NetObjManager::NetObjManager(std::shared_ptr initIDGen, std::shared_ptr initTypeList, bool initIsServer): + isServer(initIsServer), idGen(initIDGen), typeList(initTypeList), nextTypeID(0) {} - void NetObjManager::read_update_message(cereal::PortableBinaryInputArchive& a) { + void NetObjManager::read_update_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr& clientReceivedFrom) { NetObjID id; a(id); auto it = objectData.find(id); if(it == objectData.end()) return; auto& netTypeIDData = typeList->netTypeIDData[it->second.netTypeID]; - netTypeIDData.readUpdateFunc(it->second.p.get(), a); + if(isServer) + netTypeIDData.readUpdateFuncServer(NetObjPtr(this, id, it->second.p), a, clientReceivedFrom); + else + netTypeIDData.readUpdateFuncClient(NetObjPtr(this, id, it->second.p), a, clientReceivedFrom); } void NetObjManager::set_client(std::shared_ptr initClient, MessageCommandType initUpdateCommandID) { client = initClient; diff --git a/include/Helpers/NetworkingObjects/NetObjManager.hpp b/include/Helpers/NetworkingObjects/NetObjManager.hpp index d37a74f..b22f64d 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.hpp @@ -11,28 +11,31 @@ #include "../Networking/NetLibrary.hpp" #include "NetObjIDGenerator.hpp" #include "NetObjManagerTypeList.hpp" +#include "NetObjPtr.decl.hpp" +#include "../Networking/NetServer.hpp" namespace NetworkingObjects { - template class NetObjPtr; - class NetObjManager { public: - NetObjManager(std::shared_ptr initIDGen, std::shared_ptr initTypeList); - void read_update_message(cereal::PortableBinaryInputArchive& a); + NetObjManager(std::shared_ptr initIDGen, 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); - template NetObjPtr read_create_message(cereal::PortableBinaryInputArchive& a) { + 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]; - std::shared_ptr sharedPtr = netTypeIDData.allocatorFunc(); - auto [it, placed] = objectData.emplace(id, typeID, sharedPtr); + std::shared_ptr sharedPtr = isServer ? netTypeIDData.allocatorFuncServer() : netTypeIDData.allocatorFuncClient(); + auto [it, placed] = objectData.emplace(id, SingleObjectData{.netTypeID = typeID, .p = sharedPtr}); if(!placed) throw std::runtime_error("[NetObjManager::read_create_message] ID Collision on object creation"); - netTypeIDData.readConstructorFunc(sharedPtr.get(), a); - return NetObjPtr(id, std::static_pointer_cast(sharedPtr)); + if(isServer) + netTypeIDData.readConstructorFuncServer(NetObjPtr(this, id, sharedPtr), a, clientReceivedFrom); + else + netTypeIDData.readConstructorFuncClient(NetObjPtr(this, id, sharedPtr), a, clientReceivedFrom); + return NetObjPtr(this, id, std::static_pointer_cast(sharedPtr)); } template NetObjPtr read_get_obj_from_message(cereal::PortableBinaryInputArchive& a) { NetObjID id; @@ -40,27 +43,27 @@ namespace NetworkingObjects { auto it = objectData.find(id); if(it == objectData.end()) return NetObjPtr(); - return NetObjPtr(id, std::static_pointer_cast(it->second.p)); + return NetObjPtr(this, id, std::static_pointer_cast(it->second.p)); } template NetObjPtr make_obj(Args&&... items) { auto sharedPtr = std::make_shared(items...); NetObjID newID = idGen->gen(); - if(!objectData.emplace(newID, typeList->typeIndexData[std::type_index(typeid(T))].netTypeID, sharedPtr).second) + 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(newID, sharedPtr); + return NetObjPtr(this, newID, sharedPtr); } template NetObjPtr obj_from_ptr(T* p) { std::shared_ptr sharedPtr(p); NetObjID newID = idGen->gen(); - if(!objectData.emplace(newID, typeList->typeIndexData[std::type_index(typeid(T))].netTypeID, sharedPtr).second) + 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(newID, sharedPtr); + 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(id, std::static_pointer_cast(it->second.p)); + return NetObjPtr(this, id, std::static_pointer_cast(it->second.p)); } private: template friend class NetObjPtr; @@ -68,8 +71,8 @@ namespace NetworkingObjects { struct SingleObjectData { NetTypeIDType netTypeID; std::shared_ptr p; - std::optional> timeSinceNoReference; }; + bool isServer; std::shared_ptr client; std::shared_ptr server; MessageCommandType updateCommandID; diff --git a/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp b/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp index 1e12011..dae80cf 100644 --- a/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp @@ -1,27 +1,59 @@ #pragma once #include "../Networking/NetLibrary.hpp" #include +#include "NetObjPtr.decl.hpp" +#include "../Networking/NetServer.hpp" namespace NetworkingObjects { class NetObjManagerTypeList { public: - template void register_class(NetTypeIDType netTypeID, std::function writeConstructorFunc, std::function readConstructorFunc, std::function readUpdateFunc) { - netTypeIDData.emplace(netTypeID, { - .readConstructorFunc = [readConstructorFunc](void* obj, cereal::PortableBinaryInputArchive& message) { - readConstructorFunc(static_cast(obj), message); + template struct ServerClientClassFunctions { + std::function&, cereal::PortableBinaryOutputArchive&)> writeConstructorFuncClient; + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readConstructorFuncClient; + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readUpdateFuncClient; + + std::function&, cereal::PortableBinaryOutputArchive&)> writeConstructorFuncServer; + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readConstructorFuncServer; + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readUpdateFuncServer; + }; + template void register_class(const ServerClientClassFunctions& funcs) { + netTypeIDData[nextNetTypeID] = NetTypeIDContainer { + .readConstructorFuncClient = [f = funcs.readConstructorFuncClient](const NetObjPtr& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr& c) { + if(f) + f(obj.cast(), message, c); }, - .readUpdateFunc = [readUpdateFunc](void* obj, cereal::PortableBinaryInputArchive& message) { - readUpdateFunc(static_cast(obj), message); + .readUpdateFuncClient = [f = funcs.readUpdateFuncClient](const NetObjPtr& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr& c) { + if(f) + f(obj.cast(), message, c); }, - .allocatorFunc = []() { return std::make_shared(); } - }); - typeIndexData.emplace(std::type_index(typeid(T)), { - .netTypeID = netTypeID, - .writeConstructorFunc = [writeConstructorFunc](void* obj, cereal::PortableBinaryInputArchive& message) { - writeConstructorFunc(static_cast(obj), message); + .allocatorFuncClient = []() { return std::static_pointer_cast(std::make_shared()); }, + + .readConstructorFuncServer = [f = funcs.readConstructorFuncServer](const NetObjPtr& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr& c) { + if(f) + f(obj.cast(), message, c); }, - }); + .readUpdateFuncServer = [f = funcs.readUpdateFuncServer](const NetObjPtr& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr& c) { + if(f) + f(obj.cast(), message, c); + }, + .allocatorFuncServer = []() { return std::static_pointer_cast(std::make_shared()); } + }; + typeIndexDataClient[std::type_index(typeid(ClientActualType))] = TypeIndexContainer{ + .netTypeID = nextNetTypeID, + .writeConstructorFunc = [f = funcs.writeConstructorFuncClient](const NetObjPtr& obj, cereal::PortableBinaryOutputArchive& message) { + if(f) + f(obj.cast(), message); + }, + }; + typeIndexDataServer[std::type_index(typeid(ServerActualType))] = TypeIndexContainer{ + .netTypeID = nextNetTypeID, + .writeConstructorFunc = [f = funcs.writeConstructorFuncServer](const NetObjPtr& obj, cereal::PortableBinaryOutputArchive& message) { + if(f) + f(obj.cast(), message); + }, + }; + nextNetTypeID++; } private: friend class NetObjManager; @@ -29,16 +61,24 @@ class NetObjManagerTypeList { struct TypeIndexContainer { NetTypeIDType netTypeID; - std::function writeConstructorFunc; + std::function&, cereal::PortableBinaryOutputArchive&)> writeConstructorFunc; }; - std::unordered_map typeIndexData; + + std::unordered_map typeIndexDataClient; + std::unordered_map typeIndexDataServer; struct NetTypeIDContainer { - std::function readConstructorFunc; - std::function readUpdateFunc; - std::function()> allocatorFunc; + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readConstructorFuncClient; + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readUpdateFuncClient; + std::function()> allocatorFuncClient; + + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readConstructorFuncServer; + std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readUpdateFuncServer; + std::function()> allocatorFuncServer; }; std::unordered_map netTypeIDData; + + NetTypeIDType nextNetTypeID = 0; }; } diff --git a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp new file mode 100644 index 0000000..b7ed193 --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp @@ -0,0 +1,204 @@ +#pragma once +#include "Helpers/Networking/NetLibrary.hpp" +#include "NetObjPtr.hpp" +#include "cereal/archives/portable_binary.hpp" +#include "NetObjManagerTypeList.hpp" + +namespace NetworkingObjects { + enum class ObjPtrOrderedListCommand_StoC : uint8_t { + INSERT_SINGLE, + ERASE_SINGLE + }; + + enum class ObjPtrOrderedListCommand_CtoS : uint8_t { + INSERT_SINGLE, + ERASE_SINGLE + }; + + template class NetObjOrderedListObjectInfo { + public: + NetObjOrderedListObjectInfo(const NetObjPtr& initObj, uint32_t initPos, bool initSyncIgnore): + obj(initObj), + pos(initPos), + syncIgnore(initSyncIgnore) + {} + uint32_t get_pos() const { return pos; } + const NetObjPtr& get_obj() const { return obj; } + private: + NetObjPtr obj; + uint32_t pos; + bool syncIgnore; + template friend class NetObjOrderedList; + template friend class NetObjOrderedListServer; + template friend class NetObjOrderedListClient; + template friend void set_positions_for_object_info_vector(std::vector>>& v, uint32_t i); + }; + + template using NetObjOrderedListObjectInfoPtr = std::shared_ptr>; + + template void set_positions_for_object_info_vector(std::vector>& v, uint32_t i = 0) { + uint32_t vSize = static_cast(v.size()); + for(; i < vSize; i++) + v[i]->pos = i; + } + + template class NetObjOrderedList { + public: + template static NetObjPtr emplace_back(const NetObjPtr>& l, Args&&... args) { + NetObjPtr newObj = l.get_obj_man()->template make_obj(args...); + return push_back_and_send_create(l, newObj); + } + static NetObjPtr push_back_and_send_create(const NetObjPtr>& l, const NetObjPtr& newObj) { + l->push_back(l, newObj); + return newObj; + } + static NetObjPtr insert_and_send_create(const NetObjPtr>& l, uint32_t posToInsertAt, const NetObjPtr& newObj) { + l->insert(l, posToInsertAt, newObj); + return newObj; + } + static void erase(const NetObjPtr>& l, uint32_t indexToErase) { + l->erase_by_index(l, indexToErase); + } + static void erase(const NetObjPtr>& l, const NetObjOrderedListObjectInfoPtr& p) { + l->erase_by_ptr(l, p); + } + virtual uint32_t size() const = 0; + virtual const std::vector>& get_data() const = 0; + protected: + virtual void push_back(const NetObjPtr>& l, const NetObjPtr& newObj) = 0; + virtual void insert(const NetObjPtr>& l, uint32_t posToInsertAt, const NetObjPtr& newObj) = 0; + virtual void erase_by_index(const NetObjPtr>& l, uint32_t indexToErase) = 0; + virtual void erase_by_ptr(const NetObjPtr>& l, const NetObjOrderedListObjectInfoPtr& p) = 0; + virtual void write_constructor(const NetObjPtr>& l, cereal::PortableBinaryOutputArchive& a) = 0; + virtual void read_update(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) = 0; + virtual void read_constructor(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) = 0; + private: + template friend void register_ordered_list_class(NetObjManagerTypeList& t); + static void write_constructor_func(const NetObjPtr>& l, cereal::PortableBinaryOutputArchive& a) { + l->write_constructor(l, a); + } + static void read_constructor_func(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + l->read_constructor(l, a, c); + } + static void read_update_func(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + l->read_update(l, a, c); + } + }; + + template class NetObjOrderedListServer : public NetObjOrderedList { + public: + virtual uint32_t size() const override { + return data.size(); + } + virtual const std::vector>& get_data() const override { + return data; + } + protected: + virtual void push_back(const NetObjPtr>& l, const NetObjPtr& newObj) override { + auto& newObjInfoPtr = data.emplace_back(std::make_shared>(newObj, static_cast(data.size()), false)); + l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::INSERT_SINGLE, newObjInfoPtr->pos); + newObjInfoPtr->obj.write_create_message(a); + }); + } + virtual void insert(const NetObjPtr>& l, uint32_t posToInsertAt, const NetObjPtr& newObj) override { + posToInsertAt = std::min(posToInsertAt, data.size()); + auto& newObjInfoPtr = *data.insert(data.begin() + posToInsertAt, std::make_shared>(newObj, posToInsertAt, false)); + set_positions_for_object_info_vector(data, posToInsertAt); + l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::INSERT_SINGLE, newObjInfoPtr->pos); + newObjInfoPtr->obj.write_create_message(a); + }); + } + virtual void erase_by_index(const NetObjPtr>& l, uint32_t indexToErase) override { + NetObjOrderedListObjectInfoPtr& objToErase = data[indexToErase]; + l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [indexToErase](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::ERASE_SINGLE, indexToErase); + }); + data.erase(data.begin() + indexToErase); + set_positions_for_object_info_vector(data, indexToErase); + } + virtual void erase_by_ptr(const NetObjPtr>& l, const NetObjOrderedListObjectInfoPtr& p) override { + l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [indexToErase = p->pos](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::ERASE_SINGLE, indexToErase); + }); + data.erase(data.begin() + p->pos); + set_positions_for_object_info_vector(data, p->pos); + } + virtual void write_constructor(const NetObjPtr>& l, cereal::PortableBinaryOutputArchive& a) override { + } + virtual void read_constructor(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { + } + virtual void read_update(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { + ObjPtrOrderedListCommand_CtoS command; + a(command); + switch(command) { +//cereal::PortableBinaryInputArchive& a, const std::shared_ptr& clientReceivedFrom + case ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE: + uint32_t newPos; + a(newPos); + insert(l, newPos, l.get_obj_man()->template read_create_message(a, c)); + break; + case ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE: + NetObjID idToErase; + a(idToErase); + insert(l, newPos, l.get_obj_man()->template read_create_message(a, c)); + break; + } + } + private: + std::vector> data; + }; + + template class NetObjOrderedListClient : public NetObjOrderedList { + public: + virtual uint32_t size() const override { + return clientData.size(); + } + virtual const std::vector>& get_data() const override { + return clientData; + } + protected: + virtual void push_back(const NetObjPtr>& l, const NetObjPtr& newObj) override { + auto& newObjInfoPtr = clientData.emplace_back(std::make_shared>(newObj, static_cast(clientData.size()), true)); + l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE, newObjInfoPtr->pos); + newObjInfoPtr->obj.write_create_message(a); + }); + } + virtual void insert(const NetObjPtr>& l, uint32_t posToInsertAt, const NetObjPtr& newObj) { + } + virtual void erase_by_index(const NetObjPtr>& l, uint32_t indexToErase) override { + } + virtual void erase_by_ptr(const NetObjPtr>& l, const NetObjOrderedListObjectInfoPtr& p) override { + } + virtual void write_constructor(const NetObjPtr>& l, cereal::PortableBinaryOutputArchive& a) override { + } + virtual void read_constructor(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) override { + } + virtual void read_update(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) override { + ObjPtrOrderedListCommand_StoC c; + a(c); + switch(c) { + case ObjPtrOrderedListCommand_StoC::INSERT_SINGLE: + break; + case ObjPtrOrderedListCommand_StoC::ERASE_SINGLE: + break; + } + } + private: + std::vector> serverData; + std::vector> clientData; + }; + + template void register_ordered_list_class(NetObjManagerTypeList& t) { + t.register_class, NetObjOrderedList, NetObjOrderedListClient, NetObjOrderedListServer>({ + .writeConstructorFuncClient = NetObjOrderedList::write_constructor_func, + .readConstructorFuncClient = NetObjOrderedList::read_constructor_func, + .readUpdateFuncClient = NetObjOrderedList::read_update_func, + .writeConstructorFuncServer = NetObjOrderedList::write_constructor_func, + .readConstructorFuncServer = NetObjOrderedList::read_constructor_func, + .readUpdateFuncServer = NetObjOrderedList::read_update_func, + }); + } +} diff --git a/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp b/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp new file mode 100644 index 0000000..f24a91e --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp @@ -0,0 +1,33 @@ +#pragma once +#include "NetObjIDGenerator.hpp" +#include + +namespace NetworkingObjects { + class NetObjManager; + template class NetObjPtr { + public: + NetObjPtr(); + NetObjPtr(const NetObjPtr& other); + NetObjPtr& operator=(const NetObjPtr& other); + ~NetObjPtr(); + template NetObjPtr cast() const; + NetObjManager* get_obj_man() const; + NetObjID get_net_id() const; + T* get() const; + std::add_lvalue_reference_t operator*() const requires(!std::is_void_v); + T* operator->() const; + operator bool() const; + std::strong_ordering operator<=>(const NetObjPtr& rhs) const; + void send_client_update(const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const; + void send_server_update_to_all_clients(const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const; + void write_create_message(cereal::PortableBinaryOutputArchive& a) const; + private: + friend class NetObjManager; + template friend class NetObjPtr; + + NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr& initPtr); + NetObjManager* objMan; + NetObjID id; + std::shared_ptr sharedPtr; + }; +} diff --git a/include/Helpers/NetworkingObjects/NetObjPtr.hpp b/include/Helpers/NetworkingObjects/NetObjPtr.hpp index 7ce3f23..bc9aaf5 100644 --- a/include/Helpers/NetworkingObjects/NetObjPtr.hpp +++ b/include/Helpers/NetworkingObjects/NetObjPtr.hpp @@ -1,93 +1,3 @@ #pragma once -#include "NetObjIDGenerator.hpp" -#include -#include -#include -#include -#include "NetObjManager.hpp" -#include "NetObjManagerTypeList.hpp" - -namespace NetworkingObjects { - template class NetObjPtr { - public: - NetObjPtr(): - objMan(nullptr), - sharedPtr(nullptr) - {} - NetObjPtr(const NetObjPtr& other): - objMan(other.objMan), - id(other.id), - sharedPtr(other.sharedPtr) - {} - NetObjPtr& operator=(const NetObjPtr& other) { - if(this != &other) { - if(sharedPtr && sharedPtr.unique()) - objMan->objectData.erase(id); - objMan = other.objMan; - id = other.id; - sharedPtr = other.sharedPtr; - } - return *this; - } - ~NetObjPtr() { - if(sharedPtr && sharedPtr.unique()) - objMan->objectData.erase(id); - } - - NetObjID get_net_id() const { - return id; - } - T* get() const { - return sharedPtr.get(); - } - T& operator*() const { - return *sharedPtr; - } - operator bool() const { - return sharedPtr != nullptr; - } - std::strong_ordering operator<=>(const NetObjPtr& rhs) const { - return sharedPtr <=> rhs.sharedPtr; - } - void send_client_update(const std::string& channel, std::function sendUpdateFunc) const { - if(objMan->client && !objMan->client->is_disconnected()) { - auto ss(std::make_shared()); - { - cereal::PortableBinaryOutputArchive m(*ss); - m(objMan->updateCommandID, id); - sendUpdateFunc(*this, m); - } - objMan->client->send_string_stream_to_server(channel, ss); - } - } - void send_server_update_to_all_clients(const std::string& channel, std::function sendUpdateFunc) const { - if(objMan->server && !objMan->server->is_disconnected()) { - auto ss(std::make_shared()); - { - cereal::PortableBinaryOutputArchive m(*ss); - m(objMan->updateCommandID, id); - sendUpdateFunc(*this, m); - } - objMan->server->send_string_stream_to_all_clients(channel, ss); - } - } - void write_create_message(cereal::PortableBinaryOutputArchive& a) const { - auto& typeIndexData = objMan->typeList->typeIndexData[std::type_index(typeid(T))]; - a(id, typeIndexData.netTypeID); - typeIndexData.writeConstructorFunc(static_cast(this), a); - } - private: - friend class NetObjManager; - - NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr& initPtr): - objMan(initObjMan), - id(initID), - sharedPtr(initPtr) - {} - - NetObjManager* objMan; - NetObjID id; - std::shared_ptr sharedPtr; - }; - -} +#include "NetObjPtr.decl.hpp" +#include "NetObjPtr.impl.hpp" diff --git a/include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp b/include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp new file mode 100644 index 0000000..a3a6027 --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp @@ -0,0 +1,103 @@ +#pragma once +#include +#include +#include +#include +#include +#include "NetObjPtr.decl.hpp" +#include "NetObjManager.hpp" +#include "NetObjManagerTypeList.hpp" + +namespace NetworkingObjects { + template NetObjPtr::NetObjPtr(): + objMan(nullptr), + sharedPtr(nullptr) + {} + template NetObjPtr::NetObjPtr(const NetObjPtr& other): + objMan(other.objMan), + id(other.id), + sharedPtr(other.sharedPtr) + {} + template NetObjPtr& NetObjPtr::operator=(const NetObjPtr& other) { + if(this != &other) { + if(sharedPtr && sharedPtr.unique()) + objMan->objectData.erase(id); + objMan = other.objMan; + id = other.id; + sharedPtr = other.sharedPtr; + } + return *this; + } + template NetObjPtr::~NetObjPtr() { + if(sharedPtr && sharedPtr.unique()) + objMan->objectData.erase(id); + } + + template template NetObjPtr NetObjPtr::cast() const { + return NetObjPtr(objMan, id, std::static_pointer_cast(sharedPtr)); + } + + template NetObjManager* NetObjPtr::get_obj_man() const { + return objMan; + } + + template NetObjID NetObjPtr::get_net_id() const { + return id; + } + + template T* NetObjPtr::get() const { + return sharedPtr.get(); + } + + template std::add_lvalue_reference_t NetObjPtr::operator*() const requires(!std::is_void_v) { + return *sharedPtr; + } + + template T* NetObjPtr::operator->() const { + return sharedPtr.get(); + } + + template NetObjPtr::operator bool() const { + return sharedPtr != nullptr; + } + + template std::strong_ordering NetObjPtr::operator<=>(const NetObjPtr& rhs) const { + return sharedPtr <=> rhs.sharedPtr; + } + + template void NetObjPtr::send_client_update(const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const { + if(objMan->client && !objMan->client->is_disconnected()) { + auto ss(std::make_shared()); + { + cereal::PortableBinaryOutputArchive m(*ss); + m(objMan->updateCommandID, id); + sendUpdateFunc(*this, m); + } + objMan->client->send_string_stream_to_server(channel, ss); + } + } + + template void NetObjPtr::send_server_update_to_all_clients(const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const { + if(objMan->server && !objMan->server->is_disconnected()) { + auto ss(std::make_shared()); + { + cereal::PortableBinaryOutputArchive m(*ss); + m(objMan->updateCommandID, id); + sendUpdateFunc(*this, m); + } + objMan->server->send_string_stream_to_all_clients(channel, ss); + } + } + + template void NetObjPtr::write_create_message(cereal::PortableBinaryOutputArchive& a) const { + auto& typeIndexData = objMan->isServer ? objMan->typeList->typeIndexDataServer[std::type_index(typeid(T))] : objMan->typeList->typeIndexDataClient[std::type_index(typeid(T))]; + a(id, typeIndexData.netTypeID); + typeIndexData.writeConstructorFunc(this->cast(), a); + } + + template NetObjPtr::NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr& initPtr): + objMan(initObjMan), + id(initID), + sharedPtr(initPtr) + {} +} diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index 31f4cf5..36860c2 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -1,6 +1,5 @@ #include "MainProgram.hpp" #include "DrawingProgram/DrawingProgramToolBase.hpp" -#include "Helpers/VersionNumber.hpp" #include "VersionConstants.hpp" #include "cereal/archives/portable_binary.hpp" #include "cereal/details/helpers.hpp" @@ -39,11 +38,23 @@ #include #include +#include +#include +#include + +struct Abc { + int a = 0; +}; MainProgram::MainProgram(): fonts(std::make_shared()), toolbar(*this) { + auto idGen = std::make_shared(); + auto typeList = std::make_shared(); + NetworkingObjects::register_ordered_list_class(*typeList); + auto nObjMan = std::make_shared(idGen, typeList, false); + displayName = Random::get().alphanumeric_str(10); Logger::get().add_log("WORLDFATAL", [&](const std::string& text) {