mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r9344) [0.5] -Backport from trunk (r9027, r9038, r9061, r9071):
- Fix: desync caused by buffer overflow (r9027) - Feature: kick inactive initial network connections after some time (r9038, r9061) - Fix: take over companies properly in multiplayer games (r9071)
This commit is contained in:
parent
759d155b08
commit
1e7cca8f8b
|
@ -529,6 +529,7 @@ DEF_CONSOLE_CMD(ConStatus)
|
|||
{
|
||||
static const char* const stat_str[] = {
|
||||
"inactive",
|
||||
"authorizing",
|
||||
"authorized",
|
||||
"waiting",
|
||||
"loading map",
|
||||
|
|
|
@ -168,7 +168,7 @@ void ResetCurrencies(void)
|
|||
StringID* BuildCurrencyDropdown(void)
|
||||
{
|
||||
/* Allow room for all currencies, plus a terminator entry */
|
||||
static StringID names[CUSTOM_CURRENCY_ID];
|
||||
static StringID names[NUM_CURRENCY + 1];
|
||||
uint i;
|
||||
|
||||
/* Add each name */
|
||||
|
|
63
economy.c
63
economy.c
|
@ -362,6 +362,40 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
|
|||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
static void ChangeNetworkOwner(PlayerID current_player, PlayerID new_player)
|
||||
{
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (!_networking) return;
|
||||
|
||||
if (current_player == _local_player) {
|
||||
_network_playas = new_player;
|
||||
SetLocalPlayer(new_player);
|
||||
}
|
||||
|
||||
if (!_network_server) return;
|
||||
|
||||
/* The server has to handle all administrative issues, for example
|
||||
* updating and notifying all clients of what has happened */
|
||||
NetworkClientState *cs;
|
||||
NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
|
||||
|
||||
/* The server has just changed from player */
|
||||
if (current_player == ci->client_playas) {
|
||||
ci->client_playas = new_player;
|
||||
NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
|
||||
}
|
||||
|
||||
/* Find all clients that were in control of this company, and mark them as new_player */
|
||||
FOR_ALL_CLIENTS(cs) {
|
||||
ci = DEREF_CLIENT_INFO(cs);
|
||||
if (current_player == ci->client_playas) {
|
||||
ci->client_playas = new_player;
|
||||
NetworkUpdateClientInfo(ci->client_index);
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
}
|
||||
|
||||
static void PlayersCheckBankrupt(Player *p)
|
||||
{
|
||||
PlayerID owner;
|
||||
|
@ -419,35 +453,9 @@ static void PlayersCheckBankrupt(Player *p)
|
|||
p->bankrupt_asked = 0xFF;
|
||||
p->bankrupt_timeout = 0x456;
|
||||
break;
|
||||
} else if (owner == _local_player) {
|
||||
_network_playas = PLAYER_SPECTATOR;
|
||||
SetLocalPlayer(PLAYER_SPECTATOR);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
/* The server has to handle all administrative issues, for example
|
||||
* updating and notifying all clients of what has happened */
|
||||
if (_network_server) {
|
||||
const NetworkClientState *cs;
|
||||
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) {
|
||||
ci = DEREF_CLIENT_INFO(cs);
|
||||
if (ci->client_playas == owner) {
|
||||
ci->client_playas = PLAYER_SPECTATOR;
|
||||
NetworkUpdateClientInfo(ci->client_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
ChangeNetworkOwner(owner, PLAYER_SPECTATOR);
|
||||
}
|
||||
|
||||
/* Remove the player */
|
||||
|
@ -1572,6 +1580,7 @@ static void DoAcquireCompany(Player *p)
|
|||
|
||||
// original code does this a little bit differently
|
||||
pi = p->index;
|
||||
ChangeNetworkOwner(pi, _current_player);
|
||||
ChangeOwnershipOfPlayerItems(pi, _current_player);
|
||||
|
||||
if (p->bankrupt_value == 0) {
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef struct CommandPacket {
|
|||
|
||||
typedef enum {
|
||||
STATUS_INACTIVE,
|
||||
STATUS_AUTHORIZING, // This means that the client is authorizing
|
||||
STATUS_AUTH, // This means that the client is authorized
|
||||
STATUS_MAP_WAIT, // This means that the client is put on hold because someone else is getting the map
|
||||
STATUS_MAP,
|
||||
|
|
|
@ -215,7 +215,14 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientState *c
|
|||
// uint8: Type of password
|
||||
//
|
||||
|
||||
Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
|
||||
Packet *p;
|
||||
|
||||
/* Invalid packet when status is AUTH or higher */
|
||||
if (cs->status >= STATUS_AUTH) return;
|
||||
|
||||
cs->status = STATUS_AUTHORIZING;
|
||||
|
||||
p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
|
||||
NetworkSend_uint8(p, type);
|
||||
NetworkSend_Packet(p, cs);
|
||||
}
|
||||
|
@ -694,7 +701,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
|
|||
type = NetworkRecv_uint8(cs, p);
|
||||
NetworkRecv_string(cs, p, password, sizeof(password));
|
||||
|
||||
if (cs->status == STATUS_INACTIVE && type == NETWORK_GAME_PASSWORD) {
|
||||
if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
|
||||
// Check game-password
|
||||
if (strcmp(password, _network_game_info.server_password) != 0) {
|
||||
// Password is invalid
|
||||
|
@ -712,7 +719,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
|
|||
// Valid password, allow user
|
||||
SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
|
||||
return;
|
||||
} else if (cs->status == STATUS_INACTIVE && type == NETWORK_COMPANY_PASSWORD) {
|
||||
} else if (cs->status == STATUS_AUTHORIZING && type == NETWORK_COMPANY_PASSWORD) {
|
||||
ci = DEREF_CLIENT_INFO(cs);
|
||||
|
||||
if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
|
||||
|
@ -1534,6 +1541,12 @@ void NetworkServer_Tick(bool send_frame)
|
|||
IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
|
||||
NetworkCloseClient(cs);
|
||||
}
|
||||
} else if (cs->status == STATUS_INACTIVE) {
|
||||
int lag = NetworkCalculateLag(cs);
|
||||
if (lag > 4 * DAY_TICKS) {
|
||||
IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS);
|
||||
NetworkCloseClient(cs);
|
||||
}
|
||||
}
|
||||
|
||||
if (cs->status >= STATUS_PRE_ACTIVE) {
|
||||
|
|
Loading…
Reference in New Issue