(svn r7125) -Fix: Several errors/glitches related to multiplayer and bankrupcy, mainly such a

thing happening to a server, and non updated company-information. Also fixes FS#393.
This commit is contained in:
Darkvater 2006-11-10 17:52:51 +00:00
parent c5723ab9af
commit bd7649b080
3 changed files with 99 additions and 78 deletions

View File

@ -424,9 +424,9 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
error_part1 = GB(cmd, 16, 16); error_part1 = GB(cmd, 16, 16);
_additional_cash_required = 0; _additional_cash_required = 0;
/** Spectator has no rights except for the dedicated server which /** Spectator has no rights except for the (dedicated) server which
* is a spectator but is the server, so can do anything */ * is/can be a spectator but as the server it can do anything */
if (_current_player == PLAYER_SPECTATOR && !_network_dedicated) { if (_current_player == PLAYER_SPECTATOR && !_network_server) {
ShowErrorMessage(_error_message, error_part1, x, y); ShowErrorMessage(_error_message, error_part1, x, y);
_cmd_text = NULL; _cmd_text = NULL;
return false; return false;
@ -495,12 +495,14 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
* send it to the command-queue and abort execution * send it to the command-queue and abort execution
* If we are a dedicated server temporarily switch local player, otherwise * If we are a dedicated server temporarily switch local player, otherwise
* the other parties won't be able to execute our command and will desync. * the other parties won't be able to execute our command and will desync.
* @todo Rewrite dedicated server to something more than a dirty hack! * We also need to do this if the server's company has gone bankrupt
* @todo Rewrite (dedicated) server to something more than a dirty hack!
*/ */
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) { if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
if (_network_dedicated) _local_player = 0; PlayerID pbck = _local_player;
if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = 0;
NetworkSend_Command(tile, p1, p2, cmd, callback); NetworkSend_Command(tile, p1, p2, cmd, callback);
if (_network_dedicated) _local_player = PLAYER_SPECTATOR; if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck;
_docommand_recursive = 0; _docommand_recursive = 0;
_cmd_text = NULL; _cmd_text = NULL;
return true; return true;

View File

@ -414,35 +414,47 @@ static void PlayersCheckBankrupt(Player *p)
SetDParam(1, p->name_2); SetDParam(1, p->name_2);
AddNewsItem( (StringID)(owner | NB_BBANKRUPT), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0); AddNewsItem( (StringID)(owner | NB_BBANKRUPT), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
// If the player is human, and it is no network play, leave the player playing if (IsHumanPlayer(owner)) {
if (IsHumanPlayer(owner) && !_networking) { /* XXX - If we are in offline mode, leave the player playing. Eg. there
p->bankrupt_asked = 255; * is no THE-END, otherwise mark the player as spectator to make sure
* he/she is no long in control of this company */
if (!_networking) {
p->bankrupt_asked = 0xFF;
p->bankrupt_timeout = 0x456; p->bankrupt_timeout = 0x456;
} else { break;
} else if (owner == _local_player) {
_local_player = _network_playas = PLAYER_SPECTATOR;
}
#ifdef ENABLE_NETWORK #ifdef ENABLE_NETWORK
/* If we are the server make sure it is clear that this player is not active */ /* The server has to handle all administrative issues, for example
if (IsHumanPlayer(owner) && _network_server) { * updating and notifying all clients of what has happened */
if (_network_server) {
const NetworkClientState *cs; const NetworkClientState *cs;
/* Find all clients that were in control of this company */ NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
/* The server has just gone belly-up, mark it as spectator */
if (owner == ci->client_playas) {
ci->client_playas = PLAYER_SPECTATOR;
NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
}
/* Find all clients that were in control of this company,
* and mark them as spectator; broadcast this message to everyone */
FOR_ALL_CLIENTS(cs) { FOR_ALL_CLIENTS(cs) {
NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs); ci = DEREF_CLIENT_INFO(cs);
if (ci->client_playas == owner) { if (ci->client_playas == owner) {
ci->client_playas = PLAYER_SPECTATOR; ci->client_playas = PLAYER_SPECTATOR;
// Send the new info to all the clients NetworkUpdateClientInfo(ci->client_index);
NetworkUpdateClientInfo(_network_own_client_index);
} }
} }
} }
// Make sure the player no longer controls the company
if (IsHumanPlayer(owner) && owner == _local_player) {
// Switch the player to spectator..
_local_player = PLAYER_SPECTATOR;
}
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
}
/* Remove the player */ /* Remove the player */
ChangeOwnershipOfPlayerItems(owner, PLAYER_SPECTATOR); ChangeOwnershipOfPlayerItems(owner, PLAYER_SPECTATOR);
// Register the player as not-active /* Register the player as not-active */
p->is_active = false; p->is_active = false;
if (!IsHumanPlayer(owner) && (!_networking || _network_server) && _ai.enabled) if (!IsHumanPlayer(owner) && (!_networking || _network_server) && _ai.enabled)
@ -450,7 +462,6 @@ static void PlayersCheckBankrupt(Player *p)
} }
} }
} }
}
void DrawNewsBankrupcy(Window *w) void DrawNewsBankrupcy(Window *w)
{ {

View File

@ -819,34 +819,50 @@ int32 CmdPlayerCtrl(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
switch (p1) { switch (p1) {
case 0: { /* Create a new player */ case 0: { /* Create a new player */
/* Joining Client:
* _local_player: PLAYER_SPECTATOR
* _network_playas/cid = requested company/player
*
* Other client(s)/server:
* _local_player/_network_playas: what they play as
* cid = requested company/player of joining client */
Player *p; Player *p;
uint16 cid = p2; // ClientID uint16 cid = p2; // ClientID
/* This command is only executed in a multiplayer game */
if (!_networking) return CMD_ERROR;
/* ClientID would be valid up to MAX_CLIENT_INFO, but as it has to be a /* ClientID would be valid up to MAX_CLIENT_INFO, but as it has to be a
* new player, its valid range is restricted to that of players */ * new player, its valid range is restricted to that of players */
if (!(flags & DC_EXEC) || !IsValidPlayer((PlayerID)cid)) return 0; if (!(flags & DC_EXEC) || !IsValidPlayer((PlayerID)cid)) return 0;
/* Delete multiplayer progress bar */
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
p = DoStartupNewPlayer(false); p = DoStartupNewPlayer(false);
/* A new player could not be created, revert to being a spectator */
if (p == NULL) {
#ifdef ENABLE_NETWORK #ifdef ENABLE_NETWORK
if (_networking && !_network_server && _local_player == PLAYER_SPECTATOR) { if (_network_server) {
/* In case we are a client joining a server... */ NetworkClientInfo *ci = &_network_client_info[cid];
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0); ci->client_playas = PLAYER_SPECTATOR;
} NetworkUpdateClientInfo(ci->client_index);
} else
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
{
_local_player = _network_playas = PLAYER_SPECTATOR;
}
break;
}
if (p != NULL) { /* This is the joining client who wants a new company */
if (_local_player == PLAYER_SPECTATOR) { if (_local_player != _network_playas) {
/* Check if we do not want to be a spectator in network */ assert(_local_player == PLAYER_SPECTATOR && _network_playas == p->index);
if (!_networking ||
(_network_server && !_network_dedicated) ||
_network_playas != PLAYER_SPECTATOR) {
_local_player = p->index; _local_player = p->index;
MarkWholeScreenDirty(); MarkWholeScreenDirty();
} }
} else if (p->index == _local_player) {
DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
}
#ifdef ENABLE_NETWORK #ifdef ENABLE_NETWORK
if (_network_server) { if (_network_server) {
/* XXX - UGLY! p2 (pid) is mis-used to fetch the client-id, done at /* XXX - UGLY! p2 (pid) is mis-used to fetch the client-id, done at
@ -877,16 +893,7 @@ int32 CmdPlayerCtrl(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
_local_player = player_backup; _local_player = player_backup;
} }
} }
} else if (_network_server) {
// Creating player failed, defer client to spectator
/* XXX - UGLY! p2 (pid) is mis-used to fetch the client-id, done at
* server-side in network_server.c:838, function
* DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) */
NetworkClientInfo *ci = &_network_client_info[cid];
ci->client_playas = PLAYER_SPECTATOR;
NetworkUpdateClientInfo(ci->client_index);
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
}
} break; } break;
case 1: /* Make a new AI player */ case 1: /* Make a new AI player */
@ -933,6 +940,7 @@ int32 CmdPlayerCtrl(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
ChangeOwnershipOfPlayerItems(pid_old, pid_new); ChangeOwnershipOfPlayerItems(pid_old, pid_new);
DeletePlayerStuff(pid_old); DeletePlayerStuff(pid_old);
} break; } break;
default: return CMD_ERROR; default: return CMD_ERROR;
} }