Changeset - r2879:e5a04d608a3a
[Not reviewed]
master
0 10 0
Darkvater - 18 years ago 2006-01-25 18:11:06
darkvater@openttd.org
(svn r3427) - Feature: Allow seeing and setting the maximum amount of companies and spectators for a server. This can be changed/viewed during runtime as well in the console.
10 files changed with 326 insertions and 214 deletions:
0 comments (0 inline, 0 general)
console_cmds.c
Show inline comments
 
@@ -381,7 +381,7 @@ DEF_CONSOLE_CMD(ConBan)
 
	}
 

	
 
	if (index == NETWORK_SERVER_INDEX) {
 
		IConsolePrint(_icolour_def, "Silly boy, you can not ban yourself!");
 
		IConsoleError("Silly boy, you can not ban yourself!");
 
		return true;
 
	}
 

	
 
@@ -511,7 +511,7 @@ DEF_CONSOLE_CMD(ConStatus)
 
	const NetworkClientState *cs;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("List the status of all clients connected to the server: Usage 'status'");
 
		IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
 
		return true;
 
	}
 

	
 
@@ -527,6 +527,35 @@ DEF_CONSOLE_CMD(ConStatus)
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConServerInfo)
 
{
 
	const NetworkGameInfo *gi;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("List current and maximum client/player limits. Usage 'server_info'");
 
		IConsoleHelp("You can change these values by setting the variables 'max_clients', 'max_companies' and 'max_spectators'");
 
		return true;
 
	}
 

	
 
	gi = &_network_game_info;
 
	IConsolePrintF(_icolour_def, "Current/maximum clients:    %2d/%2d", gi->clients_on, gi->clients_max);
 
	IConsolePrintF(_icolour_def, "Current/maximum companies:  %2d/%2d", gi->companies_on, gi->companies_max);
 
	IConsolePrintF(_icolour_def, "Current/maximum spectators: %2d/%2d", gi->spectators_on, gi->spectators_max);
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_HOOK(ConHookValidateMaxClientsCount) {
 
	/* XXX - hardcoded, string limiation -- TrueLight
 
	 * XXX - also see network.c:NetworkStartup ~1343 */
 
	if (_network_game_info.clients_max > 10) {
 
		_network_game_info.clients_max = 10;
 
		IConsoleError("Maximum clients is 10, truncating.");
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConKick)
 
{
 
	NetworkClientInfo *ci;
 
@@ -549,7 +578,7 @@ DEF_CONSOLE_CMD(ConKick)
 
	}
 

	
 
	if (index == NETWORK_SERVER_INDEX) {
 
		IConsolePrint(_icolour_def, "Silly boy, you can not kick yourself!");
 
		IConsoleError("Silly boy, you can not kick yourself!");
 
		return true;
 
	}
 

	
 
@@ -1405,6 +1434,13 @@ void IConsoleStdLibRegister(void)
 
	IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_POST_ACTION, ConHookServerAdvertise);
 

	
 
	IConsoleVarRegister("max_clients",           &_network_game_info.clients_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of connected players during runtime. Default value: 10");
 
	IConsoleVarHookAdd("max_clients",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleVarHookAdd("max_clients",            ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxClientsCount);
 
	IConsoleVarRegister("max_companies",         &_network_game_info.companies_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active companies during runtime. Default value: 8");
 
	IConsoleVarHookAdd("max_companies",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleVarRegister("max_spectators",        &_network_game_info.spectators_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active spectators during runtime. Default value: 9");
 
	IConsoleVarHookAdd("max_spectators",         ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleVarRegister("pause_on_join",         &_network_pause_on_join, ICONSOLE_VAR_BOOLEAN, "Set if the server should pause gameplay while a client is joining. This might help slow users");
 
	IConsoleVarHookAdd("pause_on_join",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 

	
lang/english.txt
Show inline comments
 
@@ -1201,12 +1201,12 @@ STR_NETWORK_ADD_SERVER                  
 
STR_NETWORK_ADD_SERVER_TIP                                      :{BLACK}Adds a server to the list which will always be checked for running games.
 
STR_NETWORK_ENTER_IP                                            :{BLACK}Enter the address of the host
 

	
 
STR_NETWORK_CLIENTS_ONLINE                                      :{BLACK}{COMMA}/{COMMA}
 
STR_NETWORK_GENERAL_ONLINE                                      :{BLACK}{COMMA}/{COMMA} - {COMMA}/{COMMA}
 
STR_NETWORK_CLIENTS_CAPTION                                     :{BLACK}Clients
 
STR_NETWORK_CLIENTS_CAPTION_TIP                                 :{BLACK}Clients online / clients max
 
STR_NETWORK_CLIENTS_CAPTION_TIP                                 :{BLACK}Clients online / clients max{}Companies online / companies max
 
STR_NETWORK_GAME_INFO                                           :{SILVER}GAME INFO
 
STR_ORANGE                                                      :{ORANGE}{STRING}
 
STR_NETWORK_CLIENTS                                             :{SILVER}Clients:  {WHITE}{COMMA} / {COMMA}
 
STR_NETWORK_CLIENTS                                             :{SILVER}Clients:  {WHITE}{COMMA} / {COMMA} - {COMMA} / {COMMA}
 
STR_NETWORK_LANGUAGE                                            :{SILVER}Language:  {WHITE}{STRING}
 
STR_NETWORK_TILESET                                             :{SILVER}Tileset:  {WHITE}{STRING}
 
STR_NETWORK_MAP_SIZE                                            :{SILVER}Map size:  {WHITE}{COMMA}x{COMMA}
 
@@ -1230,7 +1230,7 @@ STR_NETWORK_SET_PASSWORD                
 
STR_NETWORK_PASSWORD_TIP                                        :{BLACK}Protect your game with a password if you don't want it to be publicly accessible
 
STR_NETWORK_SELECT_MAP                                          :{BLACK}Select a map:
 
STR_NETWORK_SELECT_MAP_TIP                                      :{BLACK}Which map do you want to play?
 
STR_NETWORK_NUMBER_OF_CLIENTS                                   :{BLACK}Maximum allowed clients:
 
STR_NETWORK_NUMBER_OF_CLIENTS                                   :{BLACK}Max clients:
 
STR_NETWORK_NUMBER_OF_CLIENTS_TIP                               :{BLACK}Choose the maximum number of clients. Not all slots need to be filled
 
STR_NETWORK_COMBO1                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 
STR_NETWORK_LAN                                                 :LAN
 
@@ -1238,18 +1238,26 @@ STR_NETWORK_INTERNET                    
 
STR_NETWORK_LAN_INTERNET                                        :LAN / Internet
 
STR_NETWORK_INTERNET_ADVERTISE                                  :Internet (advertise)
 
STR_NETWORK_COMBO2                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 
STR_NETWORK_2_CLIENTS                                           :2 clients
 
STR_NETWORK_3_CLIENTS                                           :3 clients
 
STR_NETWORK_4_CLIENTS                                           :4 clients
 
STR_NETWORK_5_CLIENTS                                           :5 clients
 
STR_NETWORK_6_CLIENTS                                           :6 clients
 
STR_NETWORK_7_CLIENTS                                           :7 clients
 
STR_NETWORK_8_CLIENTS                                           :8 clients
 
STR_NETWORK_9_CLIENTS                                           :9 clients
 
STR_NETWORK_10_CLIENTS                                          :10 clients
 
STR_NETWORK_0_CLIENTS                                           :0 players
 
STR_NETWORK_1_CLIENTS                                           :1 player
 
STR_NETWORK_2_CLIENTS                                           :2 players
 
STR_NETWORK_3_CLIENTS                                           :3 players
 
STR_NETWORK_4_CLIENTS                                           :4 players
 
STR_NETWORK_5_CLIENTS                                           :5 players
 
STR_NETWORK_6_CLIENTS                                           :6 players
 
STR_NETWORK_7_CLIENTS                                           :7 players
 
STR_NETWORK_8_CLIENTS                                           :8 players
 
STR_NETWORK_9_CLIENTS                                           :9 players
 
STR_NETWORK_10_CLIENTS                                          :10 players
 
STR_NETWORK_NUMBER_OF_COMPANIES                                 :{BLACK}Max companies:
 
STR_NETWORK_NUMBER_OF_COMPANIES_TIP                             :{BLACK}Limit the server to a certain amount of companies
 
STR_NETWORK_COMBO3                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 
STR_NETWORK_NUMBER_OF_SPECTATORS                                :{BLACK}Max spectators:
 
STR_NETWORK_NUMBER_OF_SPECTATORS_TIP                            :{BLACK}Limit the server to a certain amount of spectators
 
STR_NETWORK_COMBO4                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 
STR_NETWORK_LANGUAGE_SPOKEN                                     :{BLACK}Language spoken:
 
STR_NETWORK_LANGUAGE_TIP                                        :{BLACK}Other players will know which language is spoken on the server
 
STR_NETWORK_COMBO3                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 
STR_NETWORK_COMBO5                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 
STR_NETWORK_START_GAME                                          :{BLACK}Start Game
 
STR_NETWORK_START_GAME_TIP                                      :{BLACK}Start a new network game from a random map, or scenario
 
STR_NETWORK_LOAD_GAME                                           :{BLACK}Load Game
 
@@ -1336,14 +1344,15 @@ STR_NETWORK_ERR_CLIENT_DESYNC           
 
STR_NETWORK_ERR_CLIENT_SAVEGAME                                 :could not load map
 
STR_NETWORK_ERR_CLIENT_CONNECTION_LOST                          :connection lost
 
STR_NETWORK_ERR_CLIENT_PROTOCOL_ERROR                           :protocol error
 
STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED                           :Not Authorised
 
STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED                           :not authorized
 
STR_NETWORK_ERR_CLIENT_NOT_EXPECTED                             :received strange packet
 
STR_NETWORK_ERR_CLIENT_WRONG_REVISION                           :wrong revision
 
STR_NETWORK_ERR_CLIENT_NAME_IN_USE                              :name already in use
 
STR_NETWORK_ERR_CLIENT_WRONG_PASSWORD                           :wrong game-password
 
STR_NETWORK_ERR_CLIENT_WRONG_PASSWORD                           :wrong password
 
STR_NETWORK_ERR_CLIENT_PLAYER_MISMATCH                          :wrong player-id in DoCommand
 
STR_NETWORK_ERR_CLIENT_KICKED                                   :kicked by server
 
STR_NETWORK_ERR_CLIENT_CHEATER                                  :was trying to use a cheat
 
STR_NETWORK_ERR_CLIENT_SERVER_FULL                              :server full
 
############ End of leave-in-this-order
 
STR_NETWORK_CLIENT_JOINED                                       :has joined the game
 
STR_NETWORK_GIVE_MONEY                                          :gave your company some money ({CURRENCY})
network.c
Show inline comments
 
@@ -554,8 +554,11 @@ void NetworkCloseClient(NetworkClientSta
 

	
 
	if (_network_server) {
 
		// We just lost one client :(
 
		if (cs->status > STATUS_INACTIVE)
 
		if (cs->status > STATUS_INACTIVE) {
 
			_network_game_info.clients_on--;
 
			if (DEREF_CLIENT_INFO(cs)->client_playas == OWNER_SPECTATOR)
 
				_network_game_info.spectators_on--;
 
		}
 
		_network_clients_connected--;
 

	
 
		while ((cs + 1) != DEREF_CLIENT(MAX_CLIENTS) && (cs + 1)->socket != INVALID_SOCKET) {
 
@@ -784,9 +787,8 @@ static void NetworkInitialize(void)
 
	}
 

	
 
	// Clean the client_info memory
 
	memset(_network_client_info, 0, sizeof(_network_client_info));
 
	memset(_network_player_info, 0, sizeof(_network_player_info));
 
	_network_lobby_company_count = 0;
 
	memset(&_network_client_info, 0, sizeof(_network_client_info));
 
	memset(&_network_player_info, 0, sizeof(_network_player_info));
 

	
 
	_sync_frame = 0;
 
	_network_first_time = true;
 
@@ -914,16 +916,21 @@ static void NetworkInitGameInfo(void)
 
	if (_network_game_info.server_name[0] == '\0')
 
		snprintf(_network_game_info.server_name, sizeof(_network_game_info.server_name), "Unnamed Server");
 

	
 
	ttd_strlcpy(_network_game_info.server_revision, _openttd_revision, sizeof(_network_game_info.server_revision));
 

	
 
	// The server is a client too ;)
 
	if (_network_dedicated) {
 
		_network_game_info.clients_on = 0;
 
		_network_game_info.companies_on = 0;
 
		_network_game_info.dedicated = true;
 
	} else {
 
		_network_game_info.clients_on = 1;
 
		_network_game_info.companies_on = 1;
 
		_network_game_info.dedicated = false;
 
	}
 
	ttd_strlcpy(_network_game_info.server_revision, _openttd_revision, sizeof(_network_game_info.server_revision));
 

	
 
	_network_game_info.spectators_on = 0;
 

	
 
	_network_game_info.game_date = _date;
 
	_network_game_info.start_date = ConvertIntDate(_patches.starting_date);
 
	_network_game_info.map_width = MapSizeX();
 
@@ -1332,14 +1339,12 @@ void NetworkStartUp(void)
 
	snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
 

	
 
	/* Generate an unique id when there is none yet */
 
	if (_network_unique_id[0] == '\0')
 
		NetworkGenerateUniqueId();
 
	if (_network_unique_id[0] == '\0') NetworkGenerateUniqueId();
 

	
 
	memset(&_network_game_info, 0, sizeof(_network_game_info));
 

	
 
	/* XXX - Hard number here, because the strings can currently handle no more
 
	    than 10 clients -- TrueLight */
 
	_network_game_info.clients_max = 10;
 
	_network_game_info.clients_max = 10; // XXX - hardcoded, string limiation -- TrueLight
 
	_network_game_info.companies_max = MAX_PLAYERS;
 
	_network_game_info.spectators_max = _network_game_info.clients_max;
 

	
 
	// Let's load the network in windows
 
	#if defined(WIN32)
network.h
Show inline comments
 
@@ -61,25 +61,28 @@ enum {
 
//  some fields will be empty on the client (like game_password) by default
 
//  and only filled with data a player enters.
 
typedef struct NetworkGameInfo {
 
	char server_name[NETWORK_NAME_LENGTH];					// Server name
 
	char hostname[NETWORK_HOSTNAME_LENGTH];					// Hostname of the server (if any)
 
	char server_revision[NETWORK_REVISION_LENGTH];	// The SVN version number the server is using (e.g.: 'r304')
 
																									//  It even shows a SVN version in release-version, so
 
																									//  it is easy to compare if a server is of the correct version
 
	byte server_lang;																// Language of the server (we should make a nice table for this)
 
	byte use_password;															// Is set to != 0 if it uses a password
 
	char server_password[NETWORK_PASSWORD_LENGTH];	// On the server: the game password, on the client: != "" if server has password
 
	byte clients_max;																// Max clients allowed on server
 
	byte clients_on;																// Current count of clients on server
 
	byte spectators_on;															// How many spectators do we have?
 
	uint16 game_date;																// Current date
 
	uint16 start_date;															// When the game started
 
	char map_name[NETWORK_NAME_LENGTH];							// Map which is played ["random" for a randomized map]
 
	uint16 map_width;																// Map width
 
	uint16 map_height;															// Map height
 
	byte map_set;																		// Graphical set
 
	bool dedicated;																	// Is this a dedicated server?
 
	char rcon_password[NETWORK_PASSWORD_LENGTH];		// RCon password for the server. "" if rcon is disabled
 
	char server_name[NETWORK_NAME_LENGTH];          // Server name
 
	char hostname[NETWORK_HOSTNAME_LENGTH];         // Hostname of the server (if any)
 
	char server_revision[NETWORK_REVISION_LENGTH];  // The SVN version number the server is using (e.g.: 'r304')
 
	                                                //  It even shows a SVN version in release-version, so
 
	                                                //  it is easy to compare if a server is of the correct version
 
	byte server_lang;                               // Language of the server (we should make a nice table for this)
 
	byte use_password;                              // Is set to != 0 if it uses a password
 
	char server_password[NETWORK_PASSWORD_LENGTH];  // On the server: the game password, on the client: != "" if server has password
 
	byte clients_max;                               // Max clients allowed on server
 
	byte clients_on;                                // Current count of clients on server
 
	byte companies_max;                             // Max companies allowed on server
 
	byte companies_on;                              // How many started companies do we have
 
	byte spectators_max;                            // Max spectators allowed on server
 
	byte spectators_on;                             // How many spectators do we have?
 
	uint16 game_date;                               // Current date
 
	uint16 start_date;                              // When the game started
 
	char map_name[NETWORK_NAME_LENGTH];             // Map which is played ["random" for a randomized map]
 
	uint16 map_width;                               // Map width
 
	uint16 map_height;                              // Map height
 
	byte map_set;                                   // Graphical set
 
	bool dedicated;                                 // Is this a dedicated server?
 
	char rcon_password[NETWORK_PASSWORD_LENGTH];    // RCon password for the server. "" if rcon is disabled
 
} NetworkGameInfo;
 

	
 
typedef struct NetworkPlayerInfo {
network_client.c
Show inline comments
 
@@ -395,20 +395,30 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
{
 
	NetworkErrorCode error = NetworkRecv_uint8(MY_CLIENT, p);
 

	
 
	if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED ||
 
			error == NETWORK_ERROR_PLAYER_MISMATCH) {
 
		// We made an error in the protocol, and our connection is closed.... :(
 
		_switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR;
 
	} else if (error == NETWORK_ERROR_WRONG_REVISION) {
 
		// Wrong revision :(
 
		_switch_mode_errorstr = STR_NETWORK_ERR_WRONG_REVISION;
 
	} else if (error == NETWORK_ERROR_WRONG_PASSWORD) {
 
		// Wrong password
 
		_switch_mode_errorstr = STR_NETWORK_ERR_WRONG_PASSWORD;
 
	} else if (error == NETWORK_ERROR_KICKED) {
 
		_switch_mode_errorstr = STR_NETWORK_ERR_KICKED;
 
	} else if (error == NETWORK_ERROR_CHEATER) {
 
		_switch_mode_errorstr = STR_NETWORK_ERR_CHEATER;
 
	switch (error) {
 
		/* We made an error in the protocol, and our connection is closed.... */
 
		case NETWORK_ERROR_NOT_AUTHORIZED:
 
		case NETWORK_ERROR_NOT_EXPECTED:
 
		case NETWORK_ERROR_PLAYER_MISMATCH:
 
			_switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR;
 
			break;
 
		case NETWORK_ERROR_FULL:
 
			_switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
 
			break;
 
		case NETWORK_ERROR_WRONG_REVISION:
 
			_switch_mode_errorstr = STR_NETWORK_ERR_WRONG_REVISION;
 
			break;
 
		case NETWORK_ERROR_WRONG_PASSWORD:
 
			_switch_mode_errorstr = STR_NETWORK_ERR_WRONG_PASSWORD;
 
			break;
 
		case NETWORK_ERROR_KICKED:
 
			_switch_mode_errorstr = STR_NETWORK_ERR_KICKED;
 
			break;
 
		case NETWORK_ERROR_CHEATER:
 
			_switch_mode_errorstr = STR_NETWORK_ERR_CHEATER;
 
			break;
 
		default:
 
			_switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
 
	}
 

	
 
	DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
network_data.h
Show inline comments
 
@@ -18,7 +18,7 @@
 
#define NETWORK_EMPTY_INDEX 0
 

	
 
// What version of game-info do we use?
 
#define NETWORK_GAME_INFO_VERSION 1
 
#define NETWORK_GAME_INFO_VERSION 2
 
// What version of company info is this?
 
#define NETWORK_COMPANY_INFO_VERSION 3
 
// What version of master-server-protocol do we use?
 
@@ -92,6 +92,7 @@ typedef enum {
 
	NETWORK_ERROR_PLAYER_MISMATCH, // Happens in CLIENT_COMMAND
 
	NETWORK_ERROR_KICKED,
 
	NETWORK_ERROR_CHEATER,
 
	NETWORK_ERROR_FULL,
 
} NetworkErrorCode;
 

	
 
// Actions that can be used for NetworkTextMessage
network_gui.c
Show inline comments
 
@@ -45,6 +45,29 @@ static const StringID _lan_internet_type
 
	INVALID_STRING_ID
 
};
 

	
 
static const StringID _players_dropdown[] = {
 
	STR_NETWORK_0_CLIENTS,
 
	STR_NETWORK_1_CLIENTS,
 
	STR_NETWORK_2_CLIENTS,
 
	STR_NETWORK_3_CLIENTS,
 
	STR_NETWORK_4_CLIENTS,
 
	STR_NETWORK_5_CLIENTS,
 
	STR_NETWORK_6_CLIENTS,
 
	STR_NETWORK_7_CLIENTS,
 
	STR_NETWORK_8_CLIENTS,
 
	STR_NETWORK_9_CLIENTS,
 
	STR_NETWORK_10_CLIENTS,
 
	INVALID_STRING_ID
 
};
 

	
 
static const StringID _language_dropdown[] = {
 
	STR_NETWORK_LANG_ANY,
 
	STR_NETWORK_LANG_ENGLISH,
 
	STR_NETWORK_LANG_GERMAN,
 
	STR_NETWORK_LANG_FRENCH,
 
	INVALID_STRING_ID
 
};
 

	
 
enum {
 
	NET_PRC__OFFSET_TOP_WIDGET					= 74,
 
	NET_PRC__OFFSET_TOP_WIDGET_COMPANY	= 42,
 
@@ -88,8 +111,11 @@ static void NetworkGameWindowWndProc(Win
 
			SETBIT(w->disabled_state, 17); SETBIT(w->disabled_state, 18);
 
		} else if (!sel->online) {
 
			SETBIT(w->disabled_state, 17); // Server offline, join button disabled
 
		} else if (sel->info.clients_on == sel->info.clients_max) {
 
		} else if (sel->info.clients_on >= sel->info.clients_max) {
 
			SETBIT(w->disabled_state, 17); // Server full, join button disabled
 
		} else if (sel->info.companies_on >= sel->info.companies_max &&
 
			         sel->info.spectators_on >= sel->info.spectators_max) {
 
			SETBIT(w->disabled_state, 17);
 

	
 
			// revisions don't match, check if server has no revision; then allow connection
 
		} else if (strncmp(sel->info.server_revision, _openttd_revision, NETWORK_REVISION_LENGTH - 1) != 0) {
 
@@ -106,9 +132,6 @@ static void NetworkGameWindowWndProc(Win
 
		DrawString(9, 23, STR_NETWORK_PLAYER_NAME, 2);
 
		DrawString(9, 43, STR_NETWORK_CONNECTION, 2);
 

	
 
		DrawString(15, 63, STR_NETWORK_GAME_NAME, 2);
 
		DrawString(135, 63, STR_NETWORK_CLIENTS_CAPTION, 2);
 

	
 
		{ // draw list of games
 
			uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
 
			int32 n = 0;
 
@@ -133,7 +156,9 @@ static void NetworkGameWindowWndProc(Win
 

	
 
				SetDParam(0, cur_item->info.clients_on);
 
				SetDParam(1, cur_item->info.clients_max);
 
				DrawString(135, y, STR_NETWORK_CLIENTS_ONLINE, 2);
 
				SetDParam(2, cur_item->info.companies_on);
 
				SetDParam(3, cur_item->info.companies_max);
 
				DrawString(135, y, STR_NETWORK_GENERAL_ONLINE, 2);
 

	
 
				// only draw icons if the server is online
 
				if (cur_item->online) {
 
@@ -176,10 +201,12 @@ static void NetworkGameWindowWndProc(Win
 

	
 
			SetDParam(0, sel->info.clients_on);
 
			SetDParam(1, sel->info.clients_max);
 
			DrawString(260, y, STR_NETWORK_CLIENTS, 2); // clients on the server / maximum slots
 
			SetDParam(2, sel->info.companies_on);
 
			SetDParam(3, sel->info.companies_max);
 
			DrawString(260, y, STR_NETWORK_CLIENTS, 2);
 
			y += 10;
 

	
 
			SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
 
			SetDParam(0, _language_dropdown[sel->info.server_lang]);
 
			DrawString(260, y, STR_NETWORK_LANGUAGE, 2); // server language
 
			y += 10;
 

	
 
@@ -339,40 +366,40 @@ static void NetworkGameWindowWndProc(Win
 
}
 

	
 
static const Widget _network_game_window_widgets[] = {
 
{   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,										STR_018B_CLOSE_WINDOW},
 
{    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   489,     0,    13, STR_NETWORK_MULTIPLAYER,			STR_NULL},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,     0,   489,    14,   214, 0x0,													STR_NULL},
 
{   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                   STR_018B_CLOSE_WINDOW},
 
{    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   549,     0,    13, STR_NETWORK_MULTIPLAYER,    STR_NULL},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,     0,   549,    14,   214, STR_NULL,                   STR_NULL},
 

	
 
/* LEFT SIDE */
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,    90,   231,    22,    33, 0x0,													STR_NETWORK_ENTER_NAME_TIP},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,    90,   291,    22,    33, STR_NULL,                   STR_NETWORK_ENTER_NAME_TIP},
 

	
 
{          WWT_6,   RESIZE_NONE,   BGC,    90,   231,    42,    53, STR_NETWORK_COMBO1,					STR_NETWORK_CONNECTION_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   220,   230,    43,    52, STR_0225,										STR_NETWORK_CONNECTION_TIP},
 
{          WWT_6,   RESIZE_NONE,   BGC,    90,   231,    42,    53, STR_NETWORK_COMBO1,         STR_NETWORK_CONNECTION_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   220,   230,    43,    52, STR_0225,                   STR_NETWORK_CONNECTION_TIP},
 

	
 
{     WWT_IMGBTN,   RESIZE_NONE,   BTC,    10,   130,    62,    73, 0x0,													STR_NETWORK_GAME_NAME_TIP },
 
{     WWT_IMGBTN,   RESIZE_NONE,   BTC,   131,   180,    62,    73, 0x0,													STR_NETWORK_CLIENTS_CAPTION_TIP },
 
{     WWT_IMGBTN,   RESIZE_NONE,   BTC,   181,   219,    62,    73, 0x0,													STR_NETWORK_INFO_ICONS_TIP },
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BTC,    10,   130,    62,    73, STR_NETWORK_GAME_NAME,      STR_NETWORK_GAME_NAME_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BTC,   131,   180,    62,    73, STR_NETWORK_CLIENTS_CAPTION,STR_NETWORK_CLIENTS_CAPTION_TIP},
 
{      WWT_PANEL,   RESIZE_NONE,   BTC,   181,   219,    62,    73, 0,                          STR_NETWORK_INFO_ICONS_TIP},
 

	
 
{     WWT_MATRIX,   RESIZE_NONE,   BGC,    10,   219,    74,   185, 0x801,												STR_NETWORK_CLICK_GAME_TO_SELECT},
 
{  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   220,   231,    62,   185, 0x0,													STR_0190_SCROLL_BAR_SCROLLS_LIST},
 
{     WWT_MATRIX,   RESIZE_NONE,   BGC,    10,   219,    74,   185, 0x801,                      STR_NETWORK_CLICK_GAME_TO_SELECT},
 
{  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   220,   231,    62,   185, STR_NULL,                   STR_0190_SCROLL_BAR_SCROLLS_LIST},
 

	
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    10,   115,   195,   206, STR_NETWORK_FIND_SERVER,			STR_NETWORK_FIND_SERVER_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   125,   231,   195,   206, STR_NETWORK_ADD_SERVER,			STR_NETWORK_ADD_SERVER_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   250,   360,   195,   206, STR_NETWORK_START_SERVER,		STR_NETWORK_START_SERVER_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   370,   480,   195,   206, STR_012E_CANCEL,							STR_NULL},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    10,   115,   195,   206, STR_NETWORK_FIND_SERVER,    STR_NETWORK_FIND_SERVER_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   125,   231,   195,   206, STR_NETWORK_ADD_SERVER,     STR_NETWORK_ADD_SERVER_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   250,   360,   195,   206, STR_NETWORK_START_SERVER,   STR_NETWORK_START_SERVER_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   370,   480,   195,   206, STR_012E_CANCEL,            STR_NULL},
 

	
 
/* RIGHT SIDE */
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,   250,   480,    22,   185, 0x0,					STR_NULL},
 
{          WWT_6,   RESIZE_NONE,   BGC,   251,   479,    23,   184, 0x0,					STR_NULL},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,   250,   480,    22,   185, STR_NULL,                   STR_NULL},
 
{          WWT_6,   RESIZE_NONE,   BGC,   251,   479,    23,   184, STR_NULL,                   STR_NULL},
 

	
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   257,   360,   164,   175, STR_NETWORK_JOIN_GAME,					STR_NULL},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   370,   473,   164,   175, STR_NETWORK_REFRESH,					STR_NETWORK_REFRESH_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   257,   360,   164,   175, STR_NETWORK_JOIN_GAME,      STR_NULL},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   370,   473,   164,   175, STR_NETWORK_REFRESH,        STR_NETWORK_REFRESH_TIP},
 

	
 
{   WIDGETS_END},
 
};
 

	
 
static const WindowDesc _network_game_window_desc = {
 
	WDP_CENTER, WDP_CENTER, 490, 215,
 
	WDP_CENTER, WDP_CENTER, 550, 215,
 
	WC_NETWORK_WINDOW,0,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 
	_network_game_window_widgets,
 
@@ -408,27 +435,6 @@ void ShowNetworkGameWindow(void)
 
	UpdateNetworkGameWindow(true);
 
}
 

	
 
static const StringID _players_dropdown[] = {
 
	STR_NETWORK_2_CLIENTS,
 
	STR_NETWORK_3_CLIENTS,
 
	STR_NETWORK_4_CLIENTS,
 
	STR_NETWORK_5_CLIENTS,
 
	STR_NETWORK_6_CLIENTS,
 
	STR_NETWORK_7_CLIENTS,
 
	STR_NETWORK_8_CLIENTS,
 
	STR_NETWORK_9_CLIENTS,
 
	STR_NETWORK_10_CLIENTS,
 
	INVALID_STRING_ID
 
};
 

	
 
static const StringID _language_dropdown[] = {
 
	STR_NETWORK_LANG_ANY,
 
	STR_NETWORK_LANG_ENGLISH,
 
	STR_NETWORK_LANG_GERMAN,
 
	STR_NETWORK_LANG_FRENCH,
 
	INVALID_STRING_ID
 
};
 

	
 
enum {
 
	NSSWND_START = 64,
 
	NSSWND_ROWSIZE = 12
 
@@ -446,21 +452,25 @@ static void NetworkStartServerWindowWndP
 
		int y = NSSWND_START, pos;
 
		const FiosItem *item;
 

	
 
		SetDParam(7, STR_NETWORK_LAN_INTERNET + _network_advertise);
 
		SetDParam(9, STR_NETWORK_2_CLIENTS + _network_game_info.clients_max - 2);
 
		SetDParam(11, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
 
		SetDParam( 7, _connection_types_dropdown[_network_advertise]);
 
		SetDParam( 9, _players_dropdown[_network_game_info.clients_max]);
 
		SetDParam(11, _players_dropdown[_network_game_info.companies_max]);
 
		SetDParam(13, _players_dropdown[_network_game_info.spectators_max]);
 
		SetDParam(15, _language_dropdown[_network_game_info.server_lang]);
 
		DrawWindowWidgets(w);
 

	
 
		GfxFillRect(11, 63, 259, 171, 0xD7);
 

	
 
		GfxFillRect(11, 63, 258, 215, 0xD7);
 
		DrawEditBox(w, 3);
 

	
 
		DrawString(10, 22, STR_NETWORK_NEW_GAME_NAME, 2);
 

	
 
		DrawString(10, 43, STR_NETWORK_SELECT_MAP, 2);
 
		DrawString(280, 63, STR_NETWORK_CONNECTION, 2);
 
		DrawString(280, 95, STR_NETWORK_NUMBER_OF_CLIENTS, 2);
 
		DrawString(280, 127, STR_NETWORK_LANGUAGE_SPOKEN, 2);
 

	
 
		DrawString(280,  63, STR_NETWORK_CONNECTION, 2);
 
		DrawString(280,  95, STR_NETWORK_NUMBER_OF_CLIENTS, 2);
 
		DrawString(280, 127, STR_NETWORK_NUMBER_OF_COMPANIES, 2);
 
		DrawString(280, 159, STR_NETWORK_NUMBER_OF_SPECTATORS, 2);
 
		DrawString(280, 191, STR_NETWORK_LANGUAGE_SPOKEN, 2);
 

	
 
		if (_network_game_info.use_password) DoDrawString("*", 408, 23, 3);
 

	
 
@@ -469,7 +479,7 @@ static void NetworkStartServerWindowWndP
 
		while (pos < _fios_num + 1) {
 
			item = _fios_list + pos - 1;
 
			if (item == _selected_map || (pos == 0 && _selected_map == NULL))
 
				GfxFillRect(11, y - 1, 259, y + 10, 155); // show highlighted item with a different colour
 
				GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
 

	
 
			if (pos == 0) DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, 9);
 
			else DoDrawString(item->title, 14, y, _fios_colors[item->type] );
 
@@ -484,7 +494,7 @@ static void NetworkStartServerWindowWndP
 
		_selected_field = e->click.widget;
 
		switch (e->click.widget) {
 
		case 0: /* Close 'X' */
 
		case 15: /* Cancel button */
 
		case 19: /* Cancel button */
 
			ShowNetworkGameWindow();
 
			break;
 

	
 
@@ -505,13 +515,19 @@ static void NetworkStartServerWindowWndP
 
		case 7: case 8: /* Connection type */
 
			ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
 
			break;
 
		case 9: case 10: /* Number of Players */
 
			ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max - 2, 10, 0, 0); // do it for widget 10
 
			return;
 
		case 11: case 12: /* Language */
 
			ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 12, 0, 0); // do it for widget 12
 
			return;
 
		case 13: /* Start game */
 
		case 9: case 10: /* Number of Players (hide 0 and 1 players) */
 
			ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max, 10, 0, 3);
 
			break;
 
		case 11: case 12: /* Number of Companies (hide 0, 9 and 10 companies; max is 8) */
 
			ShowDropDownMenu(w, _players_dropdown, _network_game_info.companies_max, 12, 0, 1537);
 
			break;
 
		case 13: case 14: /* Number of Spectators */
 
			ShowDropDownMenu(w, _players_dropdown, _network_game_info.spectators_max, 14, 0, 0);
 
			break;
 
		case 15: case 16: /* Language */
 
			ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 16, 0, 0);
 
			break;
 
		case 17: /* Start game */
 
			_is_network_server = true;
 
			ttd_strlcpy(_network_server_name, WP(w, querystr_d).text.buf, sizeof(_network_server_name));
 
			UpdateTextBufferSize(&WP(w, querystr_d).text);
 
@@ -529,7 +545,7 @@ static void NetworkStartServerWindowWndP
 
				}
 
			}
 
			break;
 
		case 14: /* Load game */
 
		case 18: /* Load game */
 
			_is_network_server = true;
 
			ttd_strlcpy(_network_server_name, WP(w, querystr_d).text.buf, sizeof(_network_server_name));
 
			UpdateTextBufferSize(&WP(w, querystr_d).text);
 
@@ -543,15 +559,11 @@ static void NetworkStartServerWindowWndP
 

	
 
	case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
 
		switch(e->dropdown.button) {
 
			case 8:
 
				_network_advertise = (e->dropdown.index != 0);
 
				break;
 
			case 10:
 
				_network_game_info.clients_max = e->dropdown.index + 2;
 
				break;
 
			case 12:
 
				_network_game_info.server_lang = e->dropdown.index;
 
				break;
 
			case  8: _network_advertise = (e->dropdown.index != 0); break;
 
			case 10: _network_game_info.clients_max = e->dropdown.index; break;
 
			case 12: _network_game_info.companies_max = e->dropdown.index; break;
 
			case 14: _network_game_info.spectators_max = e->dropdown.index; break;
 
			case 16: _network_game_info.server_lang = e->dropdown.index; break;
 
		}
 

	
 
		SetWindowDirty(w);
 
@@ -574,33 +586,35 @@ static void NetworkStartServerWindowWndP
 
}
 

	
 
static const Widget _network_start_server_window_widgets[] = {
 
{   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,											STR_018B_CLOSE_WINDOW },
 
{    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   419,     0,    13, STR_NETWORK_START_GAME_WINDOW,	STR_NULL},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,     0,   419,    14,   199, 0x0,														STR_NULL},
 
{   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                     STR_018B_CLOSE_WINDOW },
 
{    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   419,     0,    13, STR_NETWORK_START_GAME_WINDOW,  STR_NULL},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,     0,   419,    14,   243, 0x0,                            STR_NULL},
 

	
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,   100,   272,    22,    33, 0x0,														STR_NETWORK_NEW_GAME_NAME_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   285,   405,    22,    33, STR_NETWORK_SET_PASSWORD,			STR_NETWORK_PASSWORD_TIP},
 

	
 
