mirror of https://github.com/OpenTTD/OpenTTD
(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)release/0.5
parent
759d155b08
commit
1e7cca8f8b
|
@ -529,6 +529,7 @@ DEF_CONSOLE_CMD(ConStatus)
|
||||||
{
|
{
|
||||||
static const char* const stat_str[] = {
|
static const char* const stat_str[] = {
|
||||||
"inactive",
|
"inactive",
|
||||||
|
"authorizing",
|
||||||
"authorized",
|
"authorized",
|
||||||
"waiting",
|
"waiting",
|
||||||
"loading map",
|
"loading map",
|
||||||
|
|
|
@ -168,7 +168,7 @@ void ResetCurrencies(void)
|
||||||
StringID* BuildCurrencyDropdown(void)
|
StringID* BuildCurrencyDropdown(void)
|
||||||
{
|
{
|
||||||
/* Allow room for all currencies, plus a terminator entry */
|
/* Allow room for all currencies, plus a terminator entry */
|
||||||
static StringID names[CUSTOM_CURRENCY_ID];
|
static StringID names[NUM_CURRENCY + 1];
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
/* Add each name */
|
/* Add each name */
|
||||||
|
|
63
economy.c
63
economy.c
|
@ -362,6 +362,40 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
|
||||||
MarkWholeScreenDirty();
|
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)
|
static void PlayersCheckBankrupt(Player *p)
|
||||||
{
|
{
|
||||||
PlayerID owner;
|
PlayerID owner;
|
||||||
|
@ -419,35 +453,9 @@ static void PlayersCheckBankrupt(Player *p)
|
||||||
p->bankrupt_asked = 0xFF;
|
p->bankrupt_asked = 0xFF;
|
||||||
p->bankrupt_timeout = 0x456;
|
p->bankrupt_timeout = 0x456;
|
||||||
break;
|
break;
|
||||||
} else if (owner == _local_player) {
|
|
||||||
_network_playas = PLAYER_SPECTATOR;
|
|
||||||
SetLocalPlayer(PLAYER_SPECTATOR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_NETWORK
|
ChangeNetworkOwner(owner, PLAYER_SPECTATOR);
|
||||||
/* 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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the player */
|
/* Remove the player */
|
||||||
|
@ -1572,6 +1580,7 @@ static void DoAcquireCompany(Player *p)
|
||||||
|
|
||||||
// original code does this a little bit differently
|
// original code does this a little bit differently
|
||||||
pi = p->index;
|
pi = p->index;
|
||||||
|
ChangeNetworkOwner(pi, _current_player);
|
||||||
ChangeOwnershipOfPlayerItems(pi, _current_player);
|
ChangeOwnershipOfPlayerItems(pi, _current_player);
|
||||||
|
|
||||||
if (p->bankrupt_value == 0) {
|
if (p->bankrupt_value == 0) {
|
||||||
|
|
|
@ -49,6 +49,7 @@ typedef struct CommandPacket {
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
STATUS_INACTIVE,
|
STATUS_INACTIVE,
|
||||||
|
STATUS_AUTHORIZING, // This means that the client is authorizing
|
||||||
STATUS_AUTH, // This means that the client is authorized
|
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_WAIT, // This means that the client is put on hold because someone else is getting the map
|
||||||
STATUS_MAP,
|
STATUS_MAP,
|
||||||
|
|
|
@ -215,7 +215,14 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientState *c
|
||||||
// uint8: Type of password
|
// 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_uint8(p, type);
|
||||||
NetworkSend_Packet(p, cs);
|
NetworkSend_Packet(p, cs);
|
||||||
}
|
}
|
||||||
|
@ -694,7 +701,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
|
||||||
type = NetworkRecv_uint8(cs, p);
|
type = NetworkRecv_uint8(cs, p);
|
||||||
NetworkRecv_string(cs, p, password, sizeof(password));
|
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
|
// Check game-password
|
||||||
if (strcmp(password, _network_game_info.server_password) != 0) {
|
if (strcmp(password, _network_game_info.server_password) != 0) {
|
||||||
// Password is invalid
|
// Password is invalid
|
||||||
|
@ -712,7 +719,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
|
||||||
// Valid password, allow user
|
// Valid password, allow user
|
||||||
SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
|
SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
|
||||||
return;
|
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);
|
ci = DEREF_CLIENT_INFO(cs);
|
||||||
|
|
||||||
if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
|
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);
|
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);
|
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) {
|
if (cs->status >= STATUS_PRE_ACTIVE) {
|
||||||
|
|
Loading…
Reference in New Issue