mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 19:13:07 +01:00
improve multiplayer
This commit is contained in:
@@ -12,7 +12,8 @@
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerCommandArguments>"C:\Program Files (x86)\Infogrames\RollerCoaster Tycoon 2\Scenarios\Crazy Castle.SC6" --port 5552 --server 127.0.0.1</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release with Tests|Win32'">
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
@@ -23,7 +24,6 @@
|
||||
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>--server 127.0.0.1 --port 12345</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
53
src/game.c
53
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)++;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +188,11 @@ private:
|
||||
std::vector<uint8> chunk_buffer;
|
||||
char password[33];
|
||||
|
||||
bool was_paused_before_client_connected;
|
||||
|
||||
void UpdateServer();
|
||||
void UpdateClient();
|
||||
|
||||
private:
|
||||
std::vector<int (Network::*)(NetworkConnection& connection, NetworkPacket& packet)> client_command_handlers;
|
||||
std::vector<int (Network::*)(NetworkConnection& connection, NetworkPacket& packet)> server_command_handlers;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user