From 9e049f0201638a4a10dad19d48e9b940d4103b8e Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Mon, 15 Dec 2025 20:52:46 +0300 Subject: [PATCH] Added network unordered set --- .../NetworkingObjects/NetObjUnorderedSet.hpp | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 include/Helpers/NetworkingObjects/NetObjUnorderedSet.hpp diff --git a/include/Helpers/NetworkingObjects/NetObjUnorderedSet.hpp b/include/Helpers/NetworkingObjects/NetObjUnorderedSet.hpp new file mode 100644 index 0000000..326026d --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjUnorderedSet.hpp @@ -0,0 +1,205 @@ +#pragma once +#include "Helpers/Networking/NetLibrary.hpp" +#include "Helpers/NetworkingObjects/NetObjOwnerPtr.decl.hpp" +#include "NetObjOwnerPtr.hpp" +#include "NetObjTemporaryPtr.hpp" +#include "NetObjWeakPtr.hpp" +#include "NetObjID.hpp" +#include +#include +#include "NetObjManagerTypeList.hpp" +#include + +namespace NetworkingObjects { + enum class ObjPtrUnorderedSetCommand_StoC : uint8_t { + INSERT_SINGLE_CONSTRUCT, + ERASE_SINGLE + }; + + enum class ObjPtrUnorderedSetCommand_CtoS : uint8_t { + INSERT_SINGLE, + ERASE_SINGLE + }; + + template class NetObjUnorderedSet { + public: + // Don't use this function unless you're sure that class T isn't a base class + template NetObjTemporaryPtr emplace_direct(const NetObjTemporaryPtr>& l, Args&&... items) { + NetObjOwnerPtr newObj = l.get_obj_man()->template make_obj_direct(items...); + return l->insert(l, nullptr, std::move(newObj)); + } + static NetObjTemporaryPtr insert_and_send_create(const NetObjTemporaryPtr>& l, T* newObj) { + NetObjOwnerPtr newObjOwner = l.get_obj_man()->template make_obj_from_ptr(newObj); + return l->insert(l, nullptr, std::move(newObjOwner)); + } + static bool erase(const NetObjTemporaryPtr>& l, const NetObjID& id) { + return l->erase_by_id(l, id); + } + + typedef std::function& objPtr)> InsertCallback; + typedef std::function& objPtr)> EraseCallback; + + void set_insert_callback(const InsertCallback& func) { + insertCallback = func; + } + void set_erase_callback(const EraseCallback& func) { + eraseCallback = func; + } + + bool contains(const NetObjID& p) const { + return std::find_if(data.begin(), data.end(), [&p](const NetObjOwnerPtr& o){ o.get_net_id() == p; }) != data.end(); + } + const std::vector>& get_data() const { + return data; + } + uint32_t size() const { + return data.size(); + } + bool empty() const { + return data.empty(); + } + virtual ~NetObjUnorderedSet() {} + protected: + NetObjTemporaryPtr insert(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, NetObjOwnerPtr newObj) { + auto& objAdded = this->data.emplace_back(std::move(newObj)); + insert_network(l, clientInserting, objAdded); + call_insert_callback(objAdded); + return objAdded; + } + + bool erase_by_id(const NetObjTemporaryPtr>& l, const NetObjID& id) { + auto it = std::find_if(this->data.begin(), this->data.end(), [&id](const NetObjOwnerPtr& o){ o.get_net_id() == id; }); + if(it == this->data.end()) + return false; + call_erase_callback(*it); + erase_network(l, id); + data.erase(it); + return true; + } + + virtual void insert_network(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, NetObjOwnerPtr newObj) const = 0; + virtual void erase_network(const NetObjTemporaryPtr>& l, const NetObjID& id) const = 0; + virtual void read_update(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) = 0; + + void write_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryOutputArchive& a) { + a(static_cast(data.size())); + for(size_t i = 0; i < data.size(); i++) + data[i]->obj.write_create_message(a); + + } + void read_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + uint32_t newDataSize; + a(newDataSize); + for(size_t i = 0; i < newDataSize; i++) + data.emplace_back(l.get_obj_man()->template read_create_message(a, c)); + } + + // Call after inserting + void call_insert_callback(const NetObjOwnerPtr& objPtr) { + if(insertCallback) + insertCallback(objPtr); + } + + // Call before erasing + void call_erase_callback(const NetObjOwnerPtr& objPtr) { + if(eraseCallback) + eraseCallback(objPtr); + } + + std::vector> data; + + private: + InsertCallback insertCallback; + EraseCallback eraseCallback; + + template friend void register_unordered_set_class(NetObjManager& t); + static void write_constructor_func(const NetObjTemporaryPtr>& l, cereal::PortableBinaryOutputArchive& a) { + l->write_constructor(l, a); + } + static void read_constructor_func(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + l->read_constructor(l, a, c); + } + static void read_update_func(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + l->read_update(l, a, c); + } + }; + + template class NetObjUnorderedSetServer : public NetObjUnorderedSet { + public: + NetObjUnorderedSetServer() {} + protected: + virtual void insert_network(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, NetObjOwnerPtr newObj) const override { + l.send_server_update_to_all_clients_except(clientInserting, RELIABLE_COMMAND_CHANNEL, [&newObj](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrUnorderedSetCommand_StoC::INSERT_SINGLE_CONSTRUCT); + newObj.write_create_message(a); + }); + } + virtual void erase_network(const NetObjTemporaryPtr>& l, const NetObjID& id) const override { + l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [id](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrUnorderedSetCommand_StoC::ERASE_SINGLE, id); + }); + } + virtual void read_update(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { + ObjPtrUnorderedSetCommand_CtoS command; + a(command); + switch(command) { + case ObjPtrUnorderedSetCommand_CtoS::INSERT_SINGLE: { + insert(l, c, l.get_obj_man()->template read_create_message(a, c)); + break; + } + case ObjPtrUnorderedSetCommand_CtoS::ERASE_SINGLE: { + NetObjID idToErase; + a(idToErase); + erase_by_id(l, idToErase); + break; + } + } + } + }; + + template class NetObjUnorderedSetClient : public NetObjUnorderedSet { + public: + NetObjUnorderedSetClient() {} + protected: + virtual void insert_network(const NetObjTemporaryPtr>& l, const std::shared_ptr&, NetObjOwnerPtr newObj) const override { + l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&newObj](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrUnorderedSetCommand_CtoS::INSERT_SINGLE); + newObj.write_create_message(a); + }); + } + virtual void erase_network(const NetObjTemporaryPtr>& l, const NetObjID& id) const override { + l.send_client_update(RELIABLE_COMMAND_CHANNEL, [id](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrUnorderedSetCommand_CtoS::ERASE_SINGLE, id); + }); + } + virtual void read_update(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { + ObjPtrUnorderedSetCommand_StoC command; + a(command); + switch(command) { + case ObjPtrUnorderedSetCommand_StoC::INSERT_SINGLE_CONSTRUCT: { + this->data.emplace_back(l.get_obj_man()->template read_create_message(a, c)); + break; + } + case ObjPtrUnorderedSetCommand_StoC::ERASE_SINGLE: { + NetObjID id; + a(id); + auto it = std::find_if(this->data.begin(), this->data.end(), [&id](const NetObjOwnerPtr& o){ o.get_net_id() == id; }); + if(it != this->data.end()) + this->data.erase(it); + break; + } + } + } + }; + + template void register_unordered_set_class(NetObjManager& objMan) { + objMan.register_class, NetObjUnorderedSet, NetObjUnorderedSetClient, NetObjUnorderedSetServer>({ + .writeConstructorFuncClient = NetObjUnorderedSet::write_constructor_func, + .readConstructorFuncClient = NetObjUnorderedSet::read_constructor_func, + .readUpdateFuncClient = NetObjUnorderedSet::read_update_func, + .writeConstructorFuncServer = NetObjUnorderedSet::write_constructor_func, + .readConstructorFuncServer = NetObjUnorderedSet::read_constructor_func, + .readUpdateFuncServer = NetObjUnorderedSet::read_update_func, + }); + } +}