{          WWT_6,   RESIZE_NONE,   BGC,    10,   271,    62,   172, 0x0,														STR_NETWORK_SELECT_MAP_TIP},
 
{  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   260,   271,    63,   171, 0x0,														STR_0190_SCROLL_BAR_SCROLLS_LIST},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,   100,   272,    22,    33, 0x0,                            STR_NETWORK_NEW_GAME_NAME_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   285,   405,    22,    33, STR_NETWORK_SET_PASSWORD,     STR_NETWORK_PASSWORD_TIP},
 

	
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,    77,    88, STR_NETWORK_COMBO1,						STR_NETWORK_CONNECTION_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,    78,    87, STR_0225,											STR_NETWORK_CONNECTION_TIP},
 

	
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,   109,   120, STR_NETWORK_COMBO2,						STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   110,   119, STR_0225,											STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
 
{          WWT_6,   RESIZE_NONE,   BGC,    10,   271,    62,   216, 0x0,                            STR_NETWORK_SELECT_MAP_TIP},
 
{  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   259,   270,    63,   215, 0x0,                            STR_0190_SCROLL_BAR_SCROLLS_LIST},
 
/* Combo boxes to control Connection Type / Max Clients / Max Companies / Max Observers / Language */
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,    77,    88, STR_NETWORK_COMBO1,           STR_NETWORK_CONNECTION_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,    78,    87, STR_0225,                     STR_NETWORK_CONNECTION_TIP},
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,   109,   120, STR_NETWORK_COMBO2,           STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   110,   119, STR_0225,                     STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,   141,   152, STR_NETWORK_COMBO3,           STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   142,   151, STR_0225,                     STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,   173,   184, STR_NETWORK_COMBO4,           STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   174,   183, STR_0225,                     STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,   205,   216, STR_NETWORK_COMBO5,           STR_NETWORK_LANGUAGE_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   206,   215, STR_0225,                     STR_NETWORK_LANGUAGE_TIP},
 

	
 
