diff --git a/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp b/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp index d50afa6..4a591db 100644 --- a/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp +++ b/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp @@ -3,7 +3,7 @@ namespace NetworkingObjects { template void register_generic_serialized_class(NetObjManagerTypeList& t) { - t.register_class({ + t.register_class({ .writeConstructorFuncClient = [](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { a(*o); }, diff --git a/include/Helpers/NetworkingObjects/NetObjID.hpp b/include/Helpers/NetworkingObjects/NetObjID.hpp index 36f032e..d021d87 100644 --- a/include/Helpers/NetworkingObjects/NetObjID.hpp +++ b/include/Helpers/NetworkingObjects/NetObjID.hpp @@ -10,6 +10,11 @@ namespace NetworkingObjects { template void serialize(Archive& a) { a(data[1], data[0]); } + std::string to_string() { + std::stringstream ss; + ss << "[" << data[1] << ", " << data[0] << "]"; + return ss.str(); + } NetObjID& operator=(const NetObjID&) = default; bool operator==(const NetObjID&) const = default; static NetObjID random_gen(); diff --git a/include/Helpers/NetworkingObjects/NetObjManager.hpp b/include/Helpers/NetworkingObjects/NetObjManager.hpp index 6ee0307..fbac8f2 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.hpp @@ -23,7 +23,6 @@ namespace NetworkingObjects { 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; @@ -42,7 +41,15 @@ namespace NetworkingObjects { return NetObjPtr(); return NetObjPtr(this, id, std::static_pointer_cast(it->second.p)); } - template NetObjPtr make_obj(Args&&... items) { + 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) diff --git a/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp b/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp index 5161ccc..0a2dcb5 100644 --- a/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManagerTypeList.hpp @@ -17,7 +17,7 @@ class NetObjManagerTypeList { std::function(NetObjManager&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readConstructorFuncServer; std::function&, cereal::PortableBinaryInputArchive&, const std::shared_ptr&)> readUpdateFuncServer; }; - template void register_class(const ServerClientClassFunctions& funcs) { + template void register_class(const ServerClientClassFunctions& funcs) { netTypeIDData[nextNetTypeID] = NetTypeIDContainer { .readConstructorFuncClient = funcs.readConstructorFuncClient, .readUpdateFuncClient = [f = funcs.readUpdateFuncClient](const NetObjPtr& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr& c) { @@ -35,12 +35,14 @@ class NetObjManagerTypeList { .writeConstructorFunc = [f = funcs.writeConstructorFuncClient](const NetObjPtr& obj, cereal::PortableBinaryOutputArchive& message) { f(obj.cast(), message); }, + .allocatorFunc = []() { return std::make_shared(); } }; typeIndexDataServer[std::type_index(typeid(ServerT*))] = TypeIndexContainer{ .netTypeID = nextNetTypeID, .writeConstructorFunc = [f = funcs.writeConstructorFuncServer](const NetObjPtr& obj, cereal::PortableBinaryOutputArchive& message) { f(obj.cast(), message); }, + .allocatorFunc = []() { return std::make_shared(); } }; nextNetTypeID++; } @@ -51,6 +53,7 @@ class NetObjManagerTypeList { struct TypeIndexContainer { NetTypeIDType netTypeID; std::function&, cereal::PortableBinaryOutputArchive&)> writeConstructorFunc; + std::function()> allocatorFunc; }; // std::type_index in this case is the typeinfo for the POINTER of the type in question. This ensures that we get a mapping for the exact type that was registered, not for a child of the type in case of inheritance diff --git a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp index ba3f050..5040ccd 100644 --- a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp @@ -45,9 +45,11 @@ namespace NetworkingObjects { 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); + // Don't use this function unless you're sure that class T isn't a base class + template NetObjPtr emplace_back_direct(const NetObjPtr>& l, Args&&... items) { + NetObjPtr newObj = l.get_obj_man()->template make_obj_direct(items...); + l->push_back(l, newObj); + return newObj; } static NetObjPtr push_back_and_send_create(const NetObjPtr>& l, const NetObjPtr& newObj) { l->push_back(l, newObj); @@ -65,6 +67,7 @@ namespace NetworkingObjects { } virtual uint32_t size() const = 0; virtual const std::vector>& get_data() const = 0; + virtual ~NetObjOrderedList() {} 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; @@ -86,6 +89,7 @@ namespace NetworkingObjects { template class NetObjOrderedListServer : public NetObjOrderedList { public: + NetObjOrderedListServer() {} virtual uint32_t size() const override { return data.size(); } @@ -166,6 +170,7 @@ namespace NetworkingObjects { template class NetObjOrderedListClient : public NetObjOrderedList { public: + NetObjOrderedListClient() {} virtual uint32_t size() const override { return clientData.size(); } @@ -241,13 +246,13 @@ namespace NetworkingObjects { }; template NetObjPtr NetObjOrderedList::read_constructor_func(NetObjManager& objMan, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { - NetObjPtr> allocatedPtr = objMan.is_server() ? objMan.make_obj>().template cast>() : objMan.make_obj>().template cast>(); + NetObjPtr> allocatedPtr = objMan.make_obj>(); allocatedPtr->read_constructor_post_allocation(allocatedPtr, a, c); return allocatedPtr.template cast(); } template void register_ordered_list_class(NetObjManagerTypeList& t) { - t.register_class, NetObjOrderedList>({ + t.register_class, NetObjOrderedList, NetObjOrderedListClient, NetObjOrderedListServer>({ .writeConstructorFuncClient = NetObjOrderedList::write_constructor_func, .readConstructorFuncClient = NetObjOrderedList::read_constructor_func, .readUpdateFuncClient = NetObjOrderedList::read_update_func, diff --git a/src/ConnectionManager.hpp b/src/ConnectionManager.hpp index 816c81a..2f385e4 100644 --- a/src/ConnectionManager.hpp +++ b/src/ConnectionManager.hpp @@ -18,8 +18,8 @@ class ConnectionManager { bool client_exists(); std::unordered_map server_get_resource_retrieval_progress(); NetLibrary::DownloadProgress client_get_resource_retrieval_progress(); + std::unique_ptr localServer; private: std::shared_ptr client; - std::unique_ptr localServer; std::chrono::steady_clock::time_point lastKeepAliveTime; }; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index 686a6a9..dc80f31 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -1,5 +1,6 @@ #include "MainProgram.hpp" #include "DrawingProgram/DrawingProgramToolBase.hpp" +#include "Helpers/NetworkingObjects/NetObjManagerTypeList.hpp" #include "VersionConstants.hpp" #include "cereal/archives/portable_binary.hpp" #include "cereal/details/helpers.hpp" @@ -37,19 +38,16 @@ #endif #include -#include #include -#include #include MainProgram::MainProgram(): fonts(std::make_shared()), toolbar(*this) { - auto typeList = std::make_shared(); - NetworkingObjects::register_generic_serialized_class(*typeList); - NetworkingObjects::register_ordered_list_class(*typeList); - auto nObjMan = std::make_shared(typeList, false); + netObjectTypeList = std::make_shared(); + NetworkingObjects::register_generic_serialized_class(*netObjectTypeList); + NetworkingObjects::register_ordered_list_class(*netObjectTypeList); displayName = Random::get().alphanumeric_str(10); diff --git a/src/MainProgram.hpp b/src/MainProgram.hpp index 9553176..4e5fd8f 100644 --- a/src/MainProgram.hpp +++ b/src/MainProgram.hpp @@ -9,6 +9,7 @@ #include "SharedTypes.hpp" #include #include +#include #include "Toolbar.hpp" #include "World.hpp" @@ -115,6 +116,8 @@ class MainProgram { std::string displayName; + std::shared_ptr netObjectTypeList; + ~MainProgram(); private: void new_tab_open(); diff --git a/src/World.cpp b/src/World.cpp index e3d2566..576de7f 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -30,7 +30,8 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo): rMan(*this), drawProg(*this), bMan(*this), - gridMan(*this) + gridMan(*this), + netObjMan(initMain.netObjectTypeList, worldInfo.conType != CONNECTIONTYPE_CLIENT) { set_canvas_background_color(main.defaultCanvasBackgroundColor); displayName = main.displayName; @@ -68,6 +69,14 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo): gridMan.init_client_callbacks(); init_client_callbacks(); con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, displayName, false); + + using namespace NetworkingObjects; + stringListTest = netObjMan.make_obj>(); + stringListTest->emplace_back_direct(stringListTest, "Hello"); + stringListTest->emplace_back_direct(stringListTest, "World"); + stringListTest->emplace_back_direct(stringListTest, "Test"); + for(const NetObjOrderedListObjectInfoPtr& o : stringListTest->get_data()) + std::cout << "At position: " << o->get_pos() << " we have string: \"" << *o->get_obj() << "\" with object id " << o->get_obj().get_net_id().to_string() << std::endl; } void World::init_client_callbacks() { diff --git a/src/World.hpp b/src/World.hpp index 857fed7..41dcee2 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -1,4 +1,5 @@ #pragma once +#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp" #include "UndoManager.hpp" #include "BookmarkManager.hpp" #include "ResourceManager.hpp" @@ -7,6 +8,7 @@ #include "Toolbar.hpp" #include "SharedTypes.hpp" #include "GridManager.hpp" +#include #include class MainProgram; @@ -45,6 +47,7 @@ class World { BookmarkManager bMan; ConnectionManager con; GridManager gridMan; + NetworkingObjects::NetObjManager netObjMan; std::deque chatMessages; @@ -88,6 +91,8 @@ class World { std::string name; std::unordered_map clients; + NetworkingObjects::NetObjPtr> stringListTest; + void set_canvas_background_color(const Vector3f& newBackColor, bool sendChangeOverNetwork = true); struct CanvasTheme { @@ -100,6 +105,7 @@ class World { uint64_t canvasScale = 0; private: + ClientPortionID get_max_id(ServerPortionID serverID); void init_client_callbacks();