From ceafbf8bb6411a87823f35ad96681e7c4d656c16 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Wed, 10 Dec 2025 13:06:45 +0300 Subject: [PATCH] GridManager now works on net objects --- .../NetObjGenericSerializedClass.hpp | 7 + .../NetworkingObjects/NetObjManager.hpp | 1 + .../NetworkingObjects/NetObjOrderedList.hpp | 19 +- .../NetworkingObjects/NetObjPtr.decl.hpp | 2 + .../NetworkingObjects/NetObjPtr.impl.hpp | 7 + .../NetworkingObjects/NetObjWeakPtr.hpp | 63 ++++++ src/DrawingProgram/DrawingProgram.cpp | 5 +- src/DrawingProgram/DrawingProgram.hpp | 3 +- src/DrawingProgram/GridModifyTool.cpp | 30 +-- src/DrawingProgram/GridModifyTool.hpp | 5 +- src/GridManager.cpp | 190 ++++++------------ src/GridManager.hpp | 29 ++- src/MainProgram.cpp | 2 + src/Server/CommandList.hpp | 4 - src/Server/MainServer.cpp | 20 +- src/Server/ServerData.cpp | 4 - src/Server/ServerData.hpp | 1 - src/Toolbar.cpp | 36 ++-- src/Toolbar.hpp | 2 +- src/World.cpp | 6 +- 20 files changed, 214 insertions(+), 222 deletions(-) create mode 100644 include/Helpers/NetworkingObjects/NetObjWeakPtr.hpp diff --git a/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp b/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp index e570d17..9d11335 100644 --- a/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp +++ b/include/Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp @@ -1,4 +1,5 @@ #pragma once +#include "Helpers/NetworkingObjects/NetObjPtr.decl.hpp" #include "NetObjPtr.hpp" namespace NetworkingObjects { @@ -27,4 +28,10 @@ namespace NetworkingObjects { }, }); } + + template void generic_serialized_class_send_update_to_all(const NetworkingObjects::NetObjPtr& o) { + o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetworkingObjects::NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { + a(*o); + }); + } } diff --git a/include/Helpers/NetworkingObjects/NetObjManager.hpp b/include/Helpers/NetworkingObjects/NetObjManager.hpp index e766c2d..abe9a0e 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.hpp @@ -69,6 +69,7 @@ namespace NetworkingObjects { } template friend class NetObjPtr; + template friend class NetObjWeakPtr; struct SingleObjectData { NetTypeIDType netTypeID; diff --git a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp index f0d3b0e..2b44b5a 100644 --- a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp @@ -56,6 +56,7 @@ namespace NetworkingObjects { static uint32_t erase(const NetObjPtr>& l, const NetObjPtr& p) { return l->erase_by_ptr(l, p); } + virtual bool contains(const NetObjPtr& p) const = 0; virtual uint32_t size() const = 0; virtual const NetObjPtr& at(uint32_t index) const = 0; virtual bool empty() const = 0; @@ -83,6 +84,9 @@ namespace NetworkingObjects { template class NetObjOrderedListServer : public NetObjOrderedList { public: NetObjOrderedListServer() {} + virtual bool contains(const NetObjPtr& p) const override { + return idToDataMap.contains(p.get_net_id()); + } virtual uint32_t size() const override { return data.size(); } @@ -159,8 +163,11 @@ namespace NetworkingObjects { uint32_t constructedSize; a(constructedSize); data.clear(); - for(uint32_t i = 0; i < constructedSize; i++) + idToDataMap.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)); + idToDataMap.emplace(data.back()->obj.get_net_id(), data.back()); + } // 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 } @@ -190,6 +197,9 @@ namespace NetworkingObjects { template class NetObjOrderedListClient : public NetObjOrderedList { public: NetObjOrderedListClient() {} + virtual bool contains(const NetObjPtr& p) const override { + return clientIdToDataMap.contains(p.get_net_id()); + } virtual uint32_t size() const override { return clientData.size(); } @@ -273,9 +283,14 @@ namespace NetworkingObjects { a(constructedSize); clientData.clear(); serverData.clear(); - for(uint32_t i = 0; i < constructedSize; i++) + serverIdToDataMap.clear(); + clientIdToDataMap.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)); + serverIdToDataMap.emplace(serverData.back()->obj.get_net_id(), serverData.back()); + } clientData = serverData; + clientIdToDataMap = serverIdToDataMap; } 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 f200672..f999063 100644 --- a/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp +++ b/include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp @@ -21,10 +21,12 @@ namespace NetworkingObjects { 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 send_update_to_all(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; + template friend class NetObjWeakPtr; NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr& initPtr); NetObjManager* objMan; diff --git a/include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp b/include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp index 2d38b3f..776229a 100644 --- a/include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp +++ b/include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp @@ -89,6 +89,13 @@ namespace NetworkingObjects { } } + template void NetObjPtr::send_update_to_all(const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const { + if(objMan->is_server()) + send_server_update_to_all_clients(channel, sendUpdateFunc); + else + send_client_update(channel, sendUpdateFunc); + } + template void NetObjPtr::write_create_message(cereal::PortableBinaryOutputArchive& a) const { a(id); objMan->typeList->get_type_index_data(objMan->isServer).writeConstructorFunc(this->cast(), a); diff --git a/include/Helpers/NetworkingObjects/NetObjWeakPtr.hpp b/include/Helpers/NetworkingObjects/NetObjWeakPtr.hpp new file mode 100644 index 0000000..b9fe6c6 --- /dev/null +++ b/include/Helpers/NetworkingObjects/NetObjWeakPtr.hpp @@ -0,0 +1,63 @@ +#pragma once +#include "NetObjID.hpp" +#include "NetObjManager.hpp" +#include "NetObjPtr.decl.hpp" + +namespace NetworkingObjects { + template class NetObjWeakPtr { + public: + NetObjWeakPtr(): + objMan(nullptr), + id({0, 0}) + {} + NetObjWeakPtr(const NetObjWeakPtr& other): + objMan(other.objMan), + id(other.id) + {} + NetObjWeakPtr(const NetObjPtr& other): + objMan(other.objMan), + id(other.id) + {} + NetObjWeakPtr& operator=(const NetObjWeakPtr& other) { + objMan = other.objMan; + id = other.id; + } + template NetObjWeakPtr cast() const { + return NetObjWeakPtr(objMan, id); + } + bool expired() const { + if(!objMan) + return true; + auto it = objMan->objectData.find(id); + return it == objMan->objectData.end(); + } + NetObjPtr lock() const { + auto it = objMan->objectData.find(id); + if(it == objMan->objectData.end()) + return NetObjPtr(); + else + return NetObjPtr(objMan, id, std::static_pointer_cast(it->second.p)); + } + NetObjManager* get_obj_man() const { + return objMan; + } + NetObjID get_net_id() const { + return id; + } + bool operator!=(const NetObjWeakPtr& rhs) const { + return objMan != rhs.objMan || id != rhs.id; + } + bool operator==(const NetObjWeakPtr& rhs) const { + return objMan == rhs.objMan && id == rhs.id; + } + private: + NetObjWeakPtr(NetObjManager* initObjMan, NetObjID initID): + objMan(initObjMan), + id(initID) + {} + + template friend class NetObjPtr; + NetObjManager* objMan; + NetObjID id; + }; +} diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 1e7be93..6c23ad7 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -20,6 +20,7 @@ #include "../World.hpp" #include "../MainProgram.hpp" #include "Helpers/FileDownloader.hpp" +#include "Helpers/NetworkingObjects/NetObjWeakPtr.hpp" #include "Helpers/StringHelpers.hpp" #include "LassoSelectTool.hpp" #include @@ -283,9 +284,9 @@ void DrawingProgram::tool_options_gui() { } } -void DrawingProgram::modify_grid(ServerClientID gridToModifyID) { +void DrawingProgram::modify_grid(const NetworkingObjects::NetObjPtr& gridToModify) { std::unique_ptr newTool(std::make_unique(*this)); - newTool->set_grid_id(gridToModifyID); + newTool->set_grid(gridToModify); switch_to_tool_ptr(std::move(newTool)); } diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 8f6383e..f59efd6 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -2,6 +2,7 @@ #include "../DrawData.hpp" #include "DrawingProgramCache.hpp" #include "GridModifyTool.hpp" +#include #include "PanCanvasTool.hpp" #include "ZoomCanvasTool.hpp" #include "cereal/archives/portable_binary.hpp" @@ -63,7 +64,7 @@ class DrawingProgram { void clear_draw_cache(); - void modify_grid(ServerClientID gridToModifyID); + void modify_grid(const NetworkingObjects::NetObjPtr& gridToModify); private: std::optional badFrametimeTimePoint; diff --git a/src/DrawingProgram/GridModifyTool.cpp b/src/DrawingProgram/GridModifyTool.cpp index e9e2fbd..1d1ddab 100644 --- a/src/DrawingProgram/GridModifyTool.cpp +++ b/src/DrawingProgram/GridModifyTool.cpp @@ -2,18 +2,21 @@ #include "DrawingProgram.hpp" #include "../MainProgram.hpp" #include "../DrawData.hpp" +#include +#include #include +using namespace NetworkingObjects; + GridModifyTool::GridModifyTool(DrawingProgram& initDrawP): DrawingProgramToolBase(initDrawP) { } -void GridModifyTool::set_grid_id(ServerClientID newGridID) { - gridID = newGridID; - auto gridFoundIt = drawP.world.gridMan.grids.find(gridID); - if(gridFoundIt != drawP.world.gridMan.grids.end()) { - WorldGrid& g = gridFoundIt->second; +void GridModifyTool::set_grid(const NetObjPtr& newGrid) { + grid = newGrid; + if(drawP.world.gridMan.grids->contains(grid)) { + WorldGrid& g = *grid; oldGrid = g; CoordSpaceHelper newCam; newCam.inverseScale = g.size / WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE); @@ -31,9 +34,8 @@ void GridModifyTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; t.gui.push_id("Grid modify tool"); t.gui.text_label_centered("Edit Grid"); - auto gridFoundIt = drawP.world.gridMan.grids.find(gridID); - if(gridFoundIt != drawP.world.gridMan.grids.end()) { - WorldGrid& g = gridFoundIt->second; + if(drawP.world.gridMan.grids->contains(grid)) { + WorldGrid& g = *grid; t.gui.input_text_field("grid name", "Name", &g.name); t.gui.checkbox_field("Visible", "Visible", &g.visible); t.gui.checkbox_field("Display in Front", "Display in front of canvas", &g.displayInFront); @@ -83,9 +85,8 @@ bool GridModifyTool::right_click_popup_gui(Vector2f popupPos) { } void GridModifyTool::tool_update() { - auto gridFoundIt = drawP.world.gridMan.grids.find(gridID); - if(gridFoundIt != drawP.world.gridMan.grids.end()) { - WorldGrid& g = gridFoundIt->second; + if(drawP.world.gridMan.grids->contains(grid)) { + WorldGrid& g = *grid; switch(selectionMode) { case 0: if(drawP.controls.leftClick) { @@ -145,9 +146,8 @@ bool GridModifyTool::prevent_undo_or_redo() { } void GridModifyTool::draw(SkCanvas* canvas, const DrawData& drawData) { - auto gridFoundIt = drawP.world.gridMan.grids.find(gridID); - if(gridFoundIt != drawP.world.gridMan.grids.end()) { - WorldGrid& g = gridFoundIt->second; + if(drawP.world.gridMan.grids->contains(grid)) { + WorldGrid& g = *grid; if(g.bounds.has_value()) { const auto& b = g.bounds.value(); Vector2f bMin = drawP.world.drawData.cam.c.to_space(b.min); @@ -178,5 +178,5 @@ void GridModifyTool::draw(SkCanvas* canvas, const DrawData& drawData) { } void GridModifyTool::switch_tool(DrawingProgramToolType newTool) { - drawP.world.gridMan.send_grid_info(oldGrid, gridID); + NetworkingObjects::generic_serialized_class_send_update_to_all(grid); } diff --git a/src/DrawingProgram/GridModifyTool.hpp b/src/DrawingProgram/GridModifyTool.hpp index 2801cef..f693be1 100644 --- a/src/DrawingProgram/GridModifyTool.hpp +++ b/src/DrawingProgram/GridModifyTool.hpp @@ -1,13 +1,14 @@ #pragma once #include "DrawingProgramToolBase.hpp" #include "../WorldGrid.hpp" +#include "Helpers/NetworkingObjects/NetObjPtr.hpp" class DrawingProgram; class GridModifyTool : public DrawingProgramToolBase { public: GridModifyTool(DrawingProgram& initDrawP); - void set_grid_id(ServerClientID newGridID); + void set_grid(const NetworkingObjects::NetObjPtr& newGrid); virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; @@ -17,6 +18,6 @@ class GridModifyTool : public DrawingProgramToolBase { virtual void switch_tool(DrawingProgramToolType newTool) override; private: WorldGrid oldGrid; - ServerClientID gridID; + NetworkingObjects::NetObjPtr grid; unsigned selectionMode = 0; }; diff --git a/src/GridManager.cpp b/src/GridManager.cpp index a811c52..616b925 100644 --- a/src/GridManager.cpp +++ b/src/GridManager.cpp @@ -1,4 +1,5 @@ #include "GridManager.hpp" +#include "Helpers/Networking/NetLibrary.hpp" #include "Server/CommandList.hpp" #include "SharedTypes.hpp" #include "World.hpp" @@ -6,166 +7,87 @@ #include GridManager::GridManager(World& w): - world(w) {} - -void GridManager::init_client_callbacks() { - world.con.client_add_recv_callback(CLIENT_SET_GRID, [&](cereal::PortableBinaryInputArchive& message) { - ServerClientID gID; - message(gID); - auto& g = grids[gID]; - message(g); - changed = true; - }); - world.con.client_add_recv_callback(CLIENT_REMOVE_GRID, [&](cereal::PortableBinaryInputArchive& message) { - ServerClientID gID; - message(gID); - grids.erase(gID); - changed = true; - }); + world(w) { + if(w.netObjMan.is_server()) + grids = w.netObjMan.make_obj>(); } -ServerClientID GridManager::add_default_grid(const std::string& newName) { - ServerClientID newID = world.get_new_id(); - WorldGrid g; - g.name = newName; - g.color = color_mul_alpha(convert_vec4(world.canvasTheme.toolFrontColor), 0.4f); - g.size = world.drawData.cam.c.inverseScale * WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE); - g.offset = world.drawData.cam.c.pos + world.drawData.cam.c.dir_from_space(world.main.window.size.cast() * 0.5f); - grids[newID] = g; - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, newID, g); +void GridManager::add_default_grid(const std::string& newName) { + if(grids) { + WorldGrid g; + g.name = newName; + g.color = color_mul_alpha(convert_vec4(world.canvasTheme.toolFrontColor), 0.4f); + g.size = world.drawData.cam.c.inverseScale * WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE); + g.offset = world.drawData.cam.c.pos + world.drawData.cam.c.dir_from_space(world.main.window.size.cast() * 0.5f); + NetworkingObjects::NetObjPtr gridPtr = grids->emplace_back_direct(grids, g); - changed = true; - - world.undo.push({[&world = world, &changed = changed, &grids = grids, newID]() { - grids.erase(newID); - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_REMOVE_GRID, newID); - changed = true; - return true; - }, - [&world = world, &changed = changed, &grids = grids, g, newID]() { - grids[newID] = g; - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, newID, g); - changed = true; - return true; - }}); - - return newID; -} - -void GridManager::send_grid_info(WorldGrid oldGrid, ServerClientID gridID) { - auto gridFoundIt = grids.find(gridID); - if(gridFoundIt != grids.end()) { - WorldGrid& g = gridFoundIt->second; - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, gridID, g); - - world.undo.push({[&world = world, &changed = changed, &grids = grids, gridID, oldGrid]() { - auto gridFoundIt = grids.find(gridID); - if(gridFoundIt == grids.end()) - return false; - gridFoundIt->second = oldGrid; - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, gridID, oldGrid); - changed = true; + uint32_t pos = grids->size() - 1; + world.undo.push({[&grids = grids, gridPtr](){ + grids->erase(grids, gridPtr); return true; }, - [&world = world, &changed = changed, &grids = grids, gridID, g]() { - auto gridFoundIt = grids.find(gridID); - if(gridFoundIt == grids.end()) - return false; - gridFoundIt->second = g; - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, gridID, g); - changed = true; + [&grids = grids, gridPtr, pos]() { + grids->insert_and_send_create(grids, pos, gridPtr); return true; }}); - - changed = true; } } -void GridManager::remove_grid(ServerClientID idToRemove) { - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_REMOVE_GRID, idToRemove); - changed = true; - auto it = grids.find(idToRemove); - if(it == grids.end()) - return; - - WorldGrid g = it->second; - grids.erase(it); - - world.undo.push({[&world = world, &changed = changed, &grids = grids, idToRemove, g]() { - grids[idToRemove] = g; - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, idToRemove, g); - changed = true; - return true; - }, - [&world = world, &changed = changed, &grids = grids, idToRemove]() { - grids.erase(idToRemove); - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_REMOVE_GRID, idToRemove); - changed = true; - return true; - }}); -} - -const std::vector& GridManager::sorted_grid_ids() { - if(changed) { - sortedGridIDs.clear(); - for(auto& [k, v] : grids) - sortedGridIDs.emplace_back(k); - std::sort(sortedGridIDs.begin(), sortedGridIDs.end(), [&](ServerClientID a, ServerClientID b) { - std::string nameA = grids[a].get_display_name(); - std::string nameB = grids[b].get_display_name(); - bool namesEqual = nameA == nameB; - return (!namesEqual && std::lexicographical_compare(nameA.begin(), nameA.end(), nameB.begin(), nameB.end())) || (namesEqual && a < b); - }); - changed = false; +void GridManager::remove_grid(uint32_t indexToRemove) { + if(grids) { + NetworkingObjects::NetObjPtr gridPtr = grids->erase(grids, indexToRemove); + world.undo.push({[&grids = grids, gridPtr, indexToRemove]() { + grids->insert_and_send_create(grids, indexToRemove, gridPtr); + return true; + }, + [&grids = grids, gridPtr](){ + grids->erase(grids, gridPtr); + return true; + }}); } - return sortedGridIDs; -} - -ClientPortionID GridManager::get_max_id(ServerPortionID serverID) const { - ClientPortionID maxClientID = 0; - for(auto& p : grids) { - if(p.first.first == serverID) - maxClientID = std::max(maxClientID, p.first.second); - } - return maxClientID; } void GridManager::draw_back(SkCanvas* canvas, const DrawData& drawData) { - auto& sortedGridIDS = sorted_grid_ids(); - for(ServerClientID id : sortedGridIDS) { - if(!grids[id].displayInFront) - grids[id].draw(*this, canvas, drawData); + if(grids) { + for(uint32_t i = 0; i < grids->size(); i++) { + if(!grids->at(i)->displayInFront) + grids->at(i)->draw(*this, canvas, drawData); + } } } void GridManager::draw_front(SkCanvas* canvas, const DrawData& drawData) { - auto& sortedGridIDS = sorted_grid_ids(); - for(ServerClientID id : sortedGridIDS) { - if(grids[id].displayInFront) - grids[id].draw(*this, canvas, drawData); + if(grids) { + for(uint32_t i = 0; i < grids->size(); i++) { + if(grids->at(i)->displayInFront) + grids->at(i)->draw(*this, canvas, drawData); + } } } void GridManager::draw_coordinates(SkCanvas* canvas, const DrawData& drawData) { - auto& sortedGridIDS = sorted_grid_ids(); - Vector2f axisOffset{0.0f, 0.0f}; - for(ServerClientID id : sortedGridIDS) { - auto& g = grids[id]; - if(g.coordinatesWillBeDrawn && g.coordinatesAxisOnBounds) { - grids[id].draw_coordinates(canvas, drawData, axisOffset); - g.coordinatesWillBeDrawn = false; + if(grids) { + Vector2f axisOffset{0.0f, 0.0f}; + for(uint32_t i = 0; i < grids->size(); i++) { + auto& g = grids->at(i); + if(g->coordinatesWillBeDrawn && g->coordinatesAxisOnBounds) { + g->draw_coordinates(canvas, drawData, axisOffset); + g->coordinatesWillBeDrawn = false; + } + } + for(uint32_t i = 0; i < grids->size(); i++) { + auto& g = grids->at(i); + if(g->coordinatesWillBeDrawn && !g->coordinatesAxisOnBounds) + g->draw_coordinates(canvas, drawData, axisOffset); + g->coordinatesWillBeDrawn = false; } - } - for(ServerClientID id : sortedGridIDS) { - auto& g = grids[id]; - if(g.coordinatesWillBeDrawn && !g.coordinatesAxisOnBounds) - grids[id].draw_coordinates(canvas, drawData, axisOffset); - g.coordinatesWillBeDrawn = false; } } void GridManager::scale_up(const WorldScalar& scaleUpAmount) { - for(auto& [id, g] : grids) { - g.scale_up(scaleUpAmount); + if(grids) { + for(uint32_t i = 0; i < grids->size(); i++) { + grids->at(i)->scale_up(scaleUpAmount); + } } } diff --git a/src/GridManager.hpp b/src/GridManager.hpp index 99aa866..fd1c704 100644 --- a/src/GridManager.hpp +++ b/src/GridManager.hpp @@ -1,38 +1,37 @@ #pragma once +#include "Helpers/NetworkingObjects/NetObjPtr.decl.hpp" #include "WorldGrid.hpp" +#include class World; class GridManager { public: GridManager(World& w); - void init_client_callbacks(); - ServerClientID add_default_grid(const std::string& newName); + void add_default_grid(const std::string& newName); template void save(Archive& a) const { - a(grids); + a(grids->size()); + for(uint32_t i = 0; i < grids->size(); i++) + a(*grids->at(i)); } template void load(Archive& a) { - a(grids); - changed = true; + uint32_t newSize = grids->size(); + for(uint32_t i = 0; i < newSize; i++) { + WorldGrid b; + a(b); + grids->emplace_back_direct(grids, b); + } } - void send_grid_info(WorldGrid oldGrid, ServerClientID gridID); - void remove_grid(ServerClientID idToRemove); + void remove_grid(uint32_t indexToRemove); void draw_back(SkCanvas* canvas, const DrawData& drawData); void draw_front(SkCanvas* canvas, const DrawData& drawData); void draw_coordinates(SkCanvas* canvas, const DrawData& drawData); void scale_up(const WorldScalar& scaleUpAmount); - ClientPortionID get_max_id(ServerPortionID serverID) const; - - const std::vector& sorted_grid_ids(); - - std::unordered_map grids; + NetworkingObjects::NetObjPtr> grids; World& world; - private: - bool changed = true; - std::vector sortedGridIDs; }; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index c62df09..5bbe873 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -50,6 +50,8 @@ MainProgram::MainProgram(): NetworkingObjects::register_ordered_list_class(*netObjectTypeList); NetworkingObjects::register_generic_serialized_class(*netObjectTypeList); NetworkingObjects::register_ordered_list_class(*netObjectTypeList); + NetworkingObjects::register_generic_serialized_class(*netObjectTypeList); + NetworkingObjects::register_ordered_list_class(*netObjectTypeList); displayName = Random::get().alphanumeric_str(10); diff --git a/src/Server/CommandList.hpp b/src/Server/CommandList.hpp index d50fefc..bd501fc 100644 --- a/src/Server/CommandList.hpp +++ b/src/Server/CommandList.hpp @@ -19,8 +19,6 @@ enum ServerCommands : MessageCommandType { SERVER_NEW_RESOURCE_DATA, SERVER_CHAT_MESSAGE, SERVER_CANVAS_COLOR, - SERVER_SET_GRID, - SERVER_REMOVE_GRID, SERVER_CANVAS_SCALE }; @@ -43,8 +41,6 @@ enum ClientCommands : MessageCommandType { CLIENT_NEW_RESOURCE_DATA, CLIENT_CHAT_MESSAGE, CLIENT_CANVAS_COLOR, - CLIENT_SET_GRID, - CLIENT_REMOVE_GRID, CLIENT_CANVAS_SCALE }; diff --git a/src/Server/MainServer.cpp b/src/Server/MainServer.cpp index ae69f91..292af93 100644 --- a/src/Server/MainServer.cpp +++ b/src/Server/MainServer.cpp @@ -31,7 +31,6 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID): data.idToComponentMap.emplace(data.components.back()->id, data.components.back()); } data.canvasScale = world.canvasScale; - data.grids = world.gridMan.grids; data.resources = world.rMan.resource_list(); data.canvasBackColor = convert_vec3(world.canvasTheme.backColor); @@ -75,6 +74,7 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID): cereal::PortableBinaryOutputArchive a(*ss); a(CLIENT_INITIAL_DATA, isDirectConnect, newClient.serverID, newClient.cursorColor, newClient.displayName, newClient.camCoords, newClient.windowSize, fileDisplayName, clients, data); world.bMan.bookmarks.write_create_message(a); + world.gridMan.grids.write_create_message(a); } netServer->send_string_stream_to_client(client, RELIABLE_COMMAND_CHANNEL, ss); for(auto& [id, rData] : data.resources) { @@ -229,24 +229,6 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID): message(chatMessage); netServer->send_items_to_all_clients_except(client, RELIABLE_COMMAND_CHANNEL, CLIENT_CHAT_MESSAGE, client->customID, chatMessage); }); - netServer->add_recv_callback(SERVER_SET_GRID, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { - ServerClientID gID; - message(gID); - WorldGrid& g = data.grids[gID]; - message(g); - - auto& c = clients[client->customID]; - if(c.canvasScale < data.canvasScale) - g.scale_up(FixedPoint::pow_int(CANVAS_SCALE_UP_STEP, data.canvasScale - c.canvasScale)); - - netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_SET_GRID, gID, g); - }); - netServer->add_recv_callback(SERVER_REMOVE_GRID, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { - ServerClientID gID; - message(gID); - data.grids.erase(gID); - netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_REMOVE_GRID, gID); - }); netServer->add_recv_callback(SERVER_CANVAS_COLOR, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { message(data.canvasBackColor); netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_CANVAS_COLOR, data.canvasBackColor); diff --git a/src/Server/ServerData.cpp b/src/Server/ServerData.cpp index 0ef6d91..c161de6 100644 --- a/src/Server/ServerData.cpp +++ b/src/Server/ServerData.cpp @@ -6,7 +6,6 @@ void ServerData::save(cereal::PortableBinaryOutputArchive& a) const { a((uint64_t)components.size()); for(uint64_t i = 0; i < components.size(); i++) a(components[i]->get_type(), components[i]->id, components[i]->coords, *components[i]); - a(grids); } void ServerData::load(cereal::PortableBinaryInputArchive& a) { @@ -21,12 +20,9 @@ void ServerData::load(cereal::PortableBinaryInputArchive& a) { components.emplace_back(newComp); idToComponentMap.emplace(newComp->id, newComp); } - a(grids); } void ServerData::scale_up(const WorldScalar& scaleUpAmount) { - for(auto& [n, g] : grids) - g.scale_up(scaleUpAmount); for(auto& c : components) c->scale_up(scaleUpAmount); } diff --git a/src/Server/ServerData.hpp b/src/Server/ServerData.hpp index 6eff347..2bd12e3 100644 --- a/src/Server/ServerData.hpp +++ b/src/Server/ServerData.hpp @@ -11,7 +11,6 @@ class ServerData { std::vector> components; std::unordered_map> idToComponentMap; std::unordered_map resources; - std::unordered_map grids; uint64_t canvasScale = 0; Vector3f canvasBackColor; diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 383e90e..cbf7b32 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -5,6 +5,7 @@ #include "Helpers/ConvertVec.hpp" #include "Helpers/FileDownloader.hpp" #include "Helpers/Networking/NetLibrary.hpp" +#include "Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp" #include "MainProgram.hpp" #include "GUIStuff/Elements/Element.hpp" #include "GUIStuff/GUIManager.hpp" @@ -708,13 +709,12 @@ void Toolbar::grid_menu(bool justOpened) { gui.obstructing_window(); gui.text_label_centered("Grids"); float entryHeight = 25.0f; - if(main.world->gridMan.sorted_grid_ids().empty()) + if(main.world->gridMan.grids->empty()) gui.text_label_centered("No grids yet..."); - ServerClientID toDelete{0, 0}; - gui.scroll_bar_many_entries_area("grid menu entries", entryHeight, main.world->gridMan.sorted_grid_ids().size(), true, [&](size_t i, bool isListHovered) { - ServerClientID gridID = main.world->gridMan.sorted_grid_ids()[i]; - WorldGrid& grid = main.world->gridMan.grids[gridID]; - bool selectedEntry = gridID == gridMenu.gridSelected; + uint32_t toDelete = std::numeric_limits::max(); + gui.scroll_bar_many_entries_area("grid menu entries", entryHeight, main.world->gridMan.grids->size(), true, [&](size_t i, bool isListHovered) { + auto& grid = main.world->gridMan.grids->at(i); + bool selectedEntry = gridMenu.selectedGrid == i; CLAY_AUTO_ID({ .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(entryHeight)}, @@ -724,7 +724,7 @@ void Toolbar::grid_menu(bool justOpened) { }, .backgroundColor = selectedEntry ? convert_vec4(io->theme->backColor1) : convert_vec4(io->theme->backColor2) }) { - gui.text_label(grid.get_display_name()); + gui.text_label(grid->get_display_name()); bool miniButtonClicked = false; CLAY_AUTO_ID({ .layout = { @@ -734,32 +734,31 @@ void Toolbar::grid_menu(bool justOpened) { .layoutDirection = CLAY_LEFT_TO_RIGHT } }) { - if(gui.svg_icon_button_transparent("visibility eye", grid.visible ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", false, entryHeight, false)) { + if(gui.svg_icon_button_transparent("visibility eye", grid->visible ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", false, entryHeight, false)) { miniButtonClicked = true; - WorldGrid oldGrid = grid; - grid.visible = !grid.visible; - main.world->gridMan.send_grid_info(oldGrid, gridID); + grid->visible = !grid->visible; + NetworkingObjects::generic_serialized_class_send_update_to_all(grid); } if(gui.svg_icon_button_transparent("edit pencil", "data/icons/pencil.svg", false, entryHeight, false)) { miniButtonClicked = true; - main.world->drawProg.modify_grid(gridID); + main.world->drawProg.modify_grid(grid); stop_displaying_grid_menu(); } if(gui.svg_icon_button_transparent("delete trash", "data/icons/trash.svg", false, entryHeight, false)) { miniButtonClicked = true; - toDelete = gridID; + toDelete = i; } } if(Clay_Hovered() && io->mouse.leftClick && isListHovered && !miniButtonClicked) { - gridMenu.gridSelected = gridID; + gridMenu.selectedGrid = i; if(io->mouse.leftClick >= 2) { - main.world->drawProg.modify_grid(gridID); + main.world->drawProg.modify_grid(grid); stop_displaying_grid_menu(); } } } }); - if(toDelete != ServerClientID{0, 0}) + if(toDelete != std::numeric_limits::max()) main.world->gridMan.remove_grid(toDelete); gui.left_to_right_line_layout([&]() { bool addByEnter = false; @@ -767,7 +766,8 @@ void Toolbar::grid_menu(bool justOpened) { addByEnter = s.selected && io->key.enter; }); if(gui.svg_icon_button("grid add button", "data/icons/plus.svg", false, GUIStuff::GUIManager::SMALL_BUTTON_SIZE) || (addByEnter && !gridMenu.newName.empty())) { - main.world->drawProg.modify_grid(main.world->gridMan.add_default_grid(gridMenu.newName)); + main.world->gridMan.add_default_grid(gridMenu.newName); + main.world->drawProg.modify_grid(main.world->gridMan.grids->at(main.world->gridMan.grids->size() - 1)); stop_displaying_grid_menu(); } }); @@ -782,7 +782,7 @@ void Toolbar::grid_menu(bool justOpened) { void Toolbar::stop_displaying_grid_menu() { gridMenu.newName.clear(); gridMenu.popupOpen = false; - gridMenu.gridSelected = ServerClientID{0, 0}; + gridMenu.selectedGrid = std::numeric_limits::max(); } void Toolbar::bookmark_menu(bool justOpened) { diff --git a/src/Toolbar.hpp b/src/Toolbar.hpp index 91b4ca5..c0ca6a9 100644 --- a/src/Toolbar.hpp +++ b/src/Toolbar.hpp @@ -198,7 +198,7 @@ class Toolbar { struct GridMenu { bool popupOpen = false; std::string newName; - ServerClientID gridSelected = {0, 0}; + uint32_t selectedGrid = std::numeric_limits::max(); } gridMenu; bool useNativeFilePicker = true; diff --git a/src/World.cpp b/src/World.cpp index 9ebc735..fd33a32 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -66,7 +66,6 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo): drawProg.init_client_callbacks(); rMan.init_client_callbacks(); - gridMan.init_client_callbacks(); init_client_callbacks(); con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, displayName, false); } @@ -87,8 +86,8 @@ void World::init_client_callbacks() { set_canvas_background_color(newBackColor, false); message(canvasScale); drawProg.initialize_draw_data(message); - message(gridMan); bMan.bookmarks = netObjMan.read_create_message>(message, nullptr); + gridMan.grids = netObjMan.read_create_message>(message, nullptr); } nextClientID = get_max_id(ownID); clientStillConnecting = false; @@ -284,7 +283,6 @@ void World::start_hosting(const std::string& initNetSource, const std::string& s con.init_local_p2p(*this, serverLocalID); drawProg.init_client_callbacks(); rMan.init_client_callbacks(); - gridMan.init_client_callbacks(); init_client_callbacks(); con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, displayName, true, drawData.cam.c, main.window.size.cast().eval()); conType = CONNECTIONTYPE_SERVER; @@ -374,7 +372,7 @@ void World::load_from_file(const std::filesystem::path& filePathToLoadFrom, std: } ClientPortionID World::get_max_id(ServerPortionID serverID) { - return std::max(std::max(rMan.get_max_id(serverID), drawProg.get_max_id(serverID)), gridMan.get_max_id(serverID)); + return std::max(rMan.get_max_id(serverID), drawProg.get_max_id(serverID)); } void World::save_file(cereal::PortableBinaryOutputArchive& a) const {