{          WWT_6,   RESIZE_NONE,   BGC,   280,   410,   141,   152, STR_NETWORK_COMBO3,						STR_NETWORK_LANGUAGE_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   142,   151, STR_0225,											STR_NETWORK_LANGUAGE_TIP},
 

	
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    40,   140,   180,   191, STR_NETWORK_START_GAME,				STR_NETWORK_START_GAME_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   150,   250,   180,   191, STR_NETWORK_LOAD_GAME,					STR_NETWORK_LOAD_GAME_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   260,   360,   180,   191, STR_012E_CANCEL,								STR_NULL},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    40,   140,   224,   235, STR_NETWORK_START_GAME,       STR_NETWORK_START_GAME_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   150,   250,   224,   235, STR_NETWORK_LOAD_GAME,          STR_NETWORK_LOAD_GAME_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   260,   360,   224,   235, STR_012E_CANCEL,                STR_NULL},
 
{   WIDGETS_END},
 
};
 

	
 
static const WindowDesc _network_start_server_window_desc = {
 
	WDP_CENTER, WDP_CENTER, 420, 200,
 
	WDP_CENTER, WDP_CENTER, 420, 244,
 
	WC_NETWORK_WINDOW,0,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 
	_network_start_server_window_widgets,
 
@@ -645,17 +659,22 @@ static byte NetworkLobbyFindCompanyIndex
 
static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e)
 
