mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-06-20 03:59:32 +01:00
(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)
This commit is contained in:
parent
c68cfdeeca
commit
508738f836
@ -436,6 +436,9 @@ DEF_CONSOLE_CMD(ConStatus)
|
|||||||
case STATUS_AUTH:
|
case STATUS_AUTH:
|
||||||
status = "authorized";
|
status = "authorized";
|
||||||
break;
|
break;
|
||||||
|
case STATUS_MAP_WAIT:
|
||||||
|
status = "waiting";
|
||||||
|
break;
|
||||||
case STATUS_MAP:
|
case STATUS_MAP:
|
||||||
status = "loading map";
|
status = "loading map";
|
||||||
break;
|
break;
|
||||||
@ -1061,6 +1064,20 @@ DEF_CONSOLE_CMD(ConSet) {
|
|||||||
return NULL;
|
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
|
// setting the server advertising on/off
|
||||||
if (strcmp(argv[1],"server_advertise") == 0) {
|
if (strcmp(argv[1],"server_advertise") == 0) {
|
||||||
if (!_network_server) {
|
if (!_network_server) {
|
||||||
@ -1082,6 +1099,25 @@ DEF_CONSOLE_CMD(ConSet) {
|
|||||||
return NULL;
|
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
|
// setting the server autoclean on/off
|
||||||
if (strcmp(argv[1],"autoclean_companies") == 0) {
|
if (strcmp(argv[1],"autoclean_companies") == 0) {
|
||||||
if (!_network_server) {
|
if (!_network_server) {
|
||||||
@ -1175,7 +1211,9 @@ DEF_CONSOLE_CMD(ConSet) {
|
|||||||
IConsolePrint(_iconsole_color_error, " - autoclean_protected <months>");
|
IConsolePrint(_iconsole_color_error, " - autoclean_protected <months>");
|
||||||
IConsolePrint(_iconsole_color_error, " - autoclean_unprotected <months>");
|
IConsolePrint(_iconsole_color_error, " - autoclean_unprotected <months>");
|
||||||
IConsolePrint(_iconsole_color_error, " - company_pw \"<password>\"");
|
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, " - name \"<playername>\"");
|
||||||
|
IConsolePrint(_iconsole_color_error, " - pause_on_join on/off");
|
||||||
IConsolePrint(_iconsole_color_error, " - rcon_pw \"<password>\"");
|
IConsolePrint(_iconsole_color_error, " - rcon_pw \"<password>\"");
|
||||||
IConsolePrint(_iconsole_color_error, " - server_name \"<name>\"");
|
IConsolePrint(_iconsole_color_error, " - server_name \"<name>\"");
|
||||||
IConsolePrint(_iconsole_color_error, " - server_advertise on/off");
|
IConsolePrint(_iconsole_color_error, " - server_advertise on/off");
|
||||||
|
10
network.c
10
network.c
@ -4,6 +4,7 @@
|
|||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "network_data.h"
|
#include "network_data.h"
|
||||||
|
#include "command.h"
|
||||||
|
|
||||||
#if defined(WITH_REV)
|
#if defined(WITH_REV)
|
||||||
extern const char _openttd_revision[];
|
extern const char _openttd_revision[];
|
||||||
@ -466,6 +467,9 @@ static NetworkClientState *NetworkAllocClient(SOCKET s)
|
|||||||
cs->last_frame = 0;
|
cs->last_frame = 0;
|
||||||
cs->quited = false;
|
cs->quited = false;
|
||||||
|
|
||||||
|
cs->last_frame = _frame_counter;
|
||||||
|
cs->last_frame_server = _frame_counter;
|
||||||
|
|
||||||
if (_network_server) {
|
if (_network_server) {
|
||||||
ci = DEREF_CLIENT_INFO(cs);
|
ci = DEREF_CLIENT_INFO(cs);
|
||||||
memset(ci, 0, sizeof(*ci));
|
memset(ci, 0, sizeof(*ci));
|
||||||
@ -511,6 +515,12 @@ void NetworkCloseClient(NetworkClientState *cs)
|
|||||||
SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
|
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);
|
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_server_password[NETWORK_PASSWORD_LENGTH];
|
||||||
VARDEF char _network_rcon_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 _redirect_console_to_client;
|
||||||
|
|
||||||
VARDEF uint16 _network_sync_freq;
|
VARDEF uint16 _network_sync_freq;
|
||||||
|
@ -304,6 +304,9 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
|
|||||||
sent_packets = 4; // We start with trying 4 packets
|
sent_packets = 4; // We start with trying 4 packets
|
||||||
|
|
||||||
cs->status = STATUS_MAP;
|
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) {
|
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);
|
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 {
|
} else {
|
||||||
// Wrong status for this packet, give a warning to client, and close connection
|
// Wrong status for this packet, give a warning to client, and close connection
|
||||||
SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
|
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)
|
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
|
// 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
|
// With those 2 values we can calculate the lag realtime
|
||||||
cs->last_frame_server = _frame_counter;
|
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 {
|
} else {
|
||||||
cs->lag_test = 0;
|
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?
|
// 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);
|
SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
|
||||||
}
|
}
|
||||||
#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
|
#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
|
||||||
|
@ -760,6 +760,8 @@ static const SettingDesc misc_settings[] = {
|
|||||||
static const SettingDesc network_settings[] = {
|
static const SettingDesc network_settings[] = {
|
||||||
{"sync_freq", SDT_UINT16 | SDT_NOSAVE, (void*)100, &_network_sync_freq, NULL},
|
{"sync_freq", SDT_UINT16 | SDT_NOSAVE, (void*)100, &_network_sync_freq, NULL},
|
||||||
{"frame_freq", SDT_UINT8 | SDT_NOSAVE, (void*)0, &_network_frame_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_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_port", SDT_UINT, (void*)NETWORK_DEFAULT_PORT, &_network_server_port, NULL},
|
||||||
{"server_advertise",SDT_BOOL, (void*)false, &_network_advertise, NULL},
|
{"server_advertise",SDT_BOOL, (void*)false, &_network_advertise, NULL},
|
||||||
|
Loading…
Reference in New Issue
Block a user