diff options
author | truelight <truelight@openttd.org> | 2005-03-29 19:10:13 +0000 |
---|---|---|
committer | truelight <truelight@openttd.org> | 2005-03-29 19:10:13 +0000 |
commit | 508738f836af7f5315ea14f8daa280d00cad2d10 (patch) | |
tree | 71c58f5741951475a3a1776a1833c7a13b621ba7 | |
parent | c68cfdeecaccbd3979e920ec424f98375e0f9e3d (diff) | |
download | openttd-508738f836af7f5315ea14f8daa280d00cad2d10.tar.xz |
(svn r2106) -Fix: improved the network-join algoritm, it is now a bit more stable
-Add: added 'pause_on_join' and 'max_join_time' for MP games, where you
can auto-pause the game when a client wants to join the game. This to
avoid connection losses because of big maps (200+ trains). (with tnx to
#openttdcoop for the ideas and testing)
-rw-r--r-- | console_cmds.c | 38 | ||||
-rw-r--r-- | network.c | 10 | ||||
-rw-r--r-- | network.h | 3 | ||||
-rw-r--r-- | network_server.c | 41 | ||||
-rw-r--r-- | settings.c | 2 |
5 files changed, 88 insertions, 6 deletions
diff --git a/console_cmds.c b/console_cmds.c index 809808c3a..88b7bb3c2 100644 --- a/console_cmds.c +++ b/console_cmds.c @@ -436,6 +436,9 @@ DEF_CONSOLE_CMD(ConStatus) case STATUS_AUTH: status = "authorized"; break; + case STATUS_MAP_WAIT: + status = "waiting"; + break; case STATUS_MAP: status = "loading map"; break; @@ -1061,6 +1064,20 @@ DEF_CONSOLE_CMD(ConSet) { return NULL; } + // setting max-join-time + if (strcmp(argv[1],"max_join_time") == 0) { + if (argc == 3 && atoi(argv[2]) != 0) { + _network_max_join_time = atoi(argv[2]); + IConsolePrintF(_iconsole_color_warning, "Max-join-time changed to '%d'", _network_max_join_time); + IConsolePrintF(_iconsole_color_warning, "Changes will take effect immediatly."); + } else { + IConsolePrintF(_iconsole_color_default, "Current max-join-time is '%d'", _network_max_join_time); + IConsolePrint(_iconsole_color_warning, "Usage: set max_join_time <ticks> (default = 500)."); + } + return NULL; + } + + // setting the server advertising on/off if (strcmp(argv[1],"server_advertise") == 0) { if (!_network_server) { @@ -1082,6 +1099,25 @@ DEF_CONSOLE_CMD(ConSet) { return NULL; } + // setting the server 'pause on client join' on/off + if (strcmp(argv[1],"pause_on_join") == 0) { + if (!_network_server) { + IConsolePrintF(_iconsole_color_error, "You are not the server"); + return NULL; + } + if (argc == 3) { + if (strcmp(argv[2], "on") == 0 || atoi(argv[2]) == 1) + _network_pause_on_join = true; + else + _network_pause_on_join = false; + IConsolePrintF(_iconsole_color_warning, "Pause-on-join changed to '%s'", (_network_pause_on_join)?"on":"off"); + } else { + IConsolePrintF(_iconsole_color_default, "Current pause-on-join is '%s'", (_network_pause_on_join)?"on":"off"); + IConsolePrint(_iconsole_color_warning, "Usage: set pause_on_join on/off."); + } + return NULL; + } + // setting the server autoclean on/off if (strcmp(argv[1],"autoclean_companies") == 0) { if (!_network_server) { @@ -1175,7 +1211,9 @@ DEF_CONSOLE_CMD(ConSet) { IConsolePrint(_iconsole_color_error, " - autoclean_protected <months>"); IConsolePrint(_iconsole_color_error, " - autoclean_unprotected <months>"); IConsolePrint(_iconsole_color_error, " - company_pw \"<password>\""); + IConsolePrint(_iconsole_color_error, " - max_join_time <frames>"); IConsolePrint(_iconsole_color_error, " - name \"<playername>\""); + IConsolePrint(_iconsole_color_error, " - pause_on_join on/off"); IConsolePrint(_iconsole_color_error, " - rcon_pw \"<password>\""); IConsolePrint(_iconsole_color_error, " - server_name \"<name>\""); IConsolePrint(_iconsole_color_error, " - server_advertise on/off"); @@ -4,6 +4,7 @@ #include "strings.h" #include "map.h" #include "network_data.h" +#include "command.h" #if defined(WITH_REV) extern const char _openttd_revision[]; @@ -466,6 +467,9 @@ static NetworkClientState *NetworkAllocClient(SOCKET s) cs->last_frame = 0; cs->quited = false; + cs->last_frame = _frame_counter; + cs->last_frame_server = _frame_counter; + if (_network_server) { ci = DEREF_CLIENT_INFO(cs); memset(ci, 0, sizeof(*ci)); @@ -511,6 +515,12 @@ void NetworkCloseClient(NetworkClientState *cs) SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno); } } + + /* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */ + if (cs->status == STATUS_PRE_ACTIVE && _network_pause_on_join) { + DoCommandP(0, 0, 0, NULL, CMD_PAUSE); + NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX); + } } closesocket(cs->socket); @@ -161,6 +161,9 @@ VARDEF char _network_server_name[NETWORK_NAME_LENGTH]; VARDEF char _network_server_password[NETWORK_PASSWORD_LENGTH]; VARDEF char _network_rcon_password[NETWORK_PASSWORD_LENGTH]; +VARDEF uint16 _network_max_join_time; //! Time a client can max take to join +VARDEF bool _network_pause_on_join; //! Pause the game when a client tries to join (more chance of succeeding join) + VARDEF uint16 _redirect_console_to_client; VARDEF uint16 _network_sync_freq; diff --git a/network_server.c b/network_server.c index 1d5393d41..cc01c7dc5 100644 --- a/network_server.c +++ b/network_server.c @@ -304,6 +304,9 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP) sent_packets = 4; // We start with trying 4 packets cs->status = STATUS_MAP; + /* Mark the start of download */ + cs->last_frame = _frame_counter; + cs->last_frame_server = _frame_counter; } if (cs->status == STATUS_MAP) { @@ -759,6 +762,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK) SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->index); } } + + if (_network_pause_on_join) { + /* Now pause the game till the client is in sync */ + DoCommandP(0, 1, 0, NULL, CMD_PAUSE); + + NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX); + } } else { // Wrong status for this packet, give a warning to client, and close connection SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); @@ -937,14 +947,27 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT) DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK) { + uint32 frame = NetworkRecv_uint32(cs, p); + + /* The client is trying to catch up with the server */ + if (cs->status == STATUS_PRE_ACTIVE) { + /* The client is not yet catched up? */ + if (frame + DAY_TICKS < _frame_counter) + return; + + /* Now he is! Unpause the game */ + cs->status = STATUS_ACTIVE; + + if (_network_pause_on_join) { + DoCommandP(0, 0, 0, NULL, CMD_PAUSE); + NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX); + } + } + // The client received the frame, make note of it - cs->last_frame = NetworkRecv_uint32(cs, p); + cs->last_frame = frame; // With those 2 values we can calculate the lag realtime cs->last_frame_server = _frame_counter; - - // The client is now really active - if (cs->status == STATUS_PRE_ACTIVE) - cs->status = STATUS_ACTIVE; } @@ -1527,6 +1550,12 @@ void NetworkServer_Tick(void) } else { cs->lag_test = 0; } + } else if (cs->status == STATUS_PRE_ACTIVE) { + int lag = NetworkCalculateLag(cs); + if (lag > _network_max_join_time) { + IConsolePrintF(_iconsole_color_error,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time); + NetworkCloseClient(cs); + } } @@ -1536,7 +1565,7 @@ void NetworkServer_Tick(void) } // Do we need to send the new frame-packet? - if (send_frame && cs->status == STATUS_ACTIVE) { + if (send_frame && (cs->status == STATUS_ACTIVE || cs->status == STATUS_PRE_ACTIVE)) { SEND_COMMAND(PACKET_SERVER_FRAME)(cs); } #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME diff --git a/settings.c b/settings.c index fbc37713d..11b7b2f21 100644 --- a/settings.c +++ b/settings.c @@ -760,6 +760,8 @@ static const SettingDesc misc_settings[] = { static const SettingDesc network_settings[] = { {"sync_freq", SDT_UINT16 | SDT_NOSAVE, (void*)100, &_network_sync_freq, NULL}, {"frame_freq", SDT_UINT8 | SDT_NOSAVE, (void*)0, &_network_frame_freq, NULL}, + {"max_join_time", SDT_UINT, (void*)500, &_network_max_join_time, NULL}, + {"pause_on_join", SDT_BOOL, (void*)false, &_network_pause_on_join, NULL}, {"server_bind_ip", SDT_STRINGBUF | (lengthof(_network_server_bind_ip_host) << 16), "0.0.0.0", &_network_server_bind_ip_host, NULL}, {"server_port", SDT_UINT, (void*)NETWORK_DEFAULT_PORT, &_network_server_port, NULL}, {"server_advertise",SDT_BOOL, (void*)false, &_network_advertise, NULL}, |