{
 
	switch (e->event) {
 
	case WE_CREATE:
 
		_selected_company_item = -1;
 
		break;
 

	
 
	case WE_PAINT: {
 
		const NetworkGameInfo *gi = &_network_game_info;
 
		int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
 

	
 
		w->disabled_state = (_selected_company_item == -1) ? 1 << 7 : 0;
 
		assert(_network_lobby_company_count == gi->companies_on);
 

	
 
		if (_network_lobby_company_count == MAX_PLAYERS)
 
			SETBIT(w->disabled_state, 8);
 
		if (gi->companies_on == gi->companies_max) SETBIT(w->disabled_state, 8);
 
		if (gi->spectators_on == gi->spectators_max) SETBIT(w->disabled_state, 9);
 
		/* You can not join a server as spectator when it has no companies active..
 
		     it causes some nasty crashes */
 
		if (_network_lobby_company_count == 0)
 
			SETBIT(w->disabled_state, 9);
 
		 * it causes some nasty crashes */
 
		if (gi->companies_on == 0) SETBIT(w->disabled_state, 9);
 

	
 
		DrawWindowWidgets(w);
 

	
 
@@ -665,13 +684,13 @@ static void NetworkLobbyWindowWndProc(Wi
 
		// draw company list
 
		GfxFillRect(11, 41, 154, 165, 0xD7);
 
		pos = w->vscroll.pos;
 
		while (pos < _network_lobby_company_count) {
 
		while (pos < gi->companies_on) {
 
			byte index = NetworkLobbyFindCompanyIndex(pos);
 
			bool income = false;
 
			if (_selected_company_item == index)
 
				GfxFillRect(11, y - 1, 154, y + 10, 155); // show highlighted item with a different colour
 

	
 
			DoDrawString(_network_player_info[index].company_name, 13, y, 2);
 
			DoDrawStringTruncated(_network_player_info[index].company_name, 13, y, 2, 135 - 13);
 
			if (_network_player_info[index].use_password != 0)
 
				DrawSprite(SPR_LOCK, 135, y);
 

	
 
@@ -690,10 +709,11 @@ static void NetworkLobbyWindowWndProc(Wi
 
		if (_selected_company_item != -1) { // if a company is selected...
 
			// show company info
 
			const uint x = 183;
 
			const uint trunc_width = w->widget[6].right - x;
 
			y = 65;
 

	
 
			SetDParamStr(0, _network_player_info[_selected_company_item].company_name);
 
			DrawString(x, y, STR_NETWORK_COMPANY_NAME, 2);
 
			DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, 2, trunc_width);
 
			y += 10;
 

	
 
			SetDParam(0, _network_player_info[_selected_company_item].inaugurated_year + MAX_YEAR_BEGIN_REAL);
 
@@ -733,7 +753,7 @@ static void NetworkLobbyWindowWndProc(Wi
 
			y += 10;
 

	
 
			SetDParamStr(0, _network_player_info[_selected_company_item].players);
 
			DrawString(x, y, STR_NETWORK_PLAYERS, 2); // players
 
			DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, 2, trunc_width); // players
 
			y += 10;
 
		}
 
	}	break;
 
@@ -753,7 +773,7 @@ static void NetworkLobbyWindowWndProc(Wi
 
				return;
 
			}
 
			_selected_company_item += w->vscroll.pos;
 
			if (_selected_company_item >= _network_lobby_company_count) {
 
			if (_selected_company_item >= _network_game_info.companies_on) {
 
				_selected_company_item = -1;
 
				SetWindowDirty(w);
 
				return;
 
@@ -781,9 +801,6 @@ static void NetworkLobbyWindowWndProc(Wi
 
			NetworkQueryServer(_network_last_host, _network_last_port, false);
 
			break;
 
		}	break;
 

	
 
	case WE_CREATE:
 
		_selected_company_item = -1;
 
	}
 
}
 

	
network_server.c
Show inline comments
 
@@ -156,13 +156,13 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	NetworkSend_uint8(p, error);
 
	NetworkSend_Packet(p, cs);
 

	
 
	GetString(str, STR_NETWORK_ERR_CLIENT_GENERAL + error);
 

	
 
	// Only send when the current client was in game
 
	if (cs->status > STATUS_AUTH) {
 
		NetworkGetClientName(client_name, sizeof(client_name), cs);
 

	
 
		GetString(str, STR_NETWORK_ERR_CLIENT_GENERAL + error);
 

	
 
		DEBUG(net, 2)("[NET] %s made an error (%s) and his connection is closed", client_name, str);
 
		DEBUG(net, 2) ("[NET] '%s' made an error and has been disconnected. Reason: %s", client_name, str);
 

	
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
 

	
 
@@ -177,7 +177,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
			}
 
		}
 
	} else {
 
		DEBUG(net, 2)("[NET] Clientno %d has made an error and his connection is closed", cs->index);
 
		DEBUG(net, 2) ("[NET] Client %d made an error and has been disconnected. Reason: %s", cs->index, str);
 
	}
 

	
 
	cs->quited = true;
 
@@ -213,14 +213,16 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WE
 
	//
 

	
 
	Packet *p;
 
	NetworkClientState *new_cs;
 
	const NetworkClientState *new_cs;
 
	const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 

	
 
	// Invalid packet when status is AUTH or higher
 
	if (cs->status >= STATUS_AUTH)
 
		return;
 
	if (cs->status >= STATUS_AUTH) return;
 

	
 
	cs->status = STATUS_AUTH;
 
	_network_game_info.clients_on++;
 
	/* increment spectator; defer company addition for when player is actually created */
 
	if (ci->client_playas == OWNER_SPECTATOR) _network_game_info.spectators_on++;
 

	
 
	p = NetworkSend_Init(PACKET_SERVER_WELCOME);
 
	NetworkSend_uint16(p, cs->index);
 
@@ -585,12 +587,10 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	char name[NETWORK_NAME_LENGTH];
 
	char unique_id[NETWORK_NAME_LENGTH];
 
	NetworkClientInfo *ci;
 
	char test_name[NETWORK_NAME_LENGTH];
 
	byte playas;
 
	NetworkLanguage client_lang;
 
	char client_revision[NETWORK_REVISION_LENGTH];
 

	
 

	
 
	NetworkRecv_string(cs, p, client_revision, sizeof(client_revision));
 

	
 
#if defined(WITH_REV) || defined(WITH_REV_HACK)
 
@@ -610,18 +610,28 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	client_lang = NetworkRecv_uint8(cs, p);
 
	NetworkRecv_string(cs, p, unique_id, sizeof(unique_id));
 

	
 
	if (cs->quited)
 
		return;
 
	if (cs->quited) return;
 

	
 
	// Check if someone else already has that name
 
	snprintf(test_name, sizeof(test_name), "%s", name);
 

	
 
	if (test_name[0] == '\0') {
 
		// We need a valid name.. make it Player
 
		snprintf(test_name, sizeof(test_name), "Player");
 
	// join another company does not affect these values
 
	switch (playas) {
 
		case 0: /* New company */
 
			if (_network_game_info.companies_max >= _network_game_info.companies_on) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
 
				return;
 
			}
 
			break;
 
		case OWNER_SPECTATOR: /* Spectator */
 
			if (_network_game_info.spectators_on >= _network_game_info.spectators_max) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
 
				return;
 
			}
 
			break;
 
	}
 

	
 
	if (!NetworkFindName(test_name)) {
 
	// We need a valid name.. make it Player
 
	if (name[0] == '\0') snprintf(name, sizeof(name), "Player");
 

	
 
	if (!NetworkFindName(name)) { // Change name if duplicate
 
		// We could not create a name for this player
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
 
		return;
 
@@ -629,7 +639,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 

	
 
	ci = DEREF_CLIENT_INFO(cs);
 

	
 
	snprintf(ci->client_name, sizeof(ci->client_name), "%s", test_name);
 
	snprintf(ci->client_name, sizeof(ci->client_name), "%s", name);
 
	snprintf(ci->unique_id, sizeof(ci->unique_id), "%s", unique_id);
 
	ci->client_playas = playas;
 
	ci->client_lang = client_lang;
network_udp.c
Show inline comments
 
@@ -61,6 +61,13 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIEN
 
	_network_game_info.map_set = _opt.landscape;
 

	
 
	NetworkSend_uint8 (packet, NETWORK_GAME_INFO_VERSION);
 

	
 
	/* NETWORK_GAME_INFO_VERSION = 2 */
 
	NetworkSend_uint8 (packet, _network_game_info.companies_max);
 
	NetworkSend_uint8 (packet, _network_game_info.companies_on);
 
	NetworkSend_uint8 (packet, _network_game_info.spectators_max);
 

	
 
	/* NETWORK_GAME_INFO_VERSION = 1 */
 
	NetworkSend_string(packet, _network_game_info.server_name);
 
	NetworkSend_string(packet, _network_game_info.server_revision);
 
	NetworkSend_uint8 (packet, _network_game_info.server_lang);
 
@@ -103,30 +110,39 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVE
 
	// Find next item
 
	item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
 

	
 
	if (game_info_version == 1) {
 
		NetworkRecv_string(&_udp_cs, p, item->info.server_name, sizeof(item->info.server_name));
 
		NetworkRecv_string(&_udp_cs, p, item->info.server_revision, sizeof(item->info.server_revision));
 
		item->info.server_lang   = NetworkRecv_uint8(&_udp_cs, p);
 
		item->info.use_password  = NetworkRecv_uint8(&_udp_cs, p);
 
		item->info.clients_max   = NetworkRecv_uint8(&_udp_cs, p);
 
		item->info.clients_on    = NetworkRecv_uint8(&_udp_cs, p);
 
		item->info.spectators_on = NetworkRecv_uint8(&_udp_cs, p);
 
		item->info.game_date     = NetworkRecv_uint16(&_udp_cs, p);
 
		item->info.start_date    = NetworkRecv_uint16(&_udp_cs, p);
 
		NetworkRecv_string(&_udp_cs, p, item->info.map_name, sizeof(item->info.map_name));
 
		item->info.map_width     = NetworkRecv_uint16(&_udp_cs, p);
 
		item->info.map_height    = NetworkRecv_uint16(&_udp_cs, p);
 
		item->info.map_set       = NetworkRecv_uint8(&_udp_cs, p);
 
		item->info.dedicated     = NetworkRecv_uint8(&_udp_cs, p);
 
	/* Please observe the order. In the order in which packets are sent
 
	 * they are to be received */
 
	switch (game_info_version) {
 
		case 2:
 
			item->info.companies_max = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.companies_on = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.spectators_max = NetworkRecv_uint8(&_udp_cs, p);
 
			/* Fallthrough */
 
		case 1:
 
			NetworkRecv_string(&_udp_cs, p, item->info.server_name, sizeof(item->info.server_name));
 
			NetworkRecv_string(&_udp_cs, p, item->info.server_revision, sizeof(item->info.server_revision));
 
			item->info.server_lang   = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.use_password  = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.clients_max   = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.clients_on    = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.spectators_on = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.game_date     = NetworkRecv_uint16(&_udp_cs, p);
 
			item->info.start_date    = NetworkRecv_uint16(&_udp_cs, p);
 
			NetworkRecv_string(&_udp_cs, p, item->info.map_name, sizeof(item->info.map_name));
 
			item->info.map_width     = NetworkRecv_uint16(&_udp_cs, p);
 
			item->info.map_height    = NetworkRecv_uint16(&_udp_cs, p);
 
			item->info.map_set       = NetworkRecv_uint8(&_udp_cs, p);
 
			item->info.dedicated     = NetworkRecv_uint8(&_udp_cs, p);
 

	
 
		str_validate(item->info.server_name);
 
		str_validate(item->info.server_revision);
 
		str_validate(item->info.map_name);
 
		if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
 
		if (item->info.map_set >= NUM_LANDSCAPE ) item->info.map_set = 0;
 
			str_validate(item->info.server_name);
 
			str_validate(item->info.server_revision);
 
			str_validate(item->info.map_name);
 
			if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
 
			if (item->info.map_set >= NUM_LANDSCAPE ) item->info.map_set = 0;
 

	
 
		if (item->info.hostname[0] == '\0')
 
			snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
 
			if (item->info.hostname[0] == '\0')
 
				snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
 
			break;
 
	}
 

	
 
	item->online = true;
players.c
Show inline comments
 
@@ -856,13 +856,15 @@ int32 CmdPlayerCtrl(int x, int y, uint32
 
					_local_player = ci->client_playas - 1;
 
					NetworkSend_Command(0, 0, 0, CMD_CHANGE_PRESIDENT_NAME, NULL);
 
					_local_player = player_backup;
 
					_network_game_info.companies_on++;
 
				}
 
			}
 
		} else if (_network_server) {
 
		} 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[pid];
 
			ci->client_playas = OWNER_SPECTATOR;
 
			_network_game_info.spectators_on++;
 
			NetworkUpdateClientInfo(ci->client_index);
 
		}
 
#else
 
@@ -901,6 +903,9 @@ int32 CmdPlayerCtrl(int x, int y, uint32
 
			p->is_active = false;
 
		}
 
		RemoveAllEngineReplacementForPlayer(p);
 
#ifdef ENABLE_NETWORK
 
		_network_game_info.companies_on--;
 
#endif /* ENABLE_NETWORK */
 

	
 
	} break;
 

	
0 comments (0 inline, 0 general)