forked from mirror/OpenTTD
Fix: [Network] don't desync if client leaves before you finish downloading map
When you are downloading a map, all the commands are queued up for you. Clients joining/leaving is done by the network protocol, and as such are processed immediately. This means that by the time you are processing the commands, a client that triggered it, might already have left. So, all commands that do something with ClientID, shouldn't error on an invalid ClientID when DC_EXEC is set, but gracefully handle the command anyway, to make sure the game-state is kept in sync with all the clients that did execute the DoCommand while the now-gone client was still there. Additionally, in the small chance a client disconnects between the server validating a DoCommand and the command being executed, also just process the command as if the client was still there. Otherwise, lag or latency can cause clients that did not receive the disconnect yet to desync.
This commit is contained in:
committed by
Patric Stout
parent
13889b6554
commit
2d9062bfc1
@@ -822,13 +822,6 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
|
||||
ClientID client_id = (ClientID)p2;
|
||||
NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
|
||||
#ifndef DEBUG_DUMP_COMMANDS
|
||||
/* When replaying the client ID is not a valid client; there
|
||||
* are actually no clients at all. However, the company has to
|
||||
* be created, otherwise we cannot rerun the game properly.
|
||||
* So only allow a nullptr client info in that case. */
|
||||
if (ci == nullptr) return CommandCost();
|
||||
#endif /* NOT DEBUG_DUMP_COMMANDS */
|
||||
|
||||
/* Delete multiplayer progress bar */
|
||||
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
||||
@@ -837,7 +830,9 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
|
||||
/* A new company could not be created, revert to being a spectator */
|
||||
if (c == nullptr) {
|
||||
if (_network_server) {
|
||||
/* We check for "ci != nullptr" as a client could have left by
|
||||
* the time we execute this command. */
|
||||
if (_network_server && ci != nullptr) {
|
||||
ci->client_playas = COMPANY_SPECTATOR;
|
||||
NetworkUpdateClientInfo(ci->client_id);
|
||||
}
|
||||
|
Reference in New Issue
Block a user