diff --git a/src/openrct2/actions/GameAction.cpp b/src/openrct2/actions/GameAction.cpp index 0c0a57d852..2ec2a0e036 100644 --- a/src/openrct2/actions/GameAction.cpp +++ b/src/openrct2/actions/GameAction.cpp @@ -52,8 +52,21 @@ namespace GameActions return factory; } + void Initialize() + { + static bool initialized = false; + if (initialized) + return; + + Register(); + + initialized = true; + } + IGameAction * Create(uint32 id) { + Initialize(); + IGameAction * result = nullptr; if (id < Util::CountOf(_actions)) { @@ -109,10 +122,8 @@ namespace GameActions return result; } - GameActionResult Execute(IGameAction * action) + GameActionResult Execute(const IGameAction * action) { - log_info("[%s] GameAction::Execute\n", network_get_mode() == NETWORK_MODE_CLIENT ? "cl" : "sv"); - Guard::ArgumentNotNull(action); uint16 actionFlags = action->GetActionFlags(); @@ -127,6 +138,8 @@ namespace GameActions // As a client we have to wait or send it first. if (!(actionFlags & GA_FLAGS::CLIENT_ONLY) && !(flags & GAME_COMMAND_FLAG_GHOST) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) { + log_info("[%s] GameAction::Execute\n", "cl"); + network_send_game_action(action); return result; @@ -138,12 +151,15 @@ namespace GameActions // at the beginning of the frame, so we have to put them into the queue. if (!(actionFlags & GA_FLAGS::CLIENT_ONLY) && !(flags & GAME_COMMAND_FLAG_GHOST) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) { + log_info("[%s] GameAction::Execute\n", "sv-cl"); network_enqueue_game_action(action); return result; } } + log_info("[%s] GameAction::Execute\n", "sv"); + // Execute the action, changing the game state result = action->Execute(); @@ -174,12 +190,11 @@ namespace GameActions } // Call callback for asynchronous events - /* - if (callback != nullptr) + const std::function& cb = action->GetCallback(); + if (cb) { - callback(result); + cb(); } - */ if (result.Error != GA_ERROR::OK && !(flags & GAME_COMMAND_FLAG_GHOST)) { diff --git a/src/openrct2/actions/GameAction.h b/src/openrct2/actions/GameAction.h index ddd7f289a2..dc4b71fa41 100644 --- a/src/openrct2/actions/GameAction.h +++ b/src/openrct2/actions/GameAction.h @@ -16,6 +16,10 @@ #pragma once +extern "C" { +#include "../platform/platform.h" +} + #include "IGameAction.h" typedef IGameAction *(*GameActionFactory)(); @@ -31,9 +35,11 @@ public: private: uint32 _playerId; // Callee uint32 _flags; // GAME_COMMAND_FLAGS + uint32 _networkId; + std::function _callback; public: - GameAction() : _playerId(0), _flags(0) + GameAction() : _playerId(0), _flags(0), _networkId(0) { } @@ -73,8 +79,29 @@ public: return Type; } + virtual void SetCallback(const std::function& cb) + { + _callback = cb; + } + + virtual const std::function& GetCallback() const + { + return _callback; + } + + virtual void SetNetworkId(uint32_t id) + { + _networkId = id; + } + + virtual uint32 GetNetworkId() const + { + return _networkId; + } + virtual void Serialise(DataSerialiser& stream) { + stream << _networkId; stream << _flags; stream << _playerId; } @@ -92,10 +119,13 @@ public: namespace GameActions { -GameActionFactory Register(uint32 id, GameActionFactory action); +void Initialize(); +void Register(); IGameAction * Create(uint32 id); GameActionResult Query(const IGameAction * action); -GameActionResult Execute(IGameAction * action); +GameActionResult Execute(const IGameAction * action); + +GameActionFactory Register(uint32 id, GameActionFactory action); template static GameActionFactory Register() diff --git a/src/openrct2/actions/GameActionCompat.cpp b/src/openrct2/actions/GameActionCompat.cpp new file mode 100644 index 0000000000..57552988a1 --- /dev/null +++ b/src/openrct2/actions/GameActionCompat.cpp @@ -0,0 +1,87 @@ +#include "PlaceParkEntranceAction.hpp" +#include "SetParkEntranceFeeAction.hpp" + +extern "C" +{ +#pragma region PlaceParkEntranceAction + money32 place_park_entrance(sint16 x, sint16 y, sint16 z, uint8 direction) + { + auto gameAction = PlaceParkEntranceAction(); + gameAction.x = x; + gameAction.y = y; + gameAction.z = z; + gameAction.direction = direction; + auto result = GameActions::Execute(&gameAction); + if (result.Error == GA_ERROR::OK) + { + return 0; + } + else + { + return MONEY32_UNDEFINED; + } + } + + /** + * + * rct2: 0x006666E7 + */ + void game_command_place_park_entrance(sint32* eax, + sint32* ebx, + sint32* ecx, + sint32* edx, + sint32* esi, + sint32* edi, + sint32* ebp) + { + Guard::Assert(false, "GAME_COMMAND_PLACE_PARK_ENTRANCE DEPRECIATED"); + } + + /** + * + * rct2: 0x00666F4E + */ + money32 park_entrance_place_ghost(sint32 x, sint32 y, sint32 z, sint32 direction) + { + park_entrance_remove_ghost(); + + auto gameAction = PlaceParkEntranceAction(); + gameAction.x = x; + gameAction.y = y; + gameAction.z = z; + gameAction.direction = direction; + gameAction.SetFlags(GAME_COMMAND_FLAG_GHOST); + + auto result = GameActions::Execute(&gameAction); + if (result.Error == GA_ERROR::OK) + { + gParkEntranceGhostPosition.x = x; + gParkEntranceGhostPosition.y = y; + gParkEntranceGhostPosition.z = z; + gParkEntranceGhostDirection = direction; + gParkEntranceGhostExists = true; + } + return result.Cost; + } +#pragma endregion + +#pragma region SetParkEntranceFeeAction + void park_set_entrance_fee(money32 value) + { + auto gameAction = SetParkEntranceFeeAction(); + gameAction.Fee = (money16)value; + gameAction.SetCallback([]() + { + log_info("GameAction Callback executed"); + }); + GameActions::Execute(&gameAction); + } + + void game_command_set_park_entrance_fee(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) + { + auto gameAction = SetParkEntranceFeeAction(); + gameAction.Fee = (*edi & 0xFFFF); + GameActions::Execute(&gameAction); + } +#pragma endregion +} diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp new file mode 100644 index 0000000000..f1b196f3de --- /dev/null +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -0,0 +1,13 @@ +#include "GameAction.h" +#include "PlaceParkEntranceAction.hpp" +#include "SetParkEntranceFeeAction.hpp" + +namespace GameActions { + +void Register() +{ + Register(); + Register(); +} + +} \ No newline at end of file diff --git a/src/openrct2/actions/IGameAction.h b/src/openrct2/actions/IGameAction.h index 153afe7b65..16137ae8e6 100644 --- a/src/openrct2/actions/IGameAction.h +++ b/src/openrct2/actions/IGameAction.h @@ -101,6 +101,12 @@ public: virtual void SetPlayer(uint32 playerId) abstract; virtual uint32 GetPlayer() const abstract; + virtual void SetCallback(const std::function& cb) abstract; + virtual const std::function& GetCallback() const abstract; + + virtual void SetNetworkId(uint32_t id) abstract; + virtual uint32 GetNetworkId() const abstract; + /** * Writes or reads the game action directly to the given stream. Used for * sending across the network in multiplayer. diff --git a/src/openrct2/actions/PlaceParkEntranceAction.cpp b/src/openrct2/actions/PlaceParkEntranceAction.hpp similarity index 81% rename from src/openrct2/actions/PlaceParkEntranceAction.cpp rename to src/openrct2/actions/PlaceParkEntranceAction.hpp index 99badbfed1..b12ef50027 100644 --- a/src/openrct2/actions/PlaceParkEntranceAction.cpp +++ b/src/openrct2/actions/PlaceParkEntranceAction.hpp @@ -18,6 +18,8 @@ #include "../localisation/string_ids.h" #include "GameAction.h" +#pragma once + extern "C" { #include "../cheats.h" @@ -203,68 +205,3 @@ public: return GameActionResult(); } }; - -static auto Factory UNUSED_ATTR = GameActions::Register(); - -extern "C" -{ - money32 place_park_entrance(sint16 x, sint16 y, sint16 z, uint8 direction) - { - auto gameAction = PlaceParkEntranceAction(); - gameAction.x = x; - gameAction.y = y; - gameAction.z = z; - gameAction.direction = direction; - auto result = GameActions::Execute(&gameAction); - if (result.Error == GA_ERROR::OK) - { - return 0; - } - else - { - return MONEY32_UNDEFINED; - } - } - - /** - * - * rct2: 0x006666E7 - */ - void game_command_place_park_entrance(sint32* eax, - sint32* ebx, - sint32* ecx, - sint32* edx, - sint32* esi, - sint32* edi, - sint32* ebp) - { - Guard::Assert(false, "GAME_COMMAND_PLACE_PARK_ENTRANCE DEPRECIATED"); - } - - /** - * - * rct2: 0x00666F4E - */ - money32 park_entrance_place_ghost(sint32 x, sint32 y, sint32 z, sint32 direction) - { - park_entrance_remove_ghost(); - - auto gameAction = PlaceParkEntranceAction(); - gameAction.x = x; - gameAction.y = y; - gameAction.z = z; - gameAction.direction = direction; - gameAction.SetFlags(GAME_COMMAND_FLAG_GHOST); - - auto result = GameActions::Execute(&gameAction); - if (result.Error == GA_ERROR::OK) - { - gParkEntranceGhostPosition.x = x; - gParkEntranceGhostPosition.y = y; - gParkEntranceGhostPosition.z = z; - gParkEntranceGhostDirection = direction; - gParkEntranceGhostExists = true; - } - return result.Cost; - } -} diff --git a/src/openrct2/actions/SetParkEntranceFeeAction.cpp b/src/openrct2/actions/SetParkEntranceFeeAction.hpp similarity index 77% rename from src/openrct2/actions/SetParkEntranceFeeAction.cpp rename to src/openrct2/actions/SetParkEntranceFeeAction.hpp index f6bd328b2e..52751b34fc 100644 --- a/src/openrct2/actions/SetParkEntranceFeeAction.cpp +++ b/src/openrct2/actions/SetParkEntranceFeeAction.hpp @@ -14,6 +14,8 @@ *****************************************************************************/ #pragma endregion +#pragma once + #include "../core/MemoryStream.h" #include "../localisation/string_ids.h" #include "GameAction.h" @@ -58,21 +60,3 @@ public: } }; -static auto Factory UNUSED_ATTR = GameActions::Register(); - -extern "C" -{ - void park_set_entrance_fee(money32 value) - { - auto gameAction = SetParkEntranceFeeAction(); - gameAction.Fee = (money16)value; - GameActions::Execute(&gameAction); - } - - void game_command_set_park_entrance_fee(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) - { - auto gameAction = SetParkEntranceFeeAction(); - gameAction.Fee = (*edi & 0xFFFF); - GameActions::Execute(&gameAction); - } -} diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index 5de2cc4edd..1cfc3cadc4 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -94,7 +94,8 @@ Network::Network() status = NETWORK_STATUS_NONE; last_tick_sent_time = 0; last_ping_sent_time = 0; - _commandIndex = 0; + _commandId = 0; + _actionId = 0; client_command_handlers.resize(NETWORK_COMMAND_MAX, 0); client_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Client_Handle_AUTH; client_command_handlers[NETWORK_COMMAND_MAP] = &Network::Client_Handle_MAP; @@ -1151,6 +1152,16 @@ void Network::Client_Send_GAME_ACTION(const IGameAction *action) { std::unique_ptr packet(NetworkPacket::Allocate()); + uint32_t networkId = 0; + networkId = ++_actionId; + + // I know its ugly, want basic functionality for now. + const_cast(action)->SetNetworkId(networkId); + if(action->GetCallback()) + { + _gameActionCallbacks.insert(std::make_pair(networkId, action->GetCallback())); + } + DataSerialiser stream(true); action->Serialise(stream); @@ -1472,12 +1483,14 @@ void Network::EnqueueGameAction(const IGameAction *action) action->Serialise(dsOut); IGameAction *ga = GameActions::Create(action->GetType()); + ga->SetCallback(action->GetCallback()); + stream.SetPosition(0); DataSerialiser dsIn(false, stream); ga->Serialise(dsIn); GameCommand gc(gCurrentTicks, ga); - gc.commandIndex = _commandIndex++; + gc.commandIndex = _commandId++; game_command_queue.insert(gc); } @@ -2100,7 +2113,7 @@ void Network::Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket packet >> tick >> args[0] >> args[1] >> args[2] >> args[3] >> args[4] >> args[5] >> args[6] >> playerid >> callback; GameCommand gc(tick, args, playerid, callback); - gc.commandIndex = _commandIndex++; + gc.commandIndex = _commandId++; game_command_queue.insert(gc); } @@ -2124,8 +2137,16 @@ void Network::Client_Handle_GAME_ACTION(NetworkConnection& connection, NetworkPa } action->Serialise(ds); + auto itr = _gameActionCallbacks.find(action->GetNetworkId()); + if (itr != _gameActionCallbacks.end()) + { + action->SetCallback(itr->second); + + _gameActionCallbacks.erase(itr); + } + GameCommand gc(tick, action); - gc.commandIndex = _commandIndex++; + gc.commandIndex = _commandId++; game_command_queue.insert(gc); } @@ -2200,7 +2221,7 @@ void Network::Server_Handle_GAME_ACTION(NetworkConnection& connection, NetworkPa ga->SetPlayer(connection.Player->Id); GameCommand gc(tick, ga); - gc.commandIndex = _commandIndex++; + gc.commandIndex = _commandId++; game_command_queue.insert(gc); } @@ -2265,7 +2286,7 @@ void Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket } GameCommand gc = GameCommand(tick, args, playerid, callback); - gc.commandIndex = _commandIndex++; + gc.commandIndex = _commandId++; game_command_queue.insert(gc); } diff --git a/src/openrct2/network/network.h b/src/openrct2/network/network.h index bba5b51242..566fe9038c 100644 --- a/src/openrct2/network/network.h +++ b/src/openrct2/network/network.h @@ -62,6 +62,7 @@ typedef struct IGameAction IGameAction; #include #include #include +#include #include #include #include "../core/Json.hpp" @@ -168,6 +169,7 @@ public: std::vector> group_list; NetworkKey _key; std::vector _challenge; + std::map> _gameActionCallbacks; NetworkUserManager _userManager; std::string ServerName; @@ -263,7 +265,8 @@ private: uint32 server_connect_time = 0; uint8 default_group = 0; uint32 game_commands_processed_this_tick = 0; - uint32 _commandIndex; + uint32 _commandId; + uint32 _actionId; std::string _chatLogPath; std::string _chatLogFilenameFormat = "%Y%m%d-%H%M%S.txt"; std::string _serverLogPath;