diff --git a/CMakeLists.txt b/CMakeLists.txt index baede0d..530d0c0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,8 +103,8 @@ set(sources "src/main.cpp" "include/Helpers/Networking/NetServer.cpp" "include/Helpers/Networking/NetClient.cpp" "include/Helpers/Networking/ByteStream.cpp" - "include/Helpers/NetworkingObjects/NetObjIDGenerator.cpp" "include/Helpers/NetworkingObjects/NetObjManager.cpp" + "include/Helpers/NetworkingObjects/NetObjID.cpp" "include/Helpers/Hashes.cpp" "include/Helpers/BezierEasing.cpp" "include/Helpers/Random.cpp" diff --git a/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp b/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp new file mode 100644 index 0000000..d50afa6 --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp @@ -0,0 +1,34 @@ +#pragma once +#include "NetObjPtr.hpp" + +namespace NetworkingObjects { + template void register_generic_serialized_class(NetObjManagerTypeList& t) { + t.register_class({ + .writeConstructorFuncClient = [](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { + a(*o); + }, + .readConstructorFuncClient = [](NetObjManager& m, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) { + NetObjPtr o = m.make_obj(); + a(*o); + return o.template cast(); + }, + .readUpdateFuncClient = [](const NetObjPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) { + a(*o); + }, + .writeConstructorFuncServer = [](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { + a(*o); + }, + .readConstructorFuncServer = [](NetObjManager& m, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) { + NetObjPtr o = m.make_obj(); + a(*o); + return o.template cast(); + }, + .readUpdateFuncServer = [](const NetObjPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) { + a(*o); + o.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { + a(*o); + }); + }, + }); + } +} diff --git a/include/Helpers/NetworkingObjects/NetObjID.cpp b/include/Helpers/NetworkingObjects/NetObjID.cpp new file mode 100644 index 0000000..110657a --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjID.cpp @@ -0,0 +1,10 @@ +#include "NetObjID.hpp" + +namespace NetworkingObjects { + + +NetObjID NetObjID::random_gen() { + return NetObjID{.data = {Random::get().randGen(), Random::get().randGen()}}; +} + +} diff --git a/include/Helpers/NetworkingObjects/NetObjID.hpp b/include/Helpers/NetworkingObjects/NetObjID.hpp new file mode 100644 index 0000000..36f032e --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjID.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include +#include + +namespace NetworkingObjects { + struct NetObjID { + std::array data; + template void serialize(Archive& a) { + a(data[1], data[0]); + } + NetObjID& operator=(const NetObjID&) = default; + bool operator==(const NetObjID&) const = default; + static NetObjID random_gen(); + }; +}; + +template <> struct std::hash { + size_t operator()(const NetworkingObjects::NetObjID& v) const + { + uint64_t h = 0; + hash_combine(h, v.data[1], v.data[0]); + return h; + } +}; diff --git a/include/Helpers/NetworkingObjects/NetObjIDGenerator.cpp b/include/Helpers/NetworkingObjects/NetObjIDGenerator.cpp deleted file mode 100644 index ac905b6..0000000 --- a/include/Helpers/NetworkingObjects/NetObjIDGenerator.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "NetObjIDGenerator.hpp" - -namespace NetworkingObjects { - -void NetObjIDGenerator::set_starting_id(NetObjID c) { - currentID = c; -} - -NetObjID NetObjIDGenerator::gen() { - currentID.clientID++; - return currentID; -} - -} diff --git a/include/Helpers/NetworkingObjects/NetObjIDGenerator.hpp b/include/Helpers/NetworkingObjects/NetObjIDGenerator.hpp deleted file mode 100644 index 210d47b..0000000 --- a/include/Helpers/NetworkingObjects/NetObjIDGenerator.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include "../Hashes.hpp" - -namespace NetworkingObjects { - -struct NetObjID { - typedef uint16_t ClientPortion; - typedef uint64_t ObjectPortion; - ClientPortion clientID = 0; - ObjectPortion objID = 0; - bool operator==(const NetObjID&) const = default; - template void serialize(Archive& a) { - a(clientID, objID); - } -}; - -class NetObjIDGenerator { -public: - void set_starting_id(NetObjID c); - NetObjID gen(); -private: - NetObjID currentID; -}; - -} - -template <> struct std::hash { - size_t operator()(const NetworkingObjects::NetObjID& v) const - { - uint64_t h = 0; - hash_combine(h, v.clientID, v.objID); - return h; - } -}; diff --git a/include/Helpers/NetworkingObjects/NetObjManager.cpp b/include/Helpers/NetworkingObjects/NetObjManager.cpp index 47e15d2..ce870a4 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.cpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.cpp @@ -2,9 +2,8 @@ #include "NetObjPtr.hpp" namespace NetworkingObjects { - NetObjManager::NetObjManager(std::shared_ptr initIDGen, std::shared_ptr initTypeList, bool initIsServer): + NetObjManager::NetObjManager(std::shared_ptr initTypeList, bool initIsServer): isServer(initIsServer), - idGen(initIDGen), typeList(initTypeList), nextTypeID(0) {} diff --git a/include/Helpers/NetworkingObjects/NetObjManager.hpp b/include/Helpers/NetworkingObjects/NetObjManager.hpp index 6cde3b8..6ee0307 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.hpp @@ -6,10 +6,11 @@ #include #include #include +#include #include "../Networking/NetClient.hpp" #include "../Networking/NetServer.hpp" #include "../Networking/NetLibrary.hpp" -#include "NetObjIDGenerator.hpp" +#include "Helpers/NetworkingObjects/NetObjID.hpp" #include "NetObjManagerTypeList.hpp" #include "NetObjPtr.decl.hpp" #include "../Networking/NetServer.hpp" @@ -17,7 +18,7 @@ namespace NetworkingObjects { class NetObjManager { public: - NetObjManager(std::shared_ptr initIDGen, std::shared_ptr initTypeList, bool initIsServer); + 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); @@ -43,14 +44,14 @@ namespace NetworkingObjects { } template NetObjPtr make_obj(Args&&... items) { auto sharedPtr = std::make_shared(items...); - NetObjID newID = idGen->gen(); + 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 = idGen->gen(); + 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); @@ -73,7 +74,6 @@ namespace NetworkingObjects { std::shared_ptr server; MessageCommandType updateCommandID; std::unordered_map objectData; - std::shared_ptr idGen; std::shared_ptr typeList; NetTypeIDType nextTypeID; }; diff --git a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp index e3c90ae..ba3f050 100644 --- a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp @@ -1,6 +1,7 @@ #pragma once #include "Helpers/Networking/NetLibrary.hpp" #include "NetObjPtr.hpp" +#include "NetObjID.hpp" #include "cereal/archives/portable_binary.hpp" #include "NetObjManagerTypeList.hpp" @@ -124,8 +125,18 @@ namespace NetworkingObjects { set_positions_for_object_info_vector(data, iToErase); } virtual void write_constructor(const NetObjPtr>& l, cereal::PortableBinaryOutputArchive& a) override { + a(static_cast(data.size())); + for(size_t i = 0; i < data.size(); i++) + data[i]->obj.write_create_message(a); } virtual void read_constructor_post_allocation(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { + uint32_t constructedSize; + a(constructedSize); + data.clear(); + for(uint32_t i = 0; i < constructedSize; i++) + data.emplace_back(std::make_shared>(l.get_obj_man()->template read_create_message(a, c), static_cast(data.size()), false)); + // Dont send the object data to all clients in the constructor, as the function that called read_create_message is also the one that will decide where to send the data of the constructed object + // Example: the INSERT_SINGLE command in read_update, if it was inserting another NetObjOrderedList, would first construct the list using read_create_message, then it will call insert() to send it to clients } virtual void read_update(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { ObjPtrOrderedListCommand_CtoS command; @@ -164,24 +175,30 @@ namespace NetworkingObjects { 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) { + l.send_client_update(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) { + posToInsertAt = std::min(posToInsertAt, clientData.size()); + auto& newObjInfoPtr = *clientData.insert(clientData.begin() + posToInsertAt, std::make_shared>(newObj, posToInsertAt, true)); + l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE, newObjInfoPtr->pos); + newObjInfoPtr->obj.write_create_message(a); + }); } virtual void erase_by_index(const NetObjPtr>& l, uint32_t indexToErase) override { indexToErase = std::min(indexToErase, clientData.size()); auto& newObjInfoPtr = clientData[indexToErase]; - l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { a(ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE, newObjInfoPtr->obj.get_net_id()); }); clientData.erase(clientData.begin() + indexToErase); set_positions_for_object_info_vector(clientData, indexToErase); } virtual void erase_by_ptr(const NetObjPtr>& l, const NetObjOrderedListObjectInfoPtr& p) override { - l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&p](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { + l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&p](const NetObjPtr>&, cereal::PortableBinaryOutputArchive& a) { a(ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE, p->obj.get_net_id()); }); uint32_t iToErase = p->pos; @@ -189,8 +206,18 @@ namespace NetworkingObjects { set_positions_for_object_info_vector(clientData, iToErase); } virtual void write_constructor(const NetObjPtr>& l, cereal::PortableBinaryOutputArchive& a) override { + a(static_cast(clientData.size())); + for(size_t i = 0; i < clientData.size(); i++) + clientData[i]->obj.write_create_message(a); } virtual void read_constructor_post_allocation(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) override { + uint32_t constructedSize; + a(constructedSize); + clientData.clear(); + serverData.clear(); + for(uint32_t i = 0; i < constructedSize; i++) + serverData.emplace_back(std::make_shared>(l.get_obj_man()->template read_create_message(a, nullptr), static_cast(serverData.size()), false)); + clientData = serverData; } virtual void read_update(const NetObjPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) override { ObjPtrOrderedListCommand_StoC c; diff --git a/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp b/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp index f24a91e..f200672 100644 --- a/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp +++ b/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp @@ -1,6 +1,7 @@ #pragma once -#include "NetObjIDGenerator.hpp" +#include "NetObjID.hpp" #include +#include namespace NetworkingObjects { class NetObjManager; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index 36860c2..686a6a9 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -39,21 +39,17 @@ #include #include #include -#include #include - -struct Abc { - int a = 0; -}; +#include 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); + NetworkingObjects::register_generic_serialized_class(*typeList); + NetworkingObjects::register_ordered_list_class(*typeList); + auto nObjMan = std::make_shared(typeList, false); displayName = Random::get().alphanumeric_str(10);