From 279a9317a411f874b6a4c3279b2ece2742be9552 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Tue, 2 Jun 2026 21:57:53 +0300 Subject: [PATCH] Added multi command block --- include/Helpers/Networking/NetClient.cpp | 63 +++++++++++++---- include/Helpers/Networking/NetClient.hpp | 8 +++ include/Helpers/Networking/NetServer.cpp | 69 ++++++++++++++++--- include/Helpers/Networking/NetServer.hpp | 8 +++ .../NetworkingObjects/NetObjManager.cpp | 32 +-------- .../NetworkingObjects/NetObjManager.hpp | 44 ++++-------- src/CommandList.hpp | 4 +- .../Layers/DrawingProgramLayerManager.cpp | 8 +-- src/DrawingProgram/Tools/BrushTool.cpp | 7 +- src/DrawingProgram/Tools/EraserTool.cpp | 4 +- src/DrawingProgram/Tools/LineDrawTool.cpp | 4 +- src/World.cpp | 19 ++--- src/World.hpp | 1 + src/WorldUndoManager.cpp | 8 +-- 14 files changed, 173 insertions(+), 106 deletions(-) diff --git a/include/Helpers/Networking/NetClient.cpp b/include/Helpers/Networking/NetClient.cpp index a15d35c..3b4e437 100644 --- a/include/Helpers/Networking/NetClient.cpp +++ b/include/Helpers/Networking/NetClient.cpp @@ -21,6 +21,8 @@ #include "NetServer.hpp" #include #include +#include +#include NetClient::NetClient(const std::string& serverFullID) { receiveQueue = std::make_shared(); @@ -111,9 +113,14 @@ void NetClient::parse_received_messages() { decode_fragmented_message(inArchive, spfm, NetLibrary::FRAGMENT_MESSAGE_STRIDE, [&](cereal::PortableBinaryInputArchive& completeArchive) { MessageCommandType completeCommandID; completeArchive(completeCommandID); - recvCallbacks[completeCommandID](completeArchive); + if(completeCommandID == 1) + parse_multi_command_id(completeArchive); + else + recvCallbacks[completeCommandID](completeArchive); }); } + else if(commandID == 1) + parse_multi_command_id(inArchive); else recvCallbacks[commandID](inArchive); @@ -121,23 +128,39 @@ void NetClient::parse_received_messages() { } } +void NetClient::parse_multi_command_id(cereal::PortableBinaryInputArchive& a) { + std::vector commands; + a(commands); + for(const std::string& str : commands) { + ByteMemStream strm((char*)str.data(), str.size()); + cereal::PortableBinaryInputArchive inArchive(strm); + MessageCommandType commandID; + inArchive(commandID); + recvCallbacks[commandID](inArchive); + } +} + void NetClient::send_string_stream_to_server(const std::string& channel, const std::shared_ptr& ss) { if(isDisconnected) return; - auto& messageQueue = messageQueues[channel]; - - if(channel == UNRELIABLE_COMMAND_CHANNEL) { - if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) // Drop unreliable messages that are too big - messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss); - } + if(!multiCommandData.expired() && channel == multiCommandData.lock()->channelToSendTo) + multiCommandData.lock()->commands.emplace_back(ss->str()); else { - std::vector> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE); - if(fragmentedMessage.empty()) - messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss); + auto& messageQueue = messageQueues[channel]; + + if(channel == UNRELIABLE_COMMAND_CHANNEL) { + if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) // Drop unreliable messages that are too big + messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss); + } else { - for(auto& ss2 : fragmentedMessage) - messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss2); + std::vector> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE); + if(fragmentedMessage.empty()) + messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss); + else { + for(auto& ss2 : fragmentedMessage) + messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss2); + } } } } @@ -194,6 +217,22 @@ void NetClient::send_queued_messages() { } } +void NetClient::send_multi_command_to_server(const std::string& channel, const std::function& captureSendBlock) { + if(!is_disconnected() && multiCommandData.expired() && !channel.empty()) { // Check for multiUpdateData.expired() to make sure we aren't overriding a previous call to send_multi_update_messsage + std::shared_ptr d = std::make_shared(); + d->channelToSendTo = channel; + multiCommandData = d; // Using weak pointer here ensures that object will be freed + captureSendBlock(); + if(!d->commands.empty()) { + std::vector movedVec = std::move(d->commands); + d = nullptr; + send_items_to_server(channel, (MessageCommandType)1, movedVec); + } + } + else + captureSendBlock(); +} + bool NetClient::is_disconnected() const { return isDisconnected; } diff --git a/include/Helpers/Networking/NetClient.hpp b/include/Helpers/Networking/NetClient.hpp index d8cabd4..629360e 100644 --- a/include/Helpers/Networking/NetClient.hpp +++ b/include/Helpers/Networking/NetClient.hpp @@ -46,6 +46,7 @@ class NetClient : public std::enable_shared_from_this { send_string_stream_to_server(channel, ss); } void send_string_stream_to_server(const std::string& channel, const std::shared_ptr& ss); + void send_multi_command_to_server(const std::string& channel, const std::function& captureSendBlock); void update(); void add_recv_callback(MessageCommandType commandID, const NetClientRecvCallback& callback); bool is_disconnected() const; @@ -58,6 +59,7 @@ class NetClient : public std::enable_shared_from_this { void parse_received_messages(); void send_queued_messages(); void send_str_as_bytes(std::shared_ptr channel, const std::string& str); + void parse_multi_command_id(cereal::PortableBinaryInputArchive& inArchive); struct OutgoingMessage { MessageOrder order; @@ -90,6 +92,12 @@ class NetClient : public std::enable_shared_from_this { std::string serverFullID; bool fullyRegistered = false; + struct MultiCommandData { + std::string channelToSendTo; + std::vector commands; + }; + std::weak_ptr multiCommandData; + std::chrono::steady_clock::time_point lastMessageTime; friend class NetLibrary; diff --git a/include/Helpers/Networking/NetServer.cpp b/include/Helpers/Networking/NetServer.cpp index b9087b7..2b9237e 100644 --- a/include/Helpers/Networking/NetServer.cpp +++ b/include/Helpers/Networking/NetServer.cpp @@ -24,7 +24,9 @@ #include #include #include "NetClient.hpp" -#include "cereal/archives/portable_binary.hpp" +#include +#include +#include NetServer::NetServer(const std::string& serverLocalID) { localID = serverLocalID; @@ -124,6 +126,9 @@ void NetServer::client_connected(std::shared_ptr connection } void NetServer::send_string_stream_to_client(const std::shared_ptr& client, const std::string& channel, const std::shared_ptr& ss) { + if(!multiCommandData.expired() && channel == multiCommandData.lock()->channelToSendTo) + throw std::runtime_error("[NetServer::send_string_stream_to_client] Can't call when in send_multi_command block using same channel"); + if(!client) return; @@ -144,18 +149,33 @@ void NetServer::send_string_stream_to_client(const std::shared_ptr& } void NetServer::send_string_stream_to_all_clients(const std::string& channel, const std::shared_ptr& ss) { - send_string_stream_to_client_if([&](const std::shared_ptr& c) { - return true; - }, channel, ss); + if(!multiCommandData.expired() && channel == multiCommandData.lock()->channelToSendTo) + multiCommandData.lock()->commands.emplace_back(ss->str()); + else { + send_string_stream_to_client_if([&](const std::shared_ptr& c) { + return true; + }, channel, ss); + } } void NetServer::send_string_stream_to_all_clients_except(const std::shared_ptr& client, const std::string& channel, const std::shared_ptr& ss) { - send_string_stream_to_client_if([&](const std::shared_ptr& c) { - return c != client; - }, channel, ss); + if(!multiCommandData.expired() && channel == multiCommandData.lock()->channelToSendTo) { + if(!client) + multiCommandData.lock()->commands.emplace_back(ss->str()); + else + throw std::runtime_error("[NetServer::send_string_stream_to_all_clients_except] Can't call when in send_multi_command block using same channel"); + } + else { + send_string_stream_to_client_if([&](const std::shared_ptr& c) { + return c != client; + }, channel, ss); + } } void NetServer::send_string_stream_to_client_if(std::function&)> clientChecker, const std::string& channel, const std::shared_ptr& ss) { + if(!multiCommandData.expired() && channel == multiCommandData.lock()->channelToSendTo) + throw std::runtime_error("[NetServer::send_string_stream_to_client_if] Can't call when in send_multi_command block using same channel"); + if(channel == UNRELIABLE_COMMAND_CHANNEL) { if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) { // Drop unreliable messages that are too big for(auto& client : clients) { @@ -183,6 +203,22 @@ void NetServer::send_string_stream_to_client_if(std::function& captureSendBlock) { + if(!is_disconnected() && multiCommandData.expired() && !channel.empty()) { // Check for multiUpdateData.expired() to make sure we aren't overriding a previous call to send_multi_update_messsage + std::shared_ptr d = std::make_shared(); + d->channelToSendTo = channel; + multiCommandData = d; // Using weak pointer here ensures that object will be freed + captureSendBlock(); + if(!d->commands.empty()) { + std::vector movedVec = std::move(d->commands); + d = nullptr; + send_items_to_all_clients(channel, (MessageCommandType)1, movedVec); + } + } + else + captureSendBlock(); +} + void NetServer::ClientData::send_queued_messages(NetServer& server) { for(auto& [channelName, messageQueue] : messageQueues) { bool addMessageOrder = NetLibrary::is_ordered_channel(channelName); @@ -258,9 +294,14 @@ void NetServer::ClientData::parse_received_messages(NetServer& server) { decode_fragmented_message(inArchive, spfm, NetLibrary::FRAGMENT_MESSAGE_STRIDE, [&](cereal::PortableBinaryInputArchive& completeArchive) { MessageCommandType completeCommandID; completeArchive(completeCommandID); - server.recvCallbacks[completeCommandID](shared_from_this(), completeArchive); + if(completeCommandID == 1) + parse_multi_command_id(server, completeArchive); + else + server.recvCallbacks[completeCommandID](shared_from_this(), completeArchive); }); } + else if(commandID == 1) + parse_multi_command_id(server, inArchive); else server.recvCallbacks[commandID](shared_from_this(), inArchive); @@ -268,6 +309,18 @@ void NetServer::ClientData::parse_received_messages(NetServer& server) { } } +void NetServer::ClientData::parse_multi_command_id(NetServer& server, cereal::PortableBinaryInputArchive& a) { + std::vector commands; + a(commands); + for(const std::string& str : commands) { + ByteMemStream strm((char*)str.data(), str.size()); + cereal::PortableBinaryInputArchive inArchive(strm); + MessageCommandType commandID; + inArchive(commandID); + server.recvCallbacks[commandID](shared_from_this(), inArchive); + } +} + NetLibrary::DownloadProgress NetServer::ClientData::get_progress_into_fragmented_message(const std::string& channel) const { auto it = pfm.find(channel); if(it == pfm.end()) diff --git a/include/Helpers/Networking/NetServer.hpp b/include/Helpers/Networking/NetServer.hpp index 741fba1..6e4818e 100644 --- a/include/Helpers/Networking/NetServer.hpp +++ b/include/Helpers/Networking/NetServer.hpp @@ -60,6 +60,7 @@ class NetServer : public std::enable_shared_from_this { void send_queued_messages(NetServer& server); void parse_received_messages(NetServer& server); + void parse_multi_command_id(NetServer& server, cereal::PortableBinaryInputArchive& a); void send_str_as_bytes(std::shared_ptr channel, const std::string& str); NetLibrary::DownloadProgress get_progress_into_fragmented_message(const std::string& channel) const; @@ -98,6 +99,7 @@ class NetServer : public std::enable_shared_from_this { void send_string_stream_to_all_clients(const std::string& channel, const std::shared_ptr& ss); void send_string_stream_to_all_clients_except(const std::shared_ptr& client, const std::string& channel, const std::shared_ptr& ss); void send_string_stream_to_client_if(std::function&)> clientChecker, const std::string& channel, const std::shared_ptr& ss); + void send_multi_command_to_all_clients(const std::string& channel, const std::function& captureSendBlock); bool is_disconnected() const; @@ -127,6 +129,12 @@ class NetServer : public std::enable_shared_from_this { NetClient* directConnectClient = nullptr; std::shared_ptr directConnectClientData; + struct MultiCommandData { + std::string channelToSendTo; + std::vector commands; + }; + std::weak_ptr multiCommandData; + friend class NetLibrary; friend class NetClient; }; diff --git a/include/Helpers/NetworkingObjects/NetObjManager.cpp b/include/Helpers/NetworkingObjects/NetObjManager.cpp index 26aaa8d..aaf3b9a 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.cpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.cpp @@ -35,24 +35,13 @@ namespace NetworkingObjects { return; typeList.get_net_type_data(isServer, it->second.netTypeID).readUpdateFunc(NetObjTemporaryPtr(this, id, it->second.p), a, clientReceivedFrom); } - void NetObjManager::read_many_update_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr& clientReceivedFrom) { - for(;;) { - bool objExists; - a(objExists); - if(!objExists) - break; - read_update_message(a, clientReceivedFrom); - } - } - void NetObjManager::set_client(std::shared_ptr initClient, MessageCommandType initUpdateCommandID, MessageCommandType initMultiUpdateCommandID) { + void NetObjManager::set_client(std::shared_ptr initClient, MessageCommandType initUpdateCommandID) { client = initClient; updateCommandID = initUpdateCommandID; - multiUpdateCommandID = initMultiUpdateCommandID; } - void NetObjManager::set_server(std::shared_ptr initServer, MessageCommandType initUpdateCommandID, MessageCommandType initMultiUpdateCommandID) { + void NetObjManager::set_server(std::shared_ptr initServer, MessageCommandType initUpdateCommandID) { server = initServer; updateCommandID = initUpdateCommandID; - multiUpdateCommandID = initMultiUpdateCommandID; } void NetObjManager::disconnect() { server = nullptr; @@ -67,23 +56,6 @@ namespace NetworkingObjects { void NetObjManager::set_netobj_destroy_callback(const std::function& newDestroyCallback) { destroyCallback = newDestroyCallback; } - void NetObjManager::send_multi_update_messsage(std::function captureSendBlock, SendUpdateType updateType, const std::shared_ptr& specificClient) { - if(is_connected() && multiUpdateData.expired()) { // Check for multiUpdateData.expired() to make sure we aren't overriding a previous call to send_multi_update_messsage - std::shared_ptr d = std::make_shared(); - d->ss = std::make_shared(std::ios::binary | std::ios::out); - d->outArchive = std::make_unique(*d->ss); - (*d->outArchive)(multiUpdateCommandID); - multiUpdateData = d; // Using weak pointer here ensures that object will be freed - captureSendBlock(); - if(!d->channelToSendTo.empty()) { - (*d->outArchive)(false); - d->outArchive = nullptr; // Destroy output archive to finalize serialization - send_update_data_by_type(d->channelToSendTo, d->ss, updateType, specificClient); - } - } - else - captureSendBlock(); - } void NetObjManager::send_update_data_by_type(const std::string& channel, const std::shared_ptr& ss, SendUpdateType updateType, const std::shared_ptr& specificClient) { if(client && updateType != SendUpdateType::SEND_TO_ALL) diff --git a/include/Helpers/NetworkingObjects/NetObjManager.hpp b/include/Helpers/NetworkingObjects/NetObjManager.hpp index 3af9b0e..a798c15 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.hpp @@ -40,8 +40,8 @@ namespace NetworkingObjects { NetObjManager(bool initIsServer); void read_update_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr& clientReceivedFrom); void read_many_update_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr& clientReceivedFrom); - void set_client(std::shared_ptr initClient, MessageCommandType initUpdateCommandID, MessageCommandType initMultiUpdateCommandID); - void set_server(std::shared_ptr initServer, MessageCommandType initUpdateCommandID, MessageCommandType initMultiUpdateCommandID); + void set_client(std::shared_ptr initClient, MessageCommandType initUpdateCommandID); + void set_server(std::shared_ptr initServer, MessageCommandType initUpdateCommandID); void disconnect(); bool is_server() const; bool is_connected() const; @@ -71,7 +71,6 @@ namespace NetworkingObjects { SEND_TO_ALL_EXCEPT, SEND_TO_SPECIFIC_CLIENT }; - void send_multi_update_messsage(std::function captureSendBlock, SendUpdateType updateType, const std::shared_ptr& specificClient); // NOTE: DO NOT USE THESE FUNCTIONS UNLESS SITUATION ISN'T NORMAL, EVERY OBJECT SHOULD HAVE A UNIQUE ID AND IDS SHOULDNT BE REUSED UNDER ANY CIRCUMSTANCES template NetObjOwnerPtr make_obj_with_specific_id(const NetObjID& id) { @@ -117,49 +116,40 @@ namespace NetworkingObjects { } template static void send_client_update(const NetObjTemporaryPtr& ptr, const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) { - auto ss = send_update_general_check_for_multi_update(channel, ptr, sendUpdateFunc); + auto ss = send_update_general(channel, ptr, sendUpdateFunc); if(ss) ptr.get_obj_man()->client->send_string_stream_to_server(channel, ss); } template static void send_server_update_to_client(const NetObjTemporaryPtr& ptr, const std::shared_ptr& clientToSendTo, const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) { if(clientToSendTo) { - auto ss = send_update_general_check_for_multi_update(channel, ptr, sendUpdateFunc); + auto ss = send_update_general(channel, ptr, sendUpdateFunc); if(ss) ptr.get_obj_man()->server->send_string_stream_to_client(clientToSendTo, channel, ss); } } template static void send_server_update_to_all_clients_except(const NetObjTemporaryPtr& ptr, const std::shared_ptr& clientToNotSendTo, const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) { - auto ss = send_update_general_check_for_multi_update(channel, ptr, sendUpdateFunc); + auto ss = send_update_general(channel, ptr, sendUpdateFunc); if(ss) ptr.get_obj_man()->server->send_string_stream_to_all_clients_except(clientToNotSendTo, channel, ss); } template static void send_server_update_to_all_clients(const NetObjTemporaryPtr& ptr, const std::string& channel, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) { - auto ss = send_update_general_check_for_multi_update(channel, ptr, sendUpdateFunc); + auto ss = send_update_general(channel, ptr, sendUpdateFunc); if(ss) ptr.get_obj_man()->server->send_string_stream_to_all_clients(channel, ss); } - template static std::shared_ptr send_update_general_check_for_multi_update(const std::string& channel, const NetObjTemporaryPtr& ptr, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) { + template static std::shared_ptr send_update_general(const std::string& channel, const NetObjTemporaryPtr& ptr, std::function&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) { if(ptr.get_obj_man()->is_connected()) { - std::shared_ptr mData = ptr.get_obj_man()->multiUpdateData.lock(); - if(mData) { - mData->channelToSendTo = channel; - (*mData->outArchive)(true, ptr.get_net_id()); - sendUpdateFunc(ptr, *mData->outArchive); - return nullptr; - } - else { - auto ss(std::make_shared(std::ios::binary | std::ios::out)); - { - cereal::PortableBinaryOutputArchive m(*ss); - m(ptr.get_obj_man()->updateCommandID, ptr.get_net_id()); - sendUpdateFunc(ptr, m); - } - return ss; + auto ss(std::make_shared(std::ios::binary | std::ios::out)); + { + cereal::PortableBinaryOutputArchive m(*ss); + m(ptr.get_obj_man()->updateCommandID, ptr.get_net_id()); + sendUpdateFunc(ptr, m); } + return ss; } return nullptr; } @@ -178,18 +168,10 @@ namespace NetworkingObjects { void* p; }; - struct MultiUpdateData { - std::string channelToSendTo; - std::shared_ptr ss; - std::unique_ptr outArchive; - }; - std::weak_ptr multiUpdateData; - bool isServer; std::shared_ptr client; std::shared_ptr server; MessageCommandType updateCommandID; - MessageCommandType multiUpdateCommandID; std::unordered_map objectData; NetObjManagerTypeList typeList; NetTypeIDType nextTypeID; diff --git a/src/CommandList.hpp b/src/CommandList.hpp index 38b04cf..3932a86 100644 --- a/src/CommandList.hpp +++ b/src/CommandList.hpp @@ -22,10 +22,10 @@ enum ServerCommands : MessageCommandType { SERVER_FRAGMENT = 0, + SERVER_MULTI_COMMAND = 1, SERVER_KEEP_ALIVE, SERVER_INITIAL_DATA, SERVER_UPDATE_NETWORK_OBJECT, - SERVER_UPDATE_MANY_NETWORK_OBJECTS, SERVER_NEW_RESOURCE_ID, SERVER_NEW_RESOURCE_DATA, SERVER_TRANSFORM_MANY_COMPONENTS @@ -33,10 +33,10 @@ enum ServerCommands : MessageCommandType { enum ClientCommands : MessageCommandType { CLIENT_FRAGMENT = 0, + CLIENT_MULTI_COMMAND = 1, CLIENT_KEEP_ALIVE, CLIENT_INITIAL_DATA, CLIENT_UPDATE_NETWORK_OBJECT, - CLIENT_UPDATE_MANY_NETWORK_OBJECTS, CLIENT_NEW_RESOURCE_ID, CLIENT_NEW_RESOURCE_DATA, CLIENT_TRANSFORM_MANY_COMPONENTS diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp index c31de99..fd26b9d 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp @@ -127,7 +127,7 @@ void DrawingProgramLayerManager::push_components_to(const std::vector> toEraseMap; std::vector> toInsertObjPtrs; @@ -168,7 +168,7 @@ void DrawingProgramLayerManager::push_components_to(const std::vectorobj->objInfo); } commitMoveOnLayer(); - }, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); + }); class MoveComponentsUndoAction : public WorldUndoAction { public: @@ -376,12 +376,12 @@ void DrawingProgramLayerManager::add_undo_place_component(CanvasComponentContain void DrawingProgramLayerManager::erase_component_map(const std::unordered_map>& eraseMap, bool newUndo) { add_undo_erase_components(eraseMap, newUndo); - drawP.world.netObjMan.send_multi_update_messsage([&]() { + drawP.world.send_reliable_multi_command_to_all([&]() { for(auto& [layerListItem, netObjSetToErase] : eraseMap) { auto& layerComponentList = layerListItem->get_layer().components; layerComponentList->erase_list(layerComponentList, netObjSetToErase); } - }, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); + }); } void DrawingProgramLayerManager::add_undo_erase_components(const std::unordered_map>& eraseMap, bool newUndo) { diff --git a/src/DrawingProgram/Tools/BrushTool.cpp b/src/DrawingProgram/Tools/BrushTool.cpp index e4c0a2a..b367d2f 100644 --- a/src/DrawingProgram/Tools/BrushTool.cpp +++ b/src/DrawingProgram/Tools/BrushTool.cpp @@ -23,6 +23,7 @@ #include "../../MainProgram.hpp" #include "DrawingProgramToolBase.hpp" #include "../../CanvasComponents/MeshCanvasComponent.hpp" +#include "Helpers/Networking/NetLibrary.hpp" #include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp" #include "../../CanvasComponents/CanvasComponentContainer.hpp" #include "../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp" @@ -85,10 +86,10 @@ void BrushTool::commit_data(bool final) { } containerPtr->commit_update(drawP); if(final) { - drawP.world.netObjMan.send_multi_update_messsage([&]() { + drawP.world.send_reliable_multi_command_to_all([&]() { drawP.send_transforms_for({objInfoBeingEdited}); - containerPtr->send_comp_update(drawP, final); - }, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); + containerPtr->send_comp_update(drawP, true); + }); } else containerPtr->send_comp_update(drawP, final); diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index 80c1a7e..b5f0106 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -242,7 +242,7 @@ void EraserTool::commit_erase() { return false; }); - drawP.world.netObjMan.send_multi_update_messsage([&]() { + drawP.world.send_reliable_multi_command_to_all([&]() { bool firstPlacement = true; for(auto& [layer, compMap] : newObjectsToPlace) { layer->get_layer().components->sort_netobj_ordered_list_iterator_insert_list(layer->get_layer().components, compMap); @@ -269,7 +269,7 @@ void EraserTool::commit_erase() { else drawP.world.undo.push_on_last(std::make_unique(std::move(oldData.copyData->obj), oldData.copyData->coords, drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id()))); } - }, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); + }); erasedComponents.clear(); updatedComponents.clear(); } diff --git a/src/DrawingProgram/Tools/LineDrawTool.cpp b/src/DrawingProgram/Tools/LineDrawTool.cpp index 20787d3..1314d36 100644 --- a/src/DrawingProgram/Tools/LineDrawTool.cpp +++ b/src/DrawingProgram/Tools/LineDrawTool.cpp @@ -59,10 +59,10 @@ void LineDrawTool::commit_data(bool final) { } containerPtr->commit_update(drawP); if(final) { - drawP.world.netObjMan.send_multi_update_messsage([&]() { + drawP.world.send_reliable_multi_command_to_all([&]() { drawP.send_transforms_for({objInfoBeingEdited}); containerPtr->send_comp_update(drawP, final); - }, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); + }); } else containerPtr->send_comp_update(drawP, final); diff --git a/src/World.cpp b/src/World.cpp index 2b841f8..5f1a0a1 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -149,7 +149,7 @@ void World::init_client(const std::string& serverFullID) { netClient = std::make_shared(serverFullID); lastKeepAliveSent = std::chrono::steady_clock::now(); NetLibrary::register_client(netClient); - netObjMan.set_client(netClient, SERVER_UPDATE_NETWORK_OBJECT, SERVER_UPDATE_MANY_NETWORK_OBJECTS); + netObjMan.set_client(netClient, SERVER_UPDATE_NETWORK_OBJECT); set_name(""); rMan.init_client_callbacks(); @@ -179,15 +179,21 @@ void World::init_client(const std::string& serverFullID) { netClient->add_recv_callback(CLIENT_UPDATE_NETWORK_OBJECT, [&](cereal::PortableBinaryInputArchive& message) { netObjMan.read_update_message(message, nullptr); }); - netClient->add_recv_callback(CLIENT_UPDATE_MANY_NETWORK_OBJECTS, [&](cereal::PortableBinaryInputArchive& message) { - netObjMan.read_many_update_message(message, nullptr); - }); netClient->add_recv_callback(CLIENT_KEEP_ALIVE, [&](cereal::PortableBinaryInputArchive& message) { }); netClient->send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, main.conf.displayName); } +void World::send_reliable_multi_command_to_all(const std::function& captureSendBlock) { + if(netServer) + netServer->send_multi_command_to_all_clients(RELIABLE_COMMAND_CHANNEL, captureSendBlock); + else if(netClient) + netClient->send_multi_command_to_server(RELIABLE_COMMAND_CHANNEL, captureSendBlock); + else + captureSendBlock(); +} + void World::focus_update() { if(!clientStillConnecting) { delayedUpdateObjectManager.update(netObjMan); @@ -417,7 +423,7 @@ void World::start_hosting(const std::string& initNetSource, const std::string& s netServer = std::make_shared(serverLocalID); lastKeepAliveSent = std::chrono::steady_clock::now(); NetLibrary::register_server(netServer); - netObjMan.set_server(netServer, CLIENT_UPDATE_NETWORK_OBJECT, CLIENT_UPDATE_MANY_NETWORK_OBJECTS); + netObjMan.set_server(netServer, CLIENT_UPDATE_NETWORK_OBJECT); netSource = initNetSource; rMan.init_server_callbacks(); drawProg.init_server_callbacks(); @@ -455,9 +461,6 @@ void World::start_hosting(const std::string& initNetSource, const std::string& s netServer->add_recv_callback(SERVER_UPDATE_NETWORK_OBJECT, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { netObjMan.read_update_message(message, client); }); - netServer->add_recv_callback(SERVER_UPDATE_MANY_NETWORK_OBJECTS, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { - netObjMan.read_many_update_message(message, client); - }); netServer->add_recv_callback(SERVER_KEEP_ALIVE, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { }); netServer->add_disconnect_callback([&](std::shared_ptr client) { diff --git a/src/World.hpp b/src/World.hpp index b73eee8..7529471 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -106,6 +106,7 @@ class World { void set_has_unsaved_local_changes(bool newHasUnsavedLocalChangesVal); bool is_focus(); void set_to_layout_gui_if_focus(); + void send_reliable_multi_command_to_all(const std::function& captureSendBlock); NetworkingObjects::DelayUpdateSerializedClassManager delayedUpdateObjectManager; diff --git a/src/WorldUndoManager.cpp b/src/WorldUndoManager.cpp index cfd13d2..999880c 100644 --- a/src/WorldUndoManager.cpp +++ b/src/WorldUndoManager.cpp @@ -76,14 +76,14 @@ void WorldUndoManager::undo() { bool undoFail = false; - world.netObjMan.send_multi_update_messsage([&]() { + world.send_reliable_multi_command_to_all([&]() { for(auto& u : std::views::reverse(undoQueue.back())) { if(!u->undo(*this)) { undoFail = true; break; } } - }, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); + }); if(undoFail) { clear(); @@ -106,14 +106,14 @@ void WorldUndoManager::redo() { world.bMan.refresh_gui_data(); bool redoFail = false; - world.netObjMan.send_multi_update_messsage([&]() { + world.send_reliable_multi_command_to_all([&]() { for(auto& u : redoQueue.back()) { if(!u->redo(*this)) { redoFail = true; break; } } - }, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); + }); if(redoFail) { clear();