diff --git a/src/game.c b/src/game.c index f0fb5946fa..c291516456 100644 --- a/src/game.c +++ b/src/game.c @@ -310,6 +310,7 @@ void game_update() void game_logic_update() { + network_update(); if (gNetworkStatus == NETWORK_CLIENT) { if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) == gNetworkServerTick) { return; @@ -403,24 +404,6 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * int cost, flags, insufficientFunds; int original_ebx, original_edx, original_esi, original_edi, original_ebp; - int sendPacket = 0; - if (gNetworkStatus == NETWORK_CLIENT) { - if (command & (1 << 31)) { - command &= ~(1 << 31); - } else { - sendPacket = 1; - } - } else if (gNetworkStatus == NETWORK_SERVER) { - sendPacket = 1; - } - - if (sendPacket) { - network_send_gamecmd((uint32)command, (uint32)*eax, (uint32)*ebx, (uint32)*ecx, (uint32)*edx, (uint32)*esi, (uint32)*edi, (uint32)*ebp); - - if (gNetworkStatus == NETWORK_CLIENT) - return MONEY32_UNDEFINED; - } - *esi = command; original_ebx = *ebx; original_edx = *edx; @@ -457,12 +440,21 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * *edi = original_edi; *ebp = original_ebp; - if (!(flags & 1)) { + if (!(flags & GAME_COMMAND_FLAG_APPLY)) { // Decrement nest count RCT2_GLOBAL(0x009A8C28, uint8)--; return cost; } + if (gNetworkStatus != NETWORK_NONE && !(flags & (1 << 31)) && RCT2_GLOBAL(0x009A8C28, uint8) == 1) { + network_send_gamecmd(*eax, *ebx, *ecx, *edx, *esi, *edi, *ebp); + if (gNetworkStatus == NETWORK_CLIENT) { + // Decrement nest count + RCT2_GLOBAL(0x009A8C28, uint8)--; + return cost; + } + } + // Secondary command if (game_do_command_table[command] == 0) { new_game_command_table[command](eax, ebx, ecx, edx, esi, edi, ebp); diff --git a/src/network/network.cpp b/src/network/network.cpp index 2c9add27e3..f3db7eaab8 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -21,6 +21,7 @@ #ifndef DISABLE_NETWORK #include +#include extern "C" { #include "../addresses.h" #include "../common.h" @@ -40,6 +41,16 @@ int gNetworkStartPort = NETWORK_DEFAULT_PORT; int gNetworkStatus = NETWORK_NONE; uint32 gNetworkServerTick = 0; +struct GameCommand +{ + GameCommand(uint32 args[8]) { tick = args[0], eax = args[1], ebx = args[2], ecx = args[3], edx = args[4], esi = args[5], edi = args[6], ebp = args[7]; }; + uint32 tick; + uint32 eax, ebx, ecx, edx, esi, edi, ebp; + bool operator<(const GameCommand& comp) const { + return tick < comp.tick; + } +}; + static network_packet* _packetQueue = NULL; static int _wsaInitialised = 0; static WSADATA _wsaData; @@ -50,6 +61,7 @@ static network_packet _inboundPacket; static std::vector _chunkBuffer; static NetworkConnection _serverConnection; static std::list> _clientConnectionList; +static std::multiset _gameCommandQueue; static void network_process_packet(NetworkPacket& packet); static int network_send_packet(network_packet *packet); @@ -77,6 +89,12 @@ uint8* NetworkPacket::GetData() return &(*data)[0]; } +void NetworkPacket::Clear() +{ + read = 0; + data->clear(); +} + int NetworkConnection::ReadPacket() { if (inboundpacket.read < sizeof(inboundpacket.size)) { @@ -325,6 +343,18 @@ int network_process_connection(NetworkConnection& networkconnection) return 1; } +void network_process_gamecmdqueue() +{ + while (_gameCommandQueue.begin() != _gameCommandQueue.end() && _gameCommandQueue.begin()->tick < RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32)) { + _gameCommandQueue.erase(_gameCommandQueue.begin()); + } + while (_gameCommandQueue.begin() != _gameCommandQueue.end() && _gameCommandQueue.begin()->tick == RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32)) { + const GameCommand& gc = (*_gameCommandQueue.begin()); + game_do_command(gc.eax, gc.ebx, gc.ecx, gc.edx, gc.esi, gc.edi, gc.ebp); + _gameCommandQueue.erase(_gameCommandQueue.begin()); + } +} + void network_update() { static uint32 lastTickUpdate = 0; @@ -335,14 +365,18 @@ void network_update() if (gNetworkStatus == NETWORK_CLIENT) { network_process_connection(_serverConnection); + network_process_gamecmdqueue(); } else { - for(auto it = _clientConnectionList.begin(); it != _clientConnectionList.end(); it++) { + auto it = _clientConnectionList.begin(); + while(it != _clientConnectionList.end()) { if (!network_process_connection(*(*it))) { network_remove_client((*it)); it = _clientConnectionList.begin(); + } else { + it++; } } - if (SDL_GetTicks() - lastTickUpdate >= 100) { + if (SDL_GetTicks() - lastTickUpdate >= 25) { lastTickUpdate = SDL_GetTicks(); network_send_tick(); } @@ -410,17 +444,19 @@ static void network_process_packet(NetworkPacket& packet) news_item_add_to_queue_custom(&newsItem); }break; case NETWORK_COMMAND_GAMECMD:{ - if (gNetworkStatus == NETWORK_CLIENT) - args[1] |= (1 << 31); - - game_do_command_p(args[1], (int*)&args[2], (int*)&args[3], (int*)&args[4], (int*)&args[5], (int*)&args[6], (int*)&args[7], (int*)&args[8]); + if (gNetworkStatus == NETWORK_SERVER) { + network_send_gamecmd(args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + game_do_command(args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + } else { + GameCommand gc = GameCommand(&args[1]); + _gameCommandQueue.insert(gc); + } }break; case NETWORK_COMMAND_TICK:{ gNetworkServerTick = args[1]; }break; } - packet.read = 0; - packet.data->clear(); + packet.Clear(); } void network_send_tick() @@ -472,13 +508,13 @@ void network_send_chat(const char* text) } } -void network_send_gamecmd(uint32 command, uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) +void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { std::unique_ptr packet = NetworkPacket::AllocatePacket(); packet->Write((uint32)NETWORK_COMMAND_GAMECMD); - packet->Write((uint32)command); + packet->Write((uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32)); packet->Write((uint32)eax); - packet->Write((uint32)ebx); + packet->Write((uint32)ebx | (1 << 31)); packet->Write((uint32)ecx); packet->Write((uint32)edx); packet->Write((uint32)esi); diff --git a/src/network/network.h b/src/network/network.h index 05c12a7cd2..d2f1d67837 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -41,6 +41,7 @@ public: template void Write(T value) { uint8* bytes = (uint8*)&value; data->insert(data->end(), bytes, bytes + sizeof(value)); } void Write(uint8* bytes, unsigned int size) { data->insert(data->end(), bytes, bytes + size); } + void Clear(); uint16 size; std::shared_ptr> data; @@ -115,7 +116,7 @@ void network_update(); void network_send_tick(); void network_send_map(); void network_send_chat(const char* text); -void network_send_gamecmd(uint32 command, uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); +void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); void network_print_error(); diff --git a/src/openrct2.c b/src/openrct2.c index 29bcbb28e8..1a6f283797 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -383,7 +383,6 @@ static void openrct2_loop() lastTick = currentTick; platform_process_messages(); - network_update(); rct2_update();