From da3a764ae9ae23ed6aeddabe0d43a50f32ae17f5 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Fri, 2 Jan 2026 10:29:50 +0300 Subject: [PATCH] Load file speed improved --- .../NetworkingObjects/NetObjOrderedList.hpp | 54 ++++++++++++++----- .../CanvasComponentContainer.hpp | 1 + .../Layers/DrawingProgramLayerManager.cpp | 9 ++-- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp index 89f2b9e..90c3d0c 100644 --- a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp @@ -53,22 +53,13 @@ namespace NetworkingObjects { public: // Don't use this function unless you're sure that class T isn't a base class template NetObjOrderedListIterator emplace_back_direct(const NetObjTemporaryPtr>& l, Args&&... items) { - std::vector, NetObjOwnerPtr>> newObjOwner; - newObjOwner.emplace_back(l->end(), std::move(l.get_obj_man()->template make_obj_direct(items...))); - auto toRet = l->insert_ordered_list(l, nullptr, newObjOwner); - return toRet.empty() ? l->end() : toRet.back(); + return l->insert_single(l, nullptr, l->end(), l.get_obj_man()->template make_obj_direct(items...)); } static NetObjOrderedListIterator push_back_and_send_create(const NetObjTemporaryPtr>& l, T* newObj) { - std::vector, NetObjOwnerPtr>> newObjOwner; - newObjOwner.emplace_back(l->end(), std::move(l.get_obj_man()->template make_obj_from_ptr(newObj))); - auto toRet = l->insert_ordered_list(l, nullptr, newObjOwner); - return toRet.empty() ? l->end() : toRet.back(); + return l->insert_single(l, nullptr, l->end(), l.get_obj_man()->template make_obj_from_ptr(newObj)); } static NetObjOrderedListIterator insert_and_send_create(const NetObjTemporaryPtr>& l, const NetObjOrderedListIterator& it, T* newObj) { - std::vector, NetObjOwnerPtr>> newObjOwner; - newObjOwner.emplace_back(it, std::move(l.get_obj_man()->template make_obj_from_ptr(newObj))); - auto toRet = l->insert_ordered_list(l, nullptr, newObjOwner); - return toRet.empty() ? l->end() : toRet.back(); + return l->insert_single(l, nullptr, it, l.get_obj_man()->template make_obj_from_ptr(newObj)); } static std::vector> insert_ordered_list_and_send_create(const NetObjTemporaryPtr>& l, const std::vector, T*>>& newObjs) { if(newObjs.empty()) @@ -120,6 +111,7 @@ namespace NetworkingObjects { virtual bool empty() const = 0; virtual ~NetObjOrderedList() {} protected: + virtual NetObjOrderedListIterator insert_single(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, const NetObjOrderedListIterator it, NetObjOwnerPtr newObj) = 0; virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector, NetObjOwnerPtr>>& newObj) = 0; virtual void erase_it_list(const NetObjTemporaryPtr>& l, const std::vector>& itList, std::vector>* erasedObjects) = 0; virtual void write_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryOutputArchive& a) = 0; @@ -219,6 +211,29 @@ namespace NetworkingObjects { } } protected: + virtual NetObjOrderedListIterator insert_single(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, const NetObjOrderedListIterator it, NetObjOwnerPtr newObj) override { + NetworkingObjects::NetObjID idPosition; + if(it == data.begin()) + idPosition = NetworkingObjects::NetObjID{0, 0}; + else + idPosition = std::prev(it)->obj.get_net_id(); + + NetObjOrderedListIterator toRet = data.emplace(it, std::move(newObj), it == data.end() ? data.size() : it->pos); + idToDataMap.emplace(toRet->obj.get_net_id(), toRet); + + set_position_obj_info_list(toRet, data.end()); + l.send_server_update_to_all_clients_except(clientInserting, RELIABLE_COMMAND_CHANNEL, [&toRet, &idPosition](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::INSERT_LIST_CONSTRUCT, static_cast(1)); + a(idPosition); + toRet->obj.write_create_message(a); + }); + l.send_server_update_to_client(clientInserting, RELIABLE_COMMAND_CHANNEL, [&toRet, &idPosition](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::INSERT_LIST_REFERENCE, static_cast(1)); + a(idPosition, toRet->obj.get_net_id()); + }); + this->call_insert_callback(toRet); + return toRet; + } virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector, NetObjOwnerPtr>>& newObjs) override { if(newObjs.empty()) return {}; @@ -305,7 +320,6 @@ namespace NetworkingObjects { idToDataMap.emplace(data.back().obj.get_net_id(), it); } // 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 NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { ObjPtrOrderedListCommand_CtoS command; @@ -417,6 +431,20 @@ namespace NetworkingObjects { } } protected: + virtual NetObjOrderedListIterator insert_single(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, const NetObjOrderedListIterator it, NetObjOwnerPtr newObj) override { + NetObjOrderedListIterator toRet = clientData.emplace(it, std::move(newObj), it == clientData.end() ? clientData.size() : it->pos); + clientIdToDataMap.emplace(toRet->obj.get_net_id(), toRet); + + set_position_obj_info_list(toRet, clientData.end()); + l.send_server_update_to_all_clients_except(clientInserting, RELIABLE_COMMAND_CHANNEL, [&toRet](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_CtoS::INSERT_LIST, static_cast(1)); + a(toRet->pos); + toRet->obj.write_create_message(a); + }); + + this->call_insert_callback(toRet); + return toRet; + } virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector, NetObjOwnerPtr>>& newObjs) override { if(newObjs.empty()) return {}; diff --git a/src/CanvasComponents/CanvasComponentContainer.hpp b/src/CanvasComponents/CanvasComponentContainer.hpp index b152bf2..792583c 100644 --- a/src/CanvasComponents/CanvasComponentContainer.hpp +++ b/src/CanvasComponents/CanvasComponentContainer.hpp @@ -15,6 +15,7 @@ class CanvasComponentContainer { public: typedef NetworkingObjects::NetObjOrderedList NetList; typedef NetworkingObjects::NetObjOwnerPtr NetListOwnerPtr; + typedef NetworkingObjects::NetObjTemporaryPtr NetListTemporaryPtr; typedef NetworkingObjects::NetObjOrderedListObjectInfo ObjInfo; typedef NetworkingObjects::NetObjOrderedListIterator ObjInfoIterator; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp index 62a8480..57c92fa 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp @@ -1,10 +1,12 @@ #include "DrawingProgramLayerManager.hpp" #include "../../World.hpp" #include "Helpers/NetworkingObjects/NetObjOrderedList.hpp" +#include "Helpers/NetworkingObjects/NetObjOwnerPtr.decl.hpp" #include "Helpers/Parallel.hpp" #include "../../CanvasComponents/CanvasComponentContainer.hpp" #include "../../CanvasComponents/CanvasComponentAllocator.hpp" #include "../../CanvasComponents/CanvasComponent.hpp" +#include DrawingProgramLayerManager::DrawingProgramLayerManager(DrawingProgram& drawProg): drawP(drawProg), // initialize drawP first for next objects to be initialized properly @@ -116,16 +118,17 @@ void DrawingProgramLayerManager::load_file(cereal::PortableBinaryInputArchive& a } else { server_init_no_file(); - auto editingLayerTmpPtr = editingLayer.lock(); + commitUpdateOnComponentInsert = false; + CanvasComponentContainer::NetListTemporaryPtr editingLayerTmpPtrComponents = editingLayer.lock()->get_layer().components; uint64_t compCount; a(compCount); for(uint64_t i = 0; i < compCount; i++) { CanvasComponentContainer* newContainer = new CanvasComponentContainer(); newContainer->load_file(a, version, drawP.world.netObjMan); - editingLayerTmpPtr->get_layer().components->push_back_and_send_create(editingLayerTmpPtr->get_layer().components, newContainer); + editingLayerTmpPtrComponents->push_back_and_send_create(editingLayerTmpPtrComponents, newContainer); } + commitUpdateOnComponentInsert = true; } - auto flattenedCompList = get_flattened_component_list(); parallel_loop_container(flattenedCompList, [&drawP = drawP](CanvasComponentContainer::ObjInfo* comp) { comp->obj->commit_update_dont_invalidate_cache(drawP);