From 9746bccbf6bd4650fd4d162d07bd2592de34afdd Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 15 Aug 2015 23:19:15 +0100 Subject: [PATCH] improve multiplayer --- projects/openrct2.vcxproj.user | 6 +- src/game.c | 53 ++++++------- src/network/network.cpp | 139 ++++++++++++++++++++++----------- src/network/network.h | 5 ++ src/rct2.c | 3 + 5 files changed, 129 insertions(+), 77 deletions(-) diff --git a/projects/openrct2.vcxproj.user b/projects/openrct2.vcxproj.user index 6e0ad43592..96c90432a6 100644 --- a/projects/openrct2.vcxproj.user +++ b/projects/openrct2.vcxproj.user @@ -12,7 +12,8 @@ $(TargetDir) WindowsLocalDebugger $(TargetDir)\openrct2.exe - "C:\Program Files (x86)\Infogrames\RollerCoaster Tycoon 2\Scenarios\Crazy Castle.SC6" --port 5552 --server 127.0.0.1 + + $(TargetDir) @@ -23,7 +24,6 @@ $(TargetDir)\openrct2.exe WindowsLocalDebugger $(TargetDir) - - + --server 127.0.0.1 --port 12345 \ No newline at end of file diff --git a/src/game.c b/src/game.c index 6a497edfa9..af06998e03 100644 --- a/src/game.c +++ b/src/game.c @@ -262,32 +262,39 @@ void game_update() // make sure client doesn't fall behind the server too much numUpdates += 10; } + + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) >= network_get_server_tick()) { + // dont run past the server + numUpdates = 0; + } + } else { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + numUpdates = 0; + } } // Update the game one or more times - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) { - for (i = 0; i < numUpdates; i++) { - game_logic_update(); - start_title_music(); + for (i = 0; i < numUpdates; i++) { + game_logic_update(); + start_title_music(); - if (gGameSpeed > 1) - continue; + if (gGameSpeed > 1) + continue; - // Possibly smooths viewport scrolling, I don't see a difference though - if (RCT2_GLOBAL(0x009E2D74, uint32) == 1) { - RCT2_GLOBAL(0x009E2D74, uint32) = 0; - break; - } else { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESET || - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_NORMAL - ) { - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_VIEWPORT_SCROLLING) { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING; - break; - } - } else { + // Possibly smooths viewport scrolling, I don't see a difference though + if (RCT2_GLOBAL(0x009E2D74, uint32) == 1) { + RCT2_GLOBAL(0x009E2D74, uint32) = 0; + break; + } else { + if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESET || + RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_NORMAL + ) { + if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_VIEWPORT_SCROLLING) { + RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING; break; } + } else { + break; } } } @@ -332,14 +339,6 @@ void game_update() void game_logic_update() { - network_update(); - if (network_get_mode() == NETWORK_MODE_CLIENT) { - if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) == network_get_server_tick()) { - // dont run past the server - return; - } - } - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32)++; RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, uint32)++; RCT2_GLOBAL(0x009DEA66, sint16)++; diff --git a/src/network/network.cpp b/src/network/network.cpp index f0baba10d9..ab3696eca8 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -57,6 +57,17 @@ enum { NETWORK_COMMAND_MAX }; +const char *NetworkCommandNames[] = { + "NETWORK_COMMAND_AUTH", + "NETWORK_COMMAND_MAP", + "NETWORK_COMMAND_CHAT", + "NETWORK_COMMAND_GAMECMD", + "NETWORK_COMMAND_TICK", + "NETWORK_COMMAND_PLAYERLIST", + "NETWORK_COMMAND_PING", + "NETWORK_COMMAND_PINGLIST", +}; + NetworkPacket::NetworkPacket() { transferred = 0; @@ -397,52 +408,73 @@ void Network::Update() if (GetMode() == NETWORK_MODE_NONE) return; - if (GetMode() == NETWORK_MODE_CLIENT) { - if (!ProcessConnection(server_connection)) { - Close(); + switch (GetMode()) { + case NETWORK_MODE_NONE: + return; + case NETWORK_MODE_SERVER: + UpdateServer(); + break; + case NETWORK_MODE_CLIENT: + UpdateClient(); + break; + } +} + +void Network::UpdateServer() +{ + auto it = client_connection_list.begin(); + while (it != client_connection_list.end()) { + if (!ProcessConnection(*(*it))) { + RemoveClient((*it)); + it = client_connection_list.begin(); } else { - ProcessGameCommandQueue(); + it++; } - } else - if (GetMode() == NETWORK_MODE_SERVER) { - auto it = client_connection_list.begin(); - while (it != client_connection_list.end()) { - if (!ProcessConnection(*(*it))) { - RemoveClient((*it)); - it = client_connection_list.begin(); - } else { - it++; - } + } + if (SDL_GetTicks() - last_tick_sent_time >= 25) { + last_tick_sent_time = SDL_GetTicks(); + Server_Send_TICK(); + } + if (SDL_GetTicks() - last_ping_sent_time >= 3000) { + last_ping_sent_time = SDL_GetTicks(); + Server_Send_PING(); + Server_Send_PINGLIST(); + } + SOCKET socket = accept(listening_socket, NULL, NULL); + if (socket == INVALID_SOCKET) { + if (WSAGetLastError() != WSAEWOULDBLOCK) { + PrintError(); + log_error("Failed to accept client."); } - if (SDL_GetTicks() - last_tick_sent_time >= 25) { - last_tick_sent_time = SDL_GetTicks(); - Server_Send_TICK(); - } - if (SDL_GetTicks() - last_ping_sent_time >= 3000) { - last_ping_sent_time = SDL_GetTicks(); - Server_Send_PING(); - Server_Send_PINGLIST(); - } - SOCKET socket = accept(listening_socket, NULL, NULL); - if (socket == INVALID_SOCKET) { - if (WSAGetLastError() != WSAEWOULDBLOCK) { - PrintError(); - log_error("Failed to accept client."); - } + } else { + u_long nonblocking = 1; + if (ioctlsocket(socket, FIONBIO, &nonblocking) != NO_ERROR) { + closesocket(socket); + log_error("Failed to set non-blocking mode."); } else { - u_long nonblocking = 1; - if (ioctlsocket(socket, FIONBIO, &nonblocking) != NO_ERROR) { - closesocket(socket); - log_error("Failed to set non-blocking mode."); - } else { - AddClient(socket); + AddClient(socket); + was_paused_before_client_connected = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32) != 0; + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32) == 0) { + pause_toggle(); } } } +} - if (!CheckSRAND(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32), RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32))) { - window_network_status_open("Network desync detected"); +void Network::UpdateClient() +{ + if (!ProcessConnection(server_connection)) { Close(); + } else { + ProcessGameCommandQueue(); + if (CheckSRAND(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32), RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32))) { + if (server_srand0_tick == 0) { + // printf("SRAND OK!\n"); + } + } else { + window_network_status_open("Network desync detected"); + Close(); + } } } @@ -478,6 +510,14 @@ void Network::SendPacketToClients(NetworkPacket& packet) bool Network::CheckSRAND(uint32 tick, uint32 srand0) { + if (server_srand0_tick == 0) + return true; + + if (tick >= server_srand0_tick) { + server_srand0_tick = 0; + return true; + } + if (tick == server_srand0_tick) { server_srand0_tick = 0; if (srand0 != server_srand0) { @@ -634,17 +674,20 @@ void Network::ProcessPacket(NetworkConnection& connection, NetworkPacket& packet uint32 command; packet >> command; if (command < NETWORK_COMMAND_MAX) { - if (GetMode() == NETWORK_MODE_CLIENT) { - if (client_command_handlers[command]) { - (this->*client_command_handlers[command])(connection, packet); - } - } else - if (GetMode() == NETWORK_MODE_SERVER) { + // printf("RECV %s\n", NetworkCommandNames[command]); + switch (gNetwork.GetMode()) { + case NETWORK_MODE_SERVER: if (server_command_handlers[command]) { if (connection.authstatus == NETWORK_AUTH_OK || command == NETWORK_COMMAND_AUTH) { (this->*server_command_handlers[command])(connection, packet); } } + break; + case NETWORK_MODE_CLIENT: + if (client_command_handlers[command]) { + (this->*client_command_handlers[command])(connection, packet); + } + break; } } packet.Clear(); @@ -997,11 +1040,13 @@ void network_send_chat(const char* text) void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp, uint8 callback) { - if (gNetwork.GetMode() == NETWORK_MODE_CLIENT) { - gNetwork.Client_Send_GAMECMD(eax, ebx, ecx, edx, esi, edi, ebp, callback); - } else - if (gNetwork.GetMode() == NETWORK_MODE_SERVER) { + switch (gNetwork.GetMode()) { + case NETWORK_MODE_SERVER: gNetwork.Server_Send_GAMECMD(eax, ebx, ecx, edx, esi, edi, ebp, gNetwork.GetPlayerID(), callback); + break; + case NETWORK_MODE_CLIENT: + gNetwork.Client_Send_GAMECMD(eax, ebx, ecx, edx, esi, edi, ebp, callback); + break; } } diff --git a/src/network/network.h b/src/network/network.h index 121ddf5b24..17dc74a497 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -188,6 +188,11 @@ private: std::vector chunk_buffer; char password[33]; + bool was_paused_before_client_connected; + + void UpdateServer(); + void UpdateClient(); + private: std::vector client_command_handlers; std::vector server_command_handlers; diff --git a/src/rct2.c b/src/rct2.c index 24f00a2c45..61af055adf 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -36,6 +36,7 @@ #include "localisation/date.h" #include "localisation/localisation.h" #include "management/news_item.h" +#include "network/network.h" #include "network/twitch.h" #include "object.h" #include "openrct2.h" @@ -371,6 +372,8 @@ void rct2_update_2() // TODO: screenshot countdown process + network_update(); + // check_cmdline_arg(); // Screens if (RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) != 0)