Changeset - r10454:ba5e39738ffa
[Not reviewed]
master
0 15 0
rubidium - 16 years ago 2008-12-22 12:59:31
rubidium@openttd.org
(svn r14709) -Codechange: make a clearer distinction between 'unique' client identification ids and the indices into the clients/client info arrays.
15 files changed with 191 insertions and 187 deletions:
0 comments (0 inline, 0 general)
src/company_cmd.cpp
Show inline comments
 
@@ -804,15 +804,15 @@ CommandCost CmdCompanyCtrl(TileIndex til
 
			* _local_company: COMPANY_SPECTATOR
 
			* _network_playas/cid = requested company/clientid
 
			*
 
			* Other client(s)/server:
 
			* _local_company/_network_playas: what they play as
 
			* cid = requested company/company of joining client */
 
			uint16 cid = p2; // ClientID
 
			ClientIndex cid = (ClientIndex)p2;
 

	
 
			/* Has the network client a correct ClientID? */
 
			/* Has the network client a correct ClientIndex? */
 
			if (!(flags & DC_EXEC)) return CommandCost();
 
			if (cid >= MAX_CLIENT_INFO) return CommandCost();
 

	
 
			/* Delete multiplayer progress bar */
 
			DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
@@ -820,13 +820,13 @@ CommandCost CmdCompanyCtrl(TileIndex til
 

	
 
			/* A new company could not be created, revert to being a spectator */
 
			if (c == NULL) {
 
				if (_network_server) {
 
					NetworkClientInfo *ci = &_network_client_info[cid];
 
					ci->client_playas = COMPANY_SPECTATOR;
 
					NetworkUpdateClientInfo(ci->client_index);
 
					NetworkUpdateClientInfo(ci->client_id);
 
				} else if (_local_company == COMPANY_SPECTATOR) {
 
					_network_playas = COMPANY_SPECTATOR;
 
				}
 
				break;
 
			}
 

	
 
@@ -856,13 +856,13 @@ CommandCost CmdCompanyCtrl(TileIndex til
 
			if (_network_server) {
 
				/* 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 = c->index;
 
				NetworkUpdateClientInfo(ci->client_index);
 
				NetworkUpdateClientInfo(ci->client_id);
 

	
 
				if (IsValidCompanyID(ci->client_playas)) {
 
					CompanyID company_backup = _local_company;
 
					_network_company_info[c->index].months_empty = 0;
 

	
 
					/* XXX - When a client joins, we automatically set its name to the
src/console.cpp
Show inline comments
 
@@ -35,13 +35,13 @@ bool _stdlib_con_developer = false;
 
FILE *_iconsole_output_file;
 

	
 
void IConsoleInit()
 
{
 
	_iconsole_output_file = NULL;
 
#ifdef ENABLE_NETWORK /* Initialize network only variables */
 
	_redirect_console_to_client = 0;
 
	_redirect_console_to_client = INVALID_CLIENT_ID;
 
#endif
 

	
 
	IConsoleGUIInit();
 

	
 
	IConsoleStdLibRegister();
 
}
 
@@ -87,13 +87,13 @@ void IConsoleFree()
 
 * @param string the message entered or output on the console (notice, error, etc.)
 
 */
 
void IConsolePrint(ConsoleColour color_code, const char *string)
 
{
 
	char *str;
 
#ifdef ENABLE_NETWORK
 
	if (_redirect_console_to_client != 0) {
 
	if (_redirect_console_to_client != INVALID_CLIENT_ID) {
 
		/* Redirect the string to the client */
 
		NetworkServerSendRcon(_redirect_console_to_client, color_code, string);
 
		return;
 
	}
 
#endif
 

	
src/console_cmds.cpp
Show inline comments
 
@@ -369,56 +369,56 @@ DEF_CONSOLE_CMD(ConClearBuffer)
 
#ifdef ENABLE_NETWORK
 

	
 
DEF_CONSOLE_CMD(ConBan)
 
{
 
	NetworkClientInfo *ci;
 
	const char *banip = NULL;
 
	uint32 index;
 
	ClientID client_id;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id>'");
 
		IConsoleHelp("For client-id's, see the command 'clients'");
 
		IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
 
		return true;
 
	}
 

	
 
	if (argc != 2) return false;
 

	
 
	if (strchr(argv[1], '.') == NULL) { // banning with ID
 
		index = atoi(argv[1]);
 
		ci = NetworkFindClientInfoFromIndex(index);
 
		client_id = (ClientID)atoi(argv[1]);
 
		ci = NetworkFindClientInfoFromIndex(client_id);
 
	} else { // banning IP
 
		ci = NetworkFindClientInfoFromIP(argv[1]);
 
		if (ci == NULL) {
 
			banip = argv[1];
 
			index = (uint32)-1;
 
			client_id = (ClientID)-1;
 
		} else {
 
			index = ci->client_index;
 
			client_id = ci->client_id;
 
		}
 
	}
 

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

	
 
	if (index == 0 || (ci == NULL && index != (uint32)-1)) {
 
	if (client_id == INVALID_CLIENT_ID || (ci == NULL && client_id != (ClientID)-1)) {
 
		IConsoleError("Invalid client");
 
		return true;
 
	}
 

	
 
	if (ci != NULL) {
 
		IConsolePrint(CC_DEFAULT, "Client banned");
 
		banip = GetClientIP(ci);
 
		NetworkServerSendError(index, NETWORK_ERROR_KICKED);
 
		NetworkServerSendError(client_id, NETWORK_ERROR_KICKED);
 
	} else {
 
		IConsolePrint(CC_DEFAULT, "Client not online, banned IP");
 
	}
 

	
 
	/* Add user to ban-list */
 
	for (index = 0; index < lengthof(_network_ban_list); index++) {
 
	for (uint index = 0; index < lengthof(_network_ban_list); index++) {
 
		if (_network_ban_list[index] == NULL) {
 
			_network_ban_list[index] = strdup(banip);
 
			break;
 
		}
 
	}
 

	
 
@@ -552,42 +552,42 @@ DEF_CONSOLE_CMD(ConServerInfo)
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConKick)
 
{
 
	NetworkClientInfo *ci;
 
	uint32 index;
 
	ClientID client_id;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("Kick a client from a network game. Usage: 'kick <ip | client-id>'");
 
		IConsoleHelp("For client-id's, see the command 'clients'");
 
		return true;
 
	}
 

	
 
	if (argc != 2) return false;
 

	
 
	if (strchr(argv[1], '.') == NULL) {
 
		index = atoi(argv[1]);
 
		ci = NetworkFindClientInfoFromIndex(index);
 
		client_id = (ClientID)atoi(argv[1]);
 
		ci = NetworkFindClientInfoFromIndex(client_id);
 
	} else {
 
		ci = NetworkFindClientInfoFromIP(argv[1]);
 
		index = (ci == NULL) ? 0 : ci->client_index;
 
		client_id = (ci == NULL) ? INVALID_CLIENT_ID : ci->client_id;
 
	}
 

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

	
 
	if (index == 0) {
 
	if (client_id == INVALID_CLIENT_ID) {
 
		IConsoleError("Invalid client");
 
		return true;
 
	}
 

	
 
	if (ci != NULL) {
 
		NetworkServerSendError(index, NETWORK_ERROR_KICKED);
 
		NetworkServerSendError(client_id, NETWORK_ERROR_KICKED);
 
	} else {
 
		IConsoleError("Client not found");
 
	}
 

	
 
	return true;
 
}
 
@@ -620,13 +620,13 @@ DEF_CONSOLE_CMD(ConResetCompany)
 
	}
 

	
 
	if (NetworkCompanyHasClients(index)) {
 
		IConsoleError("Cannot remove company: a client is connected to that company.");
 
		return false;
 
	}
 
	const NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 
	const NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(CLIENT_ID_SERVER);
 
	if (ci->client_playas == index) {
 
		IConsoleError("Cannot remove company: the server is connected to that company.");
 
		return true;
 
	}
 

	
 
	/* It is safe to remove this company */
 
@@ -644,13 +644,13 @@ DEF_CONSOLE_CMD(ConNetworkClients)
 
		IConsoleHelp("Get a list of connected clients including their ID, name, company-id, and IP. Usage: 'clients'");
 
		return true;
 
	}
 

	
 
	FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
 
		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  company: %1d  IP: %s",
 
		               ci->client_index, ci->client_name,
 
		               ci->client_id, ci->client_name,
 
		               ci->client_playas + (IsValidCompanyID(ci->client_playas) ? 1 : 0),
 
		               GetClientIP(ci));
 
	}
 

	
 
	return true;
 
}
 
@@ -1129,13 +1129,13 @@ DEF_CONSOLE_CMD(ConSay)
 

	
 
	if (argc != 2) return false;
 

	
 
	if (!_network_server) {
 
		NetworkClientSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
 
	} else {
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], CLIENT_ID_SERVER);
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConCompanies)
 
@@ -1182,13 +1182,13 @@ DEF_CONSOLE_CMD(ConSayCompany)
 
		return true;
 
	}
 

	
 
	if (!_network_server) {
 
		NetworkClientSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2]);
 
	} else {
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2], NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2], CLIENT_ID_SERVER);
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConSayClient)
 
@@ -1201,13 +1201,13 @@ DEF_CONSOLE_CMD(ConSayClient)
 

	
 
	if (argc != 3) return false;
 

	
 
	if (!_network_server) {
 
		NetworkClientSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
 
	} else {
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], CLIENT_ID_SERVER);
 
	}
 

	
 
	return true;
 
}
 

	
 
extern void HashCurrentCompanyPassword();
src/main_gui.cpp
Show inline comments
 
@@ -52,13 +52,13 @@ void CcGiveMoney(bool success, TileIndex
 
	/* Inform the company of the action of one of it's clients (controllers). */
 
	snprintf(msg, sizeof(msg), "%d", p1);
 

	
 
	if (!_network_server) {
 
		NetworkClientSendChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg);
 
	} else {
 
		NetworkServerSendChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, CLIENT_ID_SERVER);
 
	}
 
#endif /* ENABLE_NETWORK */
 
}
 

	
 
void HandleOnEditText(const char *str)
 
{
 
@@ -313,13 +313,13 @@ struct MainWindow : Window
 
				ResetRestoreAllTransparency();
 
				break;
 

	
 
#ifdef ENABLE_NETWORK
 
			case WKC_RETURN: case 'T': // smart chat; send to team if any, otherwise to all
 
				if (_networking) {
 
					const NetworkClientInfo *cio = NetworkFindClientInfoFromIndex(_network_own_client_index);
 
					const NetworkClientInfo *cio = NetworkFindClientInfoFromIndex(_network_own_client_id);
 
					bool teamchat = false;
 

	
 
					if (cio == NULL) break;
 

	
 
					/* Only companies actually playing can speak to team. Eg spectators cannot */
 
					if (_settings_client.gui.prefer_teamchat && IsValidCompanyID(cio->client_playas)) {
 
@@ -339,13 +339,13 @@ struct MainWindow : Window
 
			case WKC_SHIFT | WKC_RETURN: case WKC_SHIFT | 'T': // send text message to all clients
 
				if (_networking) ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
 
				break;
 

	
 
			case WKC_CTRL | WKC_RETURN: case WKC_CTRL | 'T': // send text to all team mates
 
				if (_networking) {
 
					const NetworkClientInfo *cio = NetworkFindClientInfoFromIndex(_network_own_client_index);
 
					const NetworkClientInfo *cio = NetworkFindClientInfoFromIndex(_network_own_client_id);
 
					if (cio == NULL) break;
 

	
 
					ShowNetworkChatQueryWindow(DESTTYPE_TEAM, cio->client_playas);
 
				}
 
				break;
 
#endif
src/network/core/tcp.cpp
Show inline comments
 
@@ -19,13 +19,13 @@
 

	
 
/** Very ugly temporary hack !!! */
 
void NetworkTCPSocketHandler::Initialize()
 
{
 
	this->sock              = INVALID_SOCKET;
 

	
 
	this->index             = 0;
 
	this->client_id         = INVALID_CLIENT_ID;
 
	this->last_frame        = 0;
 
	this->last_frame_server = 0;
 
	this->lag_test          = 0;
 

	
 
	this->status            = STATUS_INACTIVE;
 
	this->has_quit          = false;
src/network/core/tcp.h
Show inline comments
 
@@ -88,13 +88,13 @@ enum ClientStatus {
 
class NetworkTCPSocketHandler : public NetworkSocketHandler {
 
/* TODO: rewrite into a proper class */
 
private:
 
	Packet *packet_queue;     ///< Packets that are awaiting delivery
 
	Packet *packet_recv;      ///< Partially received packet
 
public:
 
	uint16 index;             ///< Client index
 
	ClientID client_id;       ///< Client identifier
 
	uint32 last_frame;        ///< Last frame we have executed
 
	uint32 last_frame_server; ///< Last frame the server has executed
 
	byte lag_test;            ///< Byte used for lag-testing the client
 

	
 
	ClientStatus status;      ///< Status of this client
 
	bool writable;            ///< Can we write to this socket?
src/network/network.cpp
Show inline comments
 
@@ -40,21 +40,23 @@
 
	#include "../core/alloc_func.hpp"
 
	#include "../fileio_func.h"
 
#endif /* DEBUG_DUMP_COMMANDS */
 
#include "table/strings.h"
 
#include "../company_base.h"
 

	
 
DECLARE_POSTFIX_INCREMENT(ClientID);
 

	
 
bool _network_server;     ///< network-server is active
 
bool _network_available;  ///< is network mode available?
 
bool _network_dedicated;  ///< are we a dedicated server?
 
bool _is_network_server;  ///< Does this client wants to be a network-server?
 
NetworkServerGameInfo _network_game_info;
 
NetworkCompanyInfo _network_company_info[MAX_COMPANIES];
 
NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
 
uint16 _network_own_client_index;
 
uint16 _redirect_console_to_client;
 
ClientID _network_own_client_id;
 
ClientID _redirect_console_to_client;
 
bool _network_need_advertise;
 
uint32 _network_last_advertise_frame;
 
uint8 _network_reconnect;
 
char *_network_host_list[10];
 
char *_network_ban_list[25];
 
uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
 
@@ -89,25 +91,25 @@ NetworkTCPSocketHandler _clients[MAX_CLI
 

	
 
// The listen socket for the server
 
static SOCKET _listensocket;
 

	
 
// The amount of clients connected
 
static byte _network_clients_connected = 0;
 
// The index counter for new clients (is never decreased)
 
static uint16 _network_client_index = NETWORK_SERVER_INDEX + 1;
 
// The identifier counter for new clients (is never decreased)
 
static ClientID _network_client_id = CLIENT_ID_FIRST;
 

	
 
/* Some externs / forwards */
 
extern void StateGameLoop();
 

	
 
// Function that looks up the CI for a given client-index
 
NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index)
 
// Function that looks up the CI for a given client-identifier
 
NetworkClientInfo *NetworkFindClientInfoFromIndex(ClientID client_id)
 
{
 
	NetworkClientInfo *ci;
 

	
 
	for (ci = _network_client_info; ci != endof(_network_client_info); ci++) {
 
		if (ci->client_index == client_index) return ci;
 
		if (ci->client_id == client_id) return ci;
 
	}
 

	
 
	return NULL;
 
}
 

	
 
/** Return the CI for a given IP
 
@@ -122,32 +124,32 @@ NetworkClientInfo *NetworkFindClientInfo
 
		if (ci->client_ip == ip_number) return ci;
 
	}
 

	
 
	return NULL;
 
}
 

	
 
// Function that looks up the CS for a given client-index
 
NetworkTCPSocketHandler *NetworkFindClientStateFromIndex(uint16 client_index)
 
// Function that looks up the CS for a given client-identifier
 
NetworkTCPSocketHandler *NetworkFindClientStateFromClientID(ClientID client_id)
 
{
 
	NetworkTCPSocketHandler *cs;
 

	
 
	for (cs = _clients; cs != endof(_clients); cs++) {
 
		if (cs->index == client_index) return cs;
 
		if (cs->client_id == client_id) return cs;
 
	}
 

	
 
	return NULL;
 
}
 

	
 
// NetworkGetClientName is a server-safe function to get the name of the client
 
//  if the user did not send it yet, Client #<no> is used.
 
void NetworkGetClientName(char *client_name, size_t size, const NetworkTCPSocketHandler *cs)
 
{
 
	const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 

	
 
	if (ci->client_name[0] == '\0') {
 
		snprintf(client_name, size, "Client #%4d", cs->index);
 
		snprintf(client_name, size, "Client #%4d", cs->client_id);
 
	} else {
 
		ttd_strlcpy(client_name, ci->client_name, size);
 
	}
 
}
 

	
 
byte NetworkSpectatorCount()
 
@@ -358,19 +360,19 @@ void CheckMinActiveClients()
 

	
 
	if (NetworkCountActiveClients() < _settings_client.network.min_active_clients) {
 
		if (_min_active_clients_paused) return;
 

	
 
		_min_active_clients_paused = true;
 
		DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
 
		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (not enough players)", NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (not enough players)", CLIENT_ID_SERVER);
 
	} else {
 
		if (!_min_active_clients_paused) return;
 

	
 
		_min_active_clients_paused = false;
 
		DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
 
		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", CLIENT_ID_SERVER);
 
	}
 
}
 

	
 
/** Converts a string to ip/port/company
 
 *  Format: IP#company:port
 
 *
 
@@ -417,14 +419,14 @@ static NetworkTCPSocketHandler *NetworkA
 
	cs->last_frame_server = _frame_counter;
 

	
 
	if (_network_server) {
 
		NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 
		memset(ci, 0, sizeof(*ci));
 

	
 
		cs->index = _network_client_index++;
 
		ci->client_index = cs->index;
 
		cs->client_id = _network_client_id++;
 
		ci->client_id = cs->client_id;
 
		ci->client_playas = COMPANY_INACTIVE_CLIENT;
 
		ci->join_date = _date;
 

	
 
		InvalidateWindow(WC_CLIENT_LIST, 0);
 
	}
 

	
 
@@ -438,13 +440,13 @@ void NetworkCloseClient(NetworkTCPSocket
 
	// Socket is already dead
 
	if (cs->sock == INVALID_SOCKET) {
 
		cs->has_quit = true;
 
		return;
 
	}
 

	
 
	DEBUG(net, 1, "Closed client connection %d", cs->index);
 
	DEBUG(net, 1, "Closed client connection %d", cs->client_id);
 

	
 
	if (!cs->has_quit && _network_server && cs->status > STATUS_INACTIVE) {
 
		// We did not receive a leave message from this client...
 
		NetworkErrorCode errorno = NETWORK_ERROR_CONNECTION_LOST;
 
		char str[100];
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
@@ -456,21 +458,21 @@ void NetworkCloseClient(NetworkTCPSocket
 

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

	
 
		// Inform other clients of this... strange leaving ;)
 
		FOR_ALL_CLIENTS(new_cs) {
 
			if (new_cs->status > STATUS_AUTH && cs != new_cs) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
 
				SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, errorno);
 
			}
 
		}
 
	}
 

	
 
	/* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
 
	if (cs->status == STATUS_PRE_ACTIVE && _settings_client.network.pause_on_join) {
 
		DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
 
		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", CLIENT_ID_SERVER);
 
	}
 

	
 
	cs->Destroy();
 

	
 
	// Close the gap in the client-list
 
	ci = DEREF_CLIENT_INFO(cs);
 
@@ -490,14 +492,14 @@ void NetworkCloseClient(NetworkTCPSocket
 
		InvalidateWindow(WC_CLIENT_LIST, 0);
 
	}
 

	
 
	// Reset the status of the last socket
 
	cs->sock = INVALID_SOCKET;
 
	cs->status = STATUS_INACTIVE;
 
	cs->index = NETWORK_EMPTY_INDEX;
 
	ci->client_index = NETWORK_EMPTY_INDEX;
 
	cs->client_id = INVALID_CLIENT_ID;
 
	ci->client_id = INVALID_CLIENT_ID;
 

	
 
	CheckMinActiveClients();
 
}
 

	
 
// A client wants to connect to a server
 
static bool NetworkConnect(const char *hostname, int port)
 
@@ -805,17 +807,17 @@ static void NetworkInitGameInfo()
 

	
 
	/* The server is a client too */
 
	_network_game_info.clients_on = _network_dedicated ? 0 : 1;
 
	_network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
 

	
 
	// We use _network_client_info[MAX_CLIENT_INFO - 1] to store the server-data in it
 
	//  The index is NETWORK_SERVER_INDEX ( = 1)
 
	//  The client identifier is CLIENT_ID_SERVER ( = 1)
 
	ci = &_network_client_info[MAX_CLIENT_INFO - 1];
 
	memset(ci, 0, sizeof(*ci));
 

	
 
	ci->client_index = NETWORK_SERVER_INDEX;
 
	ci->client_id = CLIENT_ID_SERVER;
 
	ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : _local_company;
 

	
 
	strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name));
 
	strecpy(ci->unique_id, _settings_client.network.network_id, lastof(ci->unique_id));
 
}
 

	
 
@@ -837,13 +839,13 @@ bool NetworkServerStart()
 
	_network_server = true;
 
	_networking = true;
 
	_frame_counter = 0;
 
	_frame_counter_server = 0;
 
	_frame_counter_max = 0;
 
	_last_sync_frame = 0;
 
	_network_own_client_index = NETWORK_SERVER_INDEX;
 
	_network_own_client_id = CLIENT_ID_SERVER;
 

	
 
	/* Non-dedicated server will always be company #1 */
 
	if (!_network_dedicated) _network_playas = COMPANY_FIRST;
 

	
 
	_network_clients_connected = 0;
 

	
src/network/network_chat_gui.cpp
Show inline comments
 
@@ -256,13 +256,13 @@ void NetworkDrawChatMessage()
 
static void SendChat(const char *buf, DestType type, int dest)
 
{
 
	if (StrEmpty(buf)) return;
 
	if (!_network_server) {
 
		SEND_COMMAND(PACKET_CLIENT_CHAT)((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf);
 
	} else {
 
		NetworkServerSendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, NETWORK_SERVER_INDEX);
 
		NetworkServerSendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, CLIENT_ID_SERVER);
 
	}
 
}
 

	
 

	
 
struct NetworkChatWindow : public QueryStringBaseWindow {
 
	DestType dtype;
 
@@ -298,13 +298,13 @@ struct NetworkChatWindow : public QueryS
 
	{
 
		static char chat_tab_temp_buffer[64];
 

	
 
		/* First, try clients */
 
		if (*item < MAX_CLIENT_INFO) {
 
			/* Skip inactive clients */
 
			while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
 
			while (_network_client_info[*item].client_id == INVALID_CLIENT_ID && *item < MAX_CLIENT_INFO) (*item)++;
 
			if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
 
		}
 

	
 
		/* Then, try townnames */
 
		/* Not that the following assumes all town indices are adjacent, ie no
 
		* towns have been deleted. */
src/network/network_client.cpp
Show inline comments
 
@@ -241,21 +241,21 @@ DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLI
 
	//
 
	// Packet: CLIENT_CHAT
 
	// Function: Send a chat-packet to the serve
 
	// Data:
 
	//    uint8:  ActionID (see network_data.h, NetworkAction)
 
	//    uint8:  Destination Type (see network_data.h, DestType);
 
	//    uint16: Destination Company/Client
 
	//    uint32: Destination CompanyID/Client-identifier
 
	//    String: Message (max NETWORK_CHAT_LENGTH)
 
	//
 

	
 
	Packet *p = NetworkSend_Init(PACKET_CLIENT_CHAT);
 

	
 
	p->Send_uint8 (action);
 
	p->Send_uint8 (type);
 
	p->Send_uint16(dest);
 
	p->Send_uint32(dest);
 
	p->Send_string(msg);
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
// Send an error-packet over the network
 
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno)
 
@@ -389,29 +389,29 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
	}
 

	
 
	return NETWORK_RECV_STATUS_CLOSE_QUERY;
 
}
 

	
 
// This packet contains info about the client (playas and name)
 
//  as client we save this in NetworkClientInfo, linked via 'index'
 
//  as client we save this in NetworkClientInfo, linked via 'client_id'
 
//  which is always an unique number on a server.
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
 
{
 
	NetworkClientInfo *ci;
 
	uint16 index = p->Recv_uint16();
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 
	CompanyID playas = (CompanyID)p->Recv_uint8();
 
	char name[NETWORK_NAME_LENGTH];
 

	
 
	p->Recv_string(name, sizeof(name));
 

	
 
	if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
 

	
 
	/* Do we receive a change of data? Most likely we changed playas */
 
	if (index == _network_own_client_index) _network_playas = playas;
 
	if (client_id == _network_own_client_id) _network_playas = playas;
 

	
 
	ci = NetworkFindClientInfoFromIndex(index);
 
	ci = NetworkFindClientInfoFromIndex(client_id);
 
	if (ci != NULL) {
 
		if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
 
			// Client name changed, display the change
 
			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", name);
 
		} else if (playas != ci->client_playas) {
 
			// The client changed from client-player..
 
@@ -423,16 +423,16 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 

	
 
		InvalidateWindow(WC_CLIENT_LIST, 0);
 

	
 
		return NETWORK_RECV_STATUS_OKAY;
 
	}
 

	
 
	// We don't have this index yet, find an empty index, and put the data there
 
	ci = NetworkFindClientInfoFromIndex(NETWORK_EMPTY_INDEX);
 
	// We don't have this client_id yet, find an empty client_id, and put the data there
 
	ci = NetworkFindClientInfoFromIndex(INVALID_CLIENT_ID);
 
	if (ci != NULL) {
 
		ci->client_index = index;
 
		ci->client_id = client_id;
 
		ci->client_playas = playas;
 

	
 
		strecpy(ci->client_name, name, lastof(ci->client_name));
 

	
 
		InvalidateWindow(WC_CLIENT_LIST, 0);
 

	
 
@@ -527,13 +527,13 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
		default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
	}
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
 
{
 
	_network_own_client_index = p->Recv_uint16();
 
	_network_own_client_id = (ClientID)p->Recv_uint32();
 

	
 
	/* Initialize the password hash salting variables, even if they were previously. */
 
	_password_game_seed = p->Recv_uint32();
 
	p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
 

	
 
	// Start receiving the map
 
@@ -714,38 +714,38 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
 
{
 
	char name[NETWORK_NAME_LENGTH], msg[NETWORK_CHAT_LENGTH];
 
	const NetworkClientInfo *ci = NULL, *ci_to;
 

	
 
	NetworkAction action = (NetworkAction)p->Recv_uint8();
 
	uint16 index = p->Recv_uint16();
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 
	bool self_send = p->Recv_bool();
 
	p->Recv_string(msg, NETWORK_CHAT_LENGTH);
 

	
 
	ci_to = NetworkFindClientInfoFromIndex(index);
 
	ci_to = NetworkFindClientInfoFromIndex(client_id);
 
	if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY;
 

	
 
	/* Did we initiate the action locally? */
 
	if (self_send) {
 
		switch (action) {
 
			case NETWORK_ACTION_CHAT_CLIENT:
 
				/* For speaking to client we need the client-name */
 
				snprintf(name, sizeof(name), "%s", ci_to->client_name);
 
				ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
 
				ci = NetworkFindClientInfoFromIndex(_network_own_client_id);
 
				break;
 

	
 
			/* For speaking to company or giving money, we need the company-name */
 
			case NETWORK_ACTION_GIVE_MONEY:
 
				if (!IsValidCompanyID(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY;
 
				/* fallthrough */
 
			case NETWORK_ACTION_CHAT_COMPANY: {
 
				StringID str = IsValidCompanyID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
 
				SetDParam(0, ci_to->client_playas);
 

	
 
				GetString(name, str, lastof(name));
 
				ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
 
				ci = NetworkFindClientInfoFromIndex(_network_own_client_id);
 
			} break;
 

	
 
			default: NOT_REACHED(); break;
 
		}
 
	} else {
 
		/* Display message from somebody else */
 
@@ -758,64 +758,59 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
 
{
 
	char str[100];
 
	uint16 index;
 
	NetworkClientInfo *ci;
 

	
 
	index = p->Recv_uint16();
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 
	GetNetworkErrorMsg(str, (NetworkErrorCode)p->Recv_uint8(), lastof(str));
 

	
 
	ci = NetworkFindClientInfoFromIndex(index);
 
	ci = NetworkFindClientInfoFromIndex(client_id);
 
	if (ci != NULL) {
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str);
 

	
 
		// The client is gone, give the NetworkClientInfo free
 
		ci->client_index = NETWORK_EMPTY_INDEX;
 
		ci->client_id = INVALID_CLIENT_ID;
 
	}
 

	
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
 
{
 
	char str[100];
 
	uint16 index;
 
	NetworkClientInfo *ci;
 

	
 
	index = p->Recv_uint16();
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 
	p->Recv_string(str, lengthof(str));
 

	
 
	ci = NetworkFindClientInfoFromIndex(index);
 
	ci = NetworkFindClientInfoFromIndex(client_id);
 
	if (ci != NULL) {
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str);
 

	
 
		// The client is gone, give the NetworkClientInfo free
 
		ci->client_index = NETWORK_EMPTY_INDEX;
 
		ci->client_id = INVALID_CLIENT_ID;
 
	} else {
 
		DEBUG(net, 0, "Unknown client (%d) is leaving the game", index);
 
		DEBUG(net, 0, "Unknown client (%d) is leaving the game", client_id);
 
	}
 

	
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 

	
 
	// If we come here it means we could not locate the client.. strange :s
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
 
{
 
	uint16 index;
 
	NetworkClientInfo *ci;
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 

	
 
	index = p->Recv_uint16();
 

	
 
	ci = NetworkFindClientInfoFromIndex(index);
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_id);
 
	if (ci != NULL)
 
		NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name, "");
 

	
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
@@ -937,25 +932,25 @@ void NetworkClientSendRcon(const char *p
 
{
 
	SEND_COMMAND(PACKET_CLIENT_RCON)(password, command);
 
}
 

	
 
void NetworkUpdateClientName()
 
{
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_id);
 

	
 
	if (ci == NULL) return;
 

	
 
	/* Don't change the name if it is the same as the old name */
 
	if (strcmp(ci->client_name, _settings_client.network.client_name) != 0) {
 
		if (!_network_server) {
 
			SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_settings_client.network.client_name);
 
		} else {
 
			if (NetworkFindName(_settings_client.network.client_name)) {
 
				NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _settings_client.network.client_name);
 
				strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name));
 
				NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
 
				NetworkUpdateClientInfo(CLIENT_ID_SERVER);
 
			}
 
		}
 
	}
 
}
 

	
 
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg)
src/network/network_func.h
Show inline comments
 
@@ -11,14 +11,14 @@
 
#include "../console_type.h"
 

	
 
extern NetworkServerGameInfo _network_game_info;
 
extern NetworkCompanyInfo _network_company_info[MAX_COMPANIES];
 
extern NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
 

	
 
extern uint16 _network_own_client_index;
 
extern uint16 _redirect_console_to_client;
 
extern ClientID _network_own_client_id;
 
extern ClientID _redirect_console_to_client;
 
extern bool _network_need_advertise;
 
extern uint32 _network_last_advertise_frame;
 
extern uint8 _network_reconnect;
 
extern char *_network_host_list[10];
 
extern char *_network_ban_list[25];
 

	
 
@@ -33,36 +33,36 @@ void NetworkGameLoop();
 
void NetworkUDPGameLoop();
 
void NetworkUDPCloseAll();
 
void ParseConnectionString(const char **company, const char **port, char *connection_string);
 
void NetworkStartDebugLog(const char *hostname, uint16 port);
 
void NetworkPopulateCompanyInfo();
 

	
 
void NetworkUpdateClientInfo(uint16 client_index);
 
void NetworkUpdateClientInfo(ClientID client_id);
 
bool NetworkClientConnectGame(const char *host, uint16 port);
 
void NetworkClientSendRcon(const char *password, const char *command);
 
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg);
 
void NetworkClientSetPassword();
 

	
 
/*** Commands ran by the server ***/
 
void NetworkServerMonthlyLoop();
 
void NetworkServerYearlyLoop();
 
void NetworkServerChangeOwner(Owner current_owner, Owner new_owner);
 
void NetworkServerShowStatusToConsole();
 
bool NetworkServerStart();
 

	
 
NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
 
NetworkClientInfo *NetworkFindClientInfoFromIndex(ClientID client_id);
 
NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
 
const char* GetClientIP(const NetworkClientInfo *ci);
 

	
 
void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string);
 
void NetworkServerSendError(uint16 client_index, NetworkErrorCode error);
 
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
 
void NetworkServerSendRcon(ClientID client_id, ConsoleColour colour_code, const char *string);
 
void NetworkServerSendError(ClientID client_id, NetworkErrorCode error);
 
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id);
 

	
 
void NetworkInitChatMessage();
 
void CDECL NetworkAddChatMessage(uint16 color, uint8 duration, const char *message, ...);
 
void NetworkUndrawChatMessage();
 
void NetworkChatMessageDailyLoop();
 

	
 
#define FOR_ALL_ACTIVE_CLIENT_INFOS(ci) for (ci = _network_client_info; ci != endof(_network_client_info); ci++) if (ci->client_index != NETWORK_EMPTY_INDEX)
 
#define FOR_ALL_ACTIVE_CLIENT_INFOS(ci) for (ci = _network_client_info; ci != endof(_network_client_info); ci++) if (ci->client_id != INVALID_CLIENT_ID)
 

	
 
#endif /* ENABLE_NETWORK */
 
#endif /* NETWORK_FUNC_H */
src/network/network_gui.cpp
Show inline comments
 
@@ -1444,13 +1444,13 @@ static void ClientList_GiveMoney(byte cl
 
	}
 
}
 

	
 
static void ClientList_SpeakToClient(byte client_no)
 
{
 
	if (NetworkFindClientInfo(client_no) != NULL) {
 
		ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, NetworkFindClientInfo(client_no)->client_index);
 
		ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, NetworkFindClientInfo(client_no)->client_id);
 
	}
 
}
 

	
 
static void ClientList_SpeakToCompany(byte client_no)
 
{
 
	if (NetworkFindClientInfo(client_no) != NULL) {
 
@@ -1485,34 +1485,34 @@ struct NetworkClientListPopupWindow : Wi
 
		 * Watch is, max 50 chars long!
 
		 */
 

	
 
		const NetworkClientInfo *ci = NetworkFindClientInfo(client_no);
 

	
 
		int i = 0;
 
		if (_network_own_client_index != ci->client_index) {
 
		if (_network_own_client_id != ci->client_id) {
 
			GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(this->action[i]));
 
			this->proc[i++] = &ClientList_SpeakToClient;
 
		}
 

	
 
		if (IsValidCompanyID(ci->client_playas) || ci->client_playas == COMPANY_SPECTATOR) {
 
			GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(this->action[i]));
 
			this->proc[i++] = &ClientList_SpeakToCompany;
 
		}
 
		GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(this->action[i]));
 
		this->proc[i++] = &ClientList_SpeakToAll;
 

	
 
		if (_network_own_client_index != ci->client_index) {
 
		if (_network_own_client_id != ci->client_id) {
 
			/* We are no spectator and the company we want to give money to is no spectator and money gifts are allowed */
 
			if (IsValidCompanyID(_network_playas) && IsValidCompanyID(ci->client_playas) && _settings_game.economy.give_money) {
 
				GetString(this->action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(this->action[i]));
 
				this->proc[i++] = &ClientList_GiveMoney;
 
			}
 
		}
 

	
 
		/* A server can kick clients (but not himself) */
 
		if (_network_server && _network_own_client_index != ci->client_index) {
 
		if (_network_server && _network_own_client_id != ci->client_id) {
 
			GetString(this->action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(this->action[i]));
 
			this->proc[i++] = &ClientList_Kick;
 

	
 
			seprintf(this->action[i], lastof(this->action[i]), "Ban"); // XXX GetString?
 
			this->proc[i++] = &ClientList_Ban;
 
		}
 
@@ -1681,13 +1681,13 @@ struct NetworkClientListWindow : Window
 
				GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
 
				colour = TC_WHITE;
 
			} else {
 
				colour = TC_BLACK;
 
			}
 

	
 
			if (ci->client_index == NETWORK_SERVER_INDEX) {
 
			if (ci->client_id == CLIENT_ID_SERVER) {
 
				DrawString(4, y, STR_NETWORK_SERVER, colour);
 
			} else {
 
				DrawString(4, y, STR_NETWORK_CLIENT, colour);
 
			}
 

	
 
			/* Filter out spectators */
src/network/network_internal.h
Show inline comments
 
@@ -141,13 +141,13 @@ void NetworkAddCommandQueue(NetworkTCPSo
 
// from network.c
 
void NetworkCloseClient(NetworkTCPSocketHandler *cs);
 
void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...);
 
void NetworkGetClientName(char *clientname, size_t size, const NetworkTCPSocketHandler *cs);
 
uint NetworkCalculateLag(const NetworkTCPSocketHandler *cs);
 
byte NetworkGetCurrentLanguageIndex();
 
NetworkTCPSocketHandler *NetworkFindClientStateFromIndex(uint16 client_index);
 
NetworkTCPSocketHandler *NetworkFindClientStateFromClientID(ClientID client_id);
 
char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
 
bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
 

	
 
#define DEREF_CLIENT(i) (&_clients[i])
 
// This returns the NetworkClientInfo from a NetworkClientState
 
#define DEREF_CLIENT_INFO(cs) (&_network_client_info[cs - _clients])
src/network/network_server.cpp
Show inline comments
 
@@ -43,20 +43,20 @@ static void NetworkHandleCommandQueue(Ne
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkTCPSocketHandler *cs, NetworkClientInfo *ci)
 
{
 
	//
 
	// Packet: SERVER_CLIENT_INFO
 
	// Function: Sends info about a client
 
	// Data:
 
	//    uint16:  The index of the client (always unique on a server. 1 = server)
 
	//    uint32:  The identifier of the client (always unique on a server. 1 = server, 0 is invalid)
 
	//    uint8:  As which company the client is playing
 
	//    String: The name of the client
 
	//
 

	
 
	if (ci->client_index != NETWORK_EMPTY_INDEX) {
 
	if (ci->client_id != INVALID_CLIENT_ID) {
 
		Packet *p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
 
		p->Send_uint16(ci->client_index);
 
		p->Send_uint32(ci->client_id);
 
		p->Send_uint8 (ci->client_playas);
 
		p->Send_string(ci->client_name);
 

	
 
		cs->Send_Packet(p);
 
	}
 
}
 
@@ -162,17 +162,17 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
			if (new_cs->status > STATUS_AUTH && new_cs != cs) {
 
				// Some errors we filter to a more general error. Clients don't have to know the real
 
				//  reason a joining failed.
 
				if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
 
					error = NETWORK_ERROR_ILLEGAL_PACKET;
 

	
 
				SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, error);
 
				SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, error);
 
			}
 
		}
 
	} else {
 
		DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->index, str);
 
		DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->client_id, str);
 
	}
 

	
 
	cs->has_quit = true;
 

	
 
	// Make sure the data get's there before we close the connection
 
	cs->Send_Packets();
 
@@ -233,37 +233,37 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
 
{
 
	//
 
	// Packet: SERVER_WELCOME
 
	// Function: The client is joined and ready to receive his map
 
	// Data:
 
	//    uint16:  Own ClientID
 
	//    uint32:  Own Client identifier
 
	//
 

	
 
	Packet *p;
 
	NetworkTCPSocketHandler *new_cs;
 

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

	
 
	cs->status = STATUS_AUTH;
 
	_network_game_info.clients_on++;
 

	
 
	p = NetworkSend_Init(PACKET_SERVER_WELCOME);
 
	p->Send_uint16(cs->index);
 
	p->Send_uint32(cs->client_id);
 
	p->Send_uint32(_settings_game.game_creation.generation_seed);
 
	p->Send_string(_settings_client.network.network_id);
 
	cs->Send_Packet(p);
 

	
 
		// Transmit info about all the active clients
 
	FOR_ALL_CLIENTS(new_cs) {
 
		if (new_cs != cs && new_cs->status > STATUS_AUTH)
 
			SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, DEREF_CLIENT_INFO(new_cs));
 
	}
 
	// Also send the info of the server
 
	SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX));
 
	SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromIndex(CLIENT_ID_SERVER));
 
}
 

	
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WAIT)
 
{
 
	//
 
	// Packet: PACKET_SERVER_WAIT
 
@@ -399,26 +399,26 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MA
 
			// Not everything is sent, decrease the sent_packets
 
			if (sent_packets > 1) sent_packets /= 2;
 
		}
 
	}
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkTCPSocketHandler *cs, uint16 client_index)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkTCPSocketHandler *cs, ClientID client_id)
 
{
 
	//
 
	// Packet: SERVER_JOIN
 
	// Function: A client is joined (all active clients receive this after a
 
	//     PACKET_CLIENT_MAP_OK) Mostly what directly follows is a
 
	//     PACKET_SERVER_CLIENT_INFO
 
	// Data:
 
	//    uint16:  Client-Index
 
	//    uint32:  Client-identifier
 
	//
 

	
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_JOIN);
 

	
 
	p->Send_uint16(client_index);
 
	p->Send_uint32(client_id);
 

	
 
	cs->Send_Packet(p);
 
}
 

	
 

	
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_FRAME)
 
@@ -496,66 +496,66 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	p->Send_uint32(cp->frame);
 
	p->Send_bool  (cp->my_cmd);
 

	
 
	cs->Send_Packet(p);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkTCPSocketHandler *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkTCPSocketHandler *cs, NetworkAction action, ClientID client_id, bool self_send, const char *msg)
 
{
 
	//
 
	// Packet: SERVER_CHAT
 
	// Function: Sends a chat-packet to the client
 
	// Data:
 
	//    uint8:  ActionID (see network_data.h, NetworkAction)
 
	//    uint16:  Client-index
 
	//    uint32:  Client-identifier
 
	//    String: Message (max NETWORK_CHAT_LENGTH)
 
	//
 

	
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_CHAT);
 

	
 
	p->Send_uint8 (action);
 
	p->Send_uint16(client_index);
 
	p->Send_uint32(client_id);
 
	p->Send_bool  (self_send);
 
	p->Send_string(msg);
 

	
 
	cs->Send_Packet(p);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkTCPSocketHandler *cs, uint16 client_index, NetworkErrorCode errorno)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkTCPSocketHandler *cs, ClientID client_id, NetworkErrorCode errorno)
 
{
 
	//
 
	// Packet: SERVER_ERROR_QUIT
 
	// Function: One of the clients made an error and is quiting the game
 
	//      This packet informs the other clients of that.
 
	// Data:
 
	//    uint16:  Client-index
 
	//    uint32:  Client-identifier
 
	//    uint8:  ErrorID (see network_data.h, NetworkErrorCode)
 
	//
 

	
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR_QUIT);
 

	
 
	p->Send_uint16(client_index);
 
	p->Send_uint32(client_id);
 
	p->Send_uint8 (errorno);
 

	
 
	cs->Send_Packet(p);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkTCPSocketHandler *cs, uint16 client_index, const char *leavemsg)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkTCPSocketHandler *cs, ClientID client_id, const char *leavemsg)
 
{
 
	//
 
	// Packet: SERVER_ERROR_QUIT
 
	// Function: A client left the game, and this packets informs the other clients
 
	//      of that.
 
	// Data:
 
	//    uint16:  Client-index
 
	//    uint32:  Client-identifier
 
	//    String: leave-message
 
	//
 

	
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_QUIT);
 

	
 
	p->Send_uint16(client_index);
 
	p->Send_uint32(client_id);
 
	p->Send_string(leavemsg);
 

	
 
	cs->Send_Packet(p);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN)
 
@@ -797,21 +797,21 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
		cs->last_frame = _frame_counter;
 
		cs->last_frame_server = _frame_counter;
 

	
 
		FOR_ALL_CLIENTS(new_cs) {
 
			if (new_cs->status > STATUS_AUTH) {
 
				SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, DEREF_CLIENT_INFO(cs));
 
				SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->index);
 
				SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->client_id);
 
			}
 
		}
 

	
 
		if (_settings_client.network.pause_on_join) {
 
			/* Now pause the game till the client is in sync */
 
			DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
 

	
 
			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
 
			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", CLIENT_ID_SERVER);
 
		}
 
	} else {
 
		// Wrong status for this packet, give a warning to client, and close connection
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
	}
 
}
 
@@ -822,24 +822,24 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
 * @param *ci client information for debugging output to console
 
 */
 
static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *ci)
 
{
 
	byte flags = GetCommandFlags(cp->cmd);
 

	
 
	if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
 
		IConsolePrintF(CC_ERROR, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetClientIP(ci));
 
	if (flags & CMD_SERVER && ci->client_id != CLIENT_ID_SERVER) {
 
		IConsolePrintF(CC_ERROR, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci));
 
		return false;
 
	}
 

	
 
	if (flags & CMD_OFFLINE) {
 
		IConsolePrintF(CC_ERROR, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetClientIP(ci));
 
		IConsolePrintF(CC_ERROR, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci));
 
		return false;
 
	}
 

	
 
	if (cp->cmd != CMD_COMPANY_CTRL && !IsValidCompanyID(cp->company) && ci->client_index != NETWORK_SERVER_INDEX) {
 
		IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_index, GetClientIP(ci));
 
	if (cp->cmd != CMD_COMPANY_CTRL && !IsValidCompanyID(cp->company) && ci->client_id != CLIENT_ID_SERVER) {
 
		IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci));
 
		return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
@@ -876,13 +876,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	}
 

	
 
	ci = DEREF_CLIENT_INFO(cs);
 

	
 
	/* Check if cp->cmd is valid */
 
	if (!IsValidCommand(cp->cmd)) {
 
		IConsolePrintF(CC_ERROR, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetClientIP(ci));
 
		IConsolePrintF(CC_ERROR, "WARNING: invalid command from client %d (IP: %s).", ci->client_id, GetClientIP(ci));
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
		free(cp);
 
		return;
 
	}
 

	
 
	if (!CheckCommandFlags(cp, ci)) {
 
@@ -974,13 +974,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
 

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

	
 
	FOR_ALL_CLIENTS(new_cs) {
 
		if (new_cs->status > STATUS_AUTH) {
 
			SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
 
			SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, errorno);
 
		}
 
	}
 

	
 
	cs->has_quit = true;
 
}
 

	
 
@@ -1003,13 +1003,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	NetworkGetClientName(client_name, sizeof(client_name), cs);
 

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

	
 
	FOR_ALL_CLIENTS(new_cs) {
 
		if (new_cs->status > STATUS_AUTH) {
 
			SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->index, str);
 
			SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->client_id, str);
 
		}
 
	}
 

	
 
	cs->has_quit = true;
 
}
 

	
 
@@ -1030,13 +1030,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 

	
 
		/* Now he is! Unpause the game */
 
		cs->status = STATUS_ACTIVE;
 

	
 
		if (_settings_client.network.pause_on_join) {
 
			DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
 
			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
 
			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", CLIENT_ID_SERVER);
 
		}
 

	
 
		CheckMinActiveClients();
 

	
 
		/* Execute script for, e.g. MOTD */
 
		IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
 
@@ -1047,46 +1047,46 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	// With those 2 values we can calculate the lag realtime
 
	cs->last_frame_server = _frame_counter;
 
}
 

	
 

	
 

	
 
void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
 
void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id)
 
{
 
	NetworkTCPSocketHandler *cs;
 
	const NetworkClientInfo *ci, *ci_own, *ci_to;
 

	
 
	switch (desttype) {
 
	case DESTTYPE_CLIENT:
 
		/* Are we sending to the server? */
 
		if (dest == NETWORK_SERVER_INDEX) {
 
			ci = NetworkFindClientInfoFromIndex(from_index);
 
		if ((ClientID)dest == CLIENT_ID_SERVER) {
 
			ci = NetworkFindClientInfoFromIndex(from_id);
 
			/* Display the text locally, and that is it */
 
			if (ci != NULL)
 
				NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColor(ci->client_playas), false, ci->client_name, "%s", msg);
 
		} else {
 
			/* Else find the client to send the message to */
 
			FOR_ALL_CLIENTS(cs) {
 
				if (cs->index == dest) {
 
					SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
 
				if (cs->client_id == (ClientID)dest) {
 
					SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_id, false, msg);
 
					break;
 
				}
 
			}
 
		}
 

	
 
		// Display the message locally (so you know you have sent it)
 
		if (from_index != dest) {
 
			if (from_index == NETWORK_SERVER_INDEX) {
 
				ci = NetworkFindClientInfoFromIndex(from_index);
 
				ci_to = NetworkFindClientInfoFromIndex(dest);
 
		if (from_id != (ClientID)dest) {
 
			if (from_id == CLIENT_ID_SERVER) {
 
				ci = NetworkFindClientInfoFromIndex(from_id);
 
				ci_to = NetworkFindClientInfoFromIndex((ClientID)dest);
 
				if (ci != NULL && ci_to != NULL)
 
					NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
 
			} else {
 
				FOR_ALL_CLIENTS(cs) {
 
					if (cs->index == from_index) {
 
						SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, dest, true, msg);
 
					if (cs->client_id == from_id) {
 
						SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, (ClientID)dest, true, msg);
 
						break;
 
					}
 
				}
 
			}
 
		}
 
		break;
 
@@ -1094,56 +1094,56 @@ void NetworkServerSendChat(NetworkAction
 
		bool show_local = true; // If this is false, the message is already displayed
 
														// on the client who did sent it.
 
		/* Find all clients that belong to this company */
 
		ci_to = NULL;
 
		FOR_ALL_CLIENTS(cs) {
 
			ci = DEREF_CLIENT_INFO(cs);
 
			if (ci->client_playas == dest) {
 
				SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
 
				if (cs->index == from_index) show_local = false;
 
			if (ci->client_playas == (CompanyID)dest) {
 
				SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_id, false, msg);
 
				if (cs->client_id == from_id) show_local = false;
 
				ci_to = ci; // Remember a client that is in the company for company-name
 
			}
 
		}
 

	
 
		ci = NetworkFindClientInfoFromIndex(from_index);
 
		ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 
		ci = NetworkFindClientInfoFromIndex(from_id);
 
		ci_own = NetworkFindClientInfoFromIndex(CLIENT_ID_SERVER);
 
		if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
 
			NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColor(ci->client_playas), false, ci->client_name, "%s", msg);
 
			if (from_index == NETWORK_SERVER_INDEX) show_local = false;
 
			if (from_id == CLIENT_ID_SERVER) show_local = false;
 
			ci_to = ci_own;
 
		}
 

	
 
		/* There is no such client */
 
		if (ci_to == NULL) break;
 

	
 
		// Display the message locally (so you know you have sent it)
 
		if (ci != NULL && show_local) {
 
			if (from_index == NETWORK_SERVER_INDEX) {
 
			if (from_id == CLIENT_ID_SERVER) {
 
				char name[NETWORK_NAME_LENGTH];
 
				StringID str = IsValidCompanyID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
 
				SetDParam(0, ci_to->client_playas);
 
				GetString(name, str, lastof(name));
 
				NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColor(ci_own->client_playas), true, name, "%s", msg);
 
			} else {
 
				FOR_ALL_CLIENTS(cs) {
 
					if (cs->index == from_index) {
 
						SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_index, true, msg);
 
					if (cs->client_id == from_id) {
 
						SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_id, true, msg);
 
					}
 
				}
 
			}
 
		}
 
		}
 
		break;
 
	default:
 
		DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
 
		/* fall-through to next case */
 
	case DESTTYPE_BROADCAST:
 
		FOR_ALL_CLIENTS(cs) {
 
			SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
 
			SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_id, false, msg);
 
		}
 
		ci = NetworkFindClientInfoFromIndex(from_index);
 
		ci = NetworkFindClientInfoFromIndex(from_id);
 
		if (ci != NULL)
 
			NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColor(ci->client_playas), false, ci->client_name, "%s", msg);
 
		break;
 
	}
 
}
 

	
 
@@ -1154,29 +1154,29 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 
		return;
 
	}
 

	
 
	NetworkAction action = (NetworkAction)p->Recv_uint8();
 
	DestType desttype = (DestType)p->Recv_uint8();
 
	int dest = p->Recv_uint16();
 
	int dest = p->Recv_uint32();
 
	char msg[NETWORK_CHAT_LENGTH];
 

	
 
	p->Recv_string(msg, NETWORK_CHAT_LENGTH);
 

	
 
	const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 
	switch (action) {
 
		case NETWORK_ACTION_GIVE_MONEY:
 
			if (!IsValidCompanyID(ci->client_playas)) break;
 
			/* Fall-through */
 
		case NETWORK_ACTION_CHAT:
 
		case NETWORK_ACTION_CHAT_CLIENT:
 
		case NETWORK_ACTION_CHAT_COMPANY:
 
			NetworkServerSendChat(action, desttype, dest, msg, cs->index);
 
			NetworkServerSendChat(action, desttype, dest, msg, cs->client_id);
 
			break;
 
		default:
 
			IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_index, GetClientIP(ci));
 
			IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, GetClientIP(ci));
 
			SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
			break;
 
	}
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
 
@@ -1216,13 +1216,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 

	
 
	if (ci != NULL) {
 
		// Display change
 
		if (NetworkFindName(client_name)) {
 
			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", client_name);
 
			strecpy(ci->client_name, client_name, lastof(ci->client_name));
 
			NetworkUpdateClientInfo(ci->client_index);
 
			NetworkUpdateClientInfo(ci->client_id);
 
		}
 
	}
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
 
{
 
@@ -1232,21 +1232,21 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	if (StrEmpty(_settings_client.network.rcon_password)) return;
 

	
 
	p->Recv_string(pass, sizeof(pass));
 
	p->Recv_string(command, sizeof(command));
 

	
 
	if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
 
		DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
 
		DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->client_id);
 
		return;
 
	}
 

	
 
	DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->index, command);
 
	DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->client_id, command);
 

	
 
	_redirect_console_to_client = cs->index;
 
	_redirect_console_to_client = cs->client_id;
 
	IConsoleCmdExec(command);
 
	_redirect_console_to_client = 0;
 
	_redirect_console_to_client = INVALID_CLIENT_ID;
 
	return;
 
}
 

	
 
// The layout for the receive-functions by the server
 
typedef void NetworkServerPacket(NetworkTCPSocketHandler *cs, Packet *p);
 

	
 
@@ -1366,13 +1366,13 @@ void NetworkPopulateCompanyInfo()
 
			if (s->facilities & FACIL_BUS_STOP)   npi->num_station[2]++;
 
			if (s->facilities & FACIL_AIRPORT)    npi->num_station[3]++;
 
			if (s->facilities & FACIL_DOCK)       npi->num_station[4]++;
 
		}
 
	}
 

	
 
	ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 
	ci = NetworkFindClientInfoFromIndex(CLIENT_ID_SERVER);
 
	// Register local company (if not dedicated)
 
	if (ci != NULL && IsValidCompanyID(ci->client_playas))
 
		strecpy(_network_company_info[ci->client_playas].clients, ci->client_name, lastof(_network_company_info[ci->client_playas].clients));
 

	
 
	FOR_ALL_CLIENTS(cs) {
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
@@ -1387,17 +1387,17 @@ void NetworkPopulateCompanyInfo()
 

	
 
			strecat(_network_company_info[ci->client_playas].clients, client_name, lastof(_network_company_info[ci->client_playas].clients));
 
		}
 
	}
 
}
 

	
 
// Send a packet to all clients with updated info about this client_index
 
void NetworkUpdateClientInfo(uint16 client_index)
 
// Send a packet to all clients with updated info about this client_id
 
void NetworkUpdateClientInfo(ClientID client_id)
 
{
 
	NetworkTCPSocketHandler *cs;
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_id);
 

	
 
	if (ci == NULL) return;
 

	
 
	FOR_ALL_CLIENTS(cs) {
 
		SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, ci);
 
	}
 
@@ -1433,13 +1433,13 @@ static void NetworkAutoCleanCompanies()
 
	FOR_ALL_CLIENTS(cs) {
 
		ci = DEREF_CLIENT_INFO(cs);
 
		if (IsValidCompanyID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
 
	}
 

	
 
	if (!_network_dedicated) {
 
		ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 
		ci = NetworkFindClientInfoFromIndex(CLIENT_ID_SERVER);
 
		if (IsValidCompanyID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
 
	}
 

	
 
	/* Go through all the comapnies */
 
	FOR_ALL_COMPANIES(c) {
 
		/* Skip the non-active once */
 
@@ -1491,13 +1491,13 @@ bool NetworkFindName(char new_name[NETWO
 
				// Name already in use
 
				found_name = false;
 
				break;
 
			}
 
		}
 
		// Check if it is the same as the server-name
 
		ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 
		ci = NetworkFindClientInfoFromIndex(CLIENT_ID_SERVER);
 
		if (ci != NULL) {
 
			if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
 
		}
 

	
 
		if (!found_name) {
 
			// Try a new name (<name> #1, <name> #2, and so on)
 
@@ -1565,35 +1565,35 @@ void NetworkServer_Tick(bool send_frame)
 
			// 1 lag-point per day
 
			int lag = NetworkCalculateLag(cs) / DAY_TICKS;
 
			if (lag > 0) {
 
				if (lag > 3) {
 
					// Client did still not report in after 4 game-day, drop him
 
					//  (that is, the 3 of above, + 1 before any lag is counted)
 
					IConsolePrintF(CC_ERROR,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
 
					IConsolePrintF(CC_ERROR,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->client_id);
 
					NetworkCloseClient(cs);
 
					continue;
 
				}
 

	
 
				// Report once per time we detect the lag
 
				if (cs->lag_test == 0) {
 
					IConsolePrintF(CC_WARNING,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
 
					IConsolePrintF(CC_WARNING,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->client_id);
 
					cs->lag_test = 1;
 
				}
 
			} else {
 
				cs->lag_test = 0;
 
			}
 
		} else if (cs->status == STATUS_PRE_ACTIVE) {
 
			int lag = NetworkCalculateLag(cs);
 
			if (lag > _settings_client.network.max_join_time) {
 
				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _settings_client.network.max_join_time);
 
				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->client_id, _settings_client.network.max_join_time);
 
				NetworkCloseClient(cs);
 
			}
 
		} else if (cs->status == STATUS_INACTIVE) {
 
			int lag = NetworkCalculateLag(cs);
 
			if (lag > 4 * DAY_TICKS) {
 
				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS);
 
				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->client_id, 4 * DAY_TICKS);
 
				NetworkCloseClient(cs);
 
			}
 
		}
 

	
 
		if (cs->status >= STATUS_PRE_ACTIVE) {
 
			// Check if we can send command, and if we have anything in the queue
 
@@ -1625,26 +1625,26 @@ void NetworkServerMonthlyLoop()
 

	
 
void NetworkServerChangeOwner(Owner current_owner, Owner new_owner)
 
{
 
	/* The server has to handle all administrative issues, for example
 
	 * updating and notifying all clients of what has happened */
 
	NetworkTCPSocketHandler *cs;
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(CLIENT_ID_SERVER);
 

	
 
	/* The server has just changed from owner */
 
	if (current_owner == ci->client_playas) {
 
		ci->client_playas = new_owner;
 
		NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
 
		NetworkUpdateClientInfo(CLIENT_ID_SERVER);
 
	}
 

	
 
	/* Find all clients that were in control of this company, and mark them as new_owner */
 
	FOR_ALL_CLIENTS(cs) {
 
		ci = DEREF_CLIENT_INFO(cs);
 
		if (current_owner == ci->client_playas) {
 
			ci->client_playas = new_owner;
 
			NetworkUpdateClientInfo(ci->client_index);
 
			NetworkUpdateClientInfo(ci->client_id);
 
		}
 
	}
 
}
 

	
 
const char* GetClientIP(const NetworkClientInfo* ci)
 
{
 
@@ -1672,26 +1672,26 @@ void NetworkServerShowStatusToConsole()
 
		int lag = NetworkCalculateLag(cs);
 
		const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 
		const char* status;
 

	
 
		status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
 
		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
 
			cs->index, ci->client_name, status, lag,
 
			cs->client_id, ci->client_name, status, lag,
 
			ci->client_playas + (IsValidCompanyID(ci->client_playas) ? 1 : 0),
 
			GetClientIP(ci), ci->unique_id);
 
	}
 
}
 

	
 
void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string)
 
void NetworkServerSendRcon(ClientID client_id, ConsoleColour colour_code, const char *string)
 
{
 
	SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(client_index), colour_code, string);
 
	SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromClientID(client_id), colour_code, string);
 
}
 

	
 
void NetworkServerSendError(uint16 client_index, NetworkErrorCode error)
 
void NetworkServerSendError(ClientID client_id, NetworkErrorCode error)
 
{
 
	SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(client_index), error);
 
	SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromClientID(client_id), error);
 
}
 

	
 
bool NetworkCompanyHasClients(CompanyID company)
 
{
 
	const NetworkTCPSocketHandler *cs;
 
	const NetworkClientInfo *ci;
src/network/network_server.h
Show inline comments
 
@@ -5,13 +5,13 @@
 
#ifndef NETWORK_SERVER_H
 
#define NETWORK_SERVER_H
 

	
 
#ifdef ENABLE_NETWORK
 

	
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP);
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkTCPSocketHandler *cs, uint16 client_index, NetworkErrorCode errorno);
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkTCPSocketHandler *cs, ClientID client_id, NetworkErrorCode errorno);
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkTCPSocketHandler *cs, NetworkErrorCode error);
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN);
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkTCPSocketHandler *cs, uint16 color, const char *command);
 

	
 
bool NetworkServer_ReadPackets(NetworkTCPSocketHandler *cs);
src/network/network_type.h
Show inline comments
 
@@ -17,24 +17,31 @@ enum {
 
	 * How many clients can we have? Like.. MAX_COMPANIES is the amount of
 
	 *  companies that can really play.. so.. a max of 3 spectators.. gives us..
 
	 *  MAX_COMPANIES + 3
 
	 */
 
	MAX_CLIENTS = MAX_COMPANIES + 3,
 

	
 
	/** Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1 */
 
	MAX_CLIENT_INFO = MAX_CLIENTS + 1,
 

	
 
	/** Maximum number of internet interfaces supported. */
 
	MAX_INTERFACES = 9,
 

	
 
	/** How many vehicle/station types we put over the network */
 
	NETWORK_VEHICLE_TYPES = 5,
 
	NETWORK_STATION_TYPES = 5,
 
};
 

	
 
	NETWORK_SERVER_INDEX = 1,
 
	NETWORK_EMPTY_INDEX  = 0,
 
/** 'Unique' identifier to be given to clients */
 
enum ClientID {
 
	INVALID_CLIENT_ID = 0, ///< Client is not part of anything
 
	CLIENT_ID_SERVER  = 1, ///< Servers always have this ID
 
	CLIENT_ID_FIRST   = 2, ///< The first client ID
 
};
 

	
 
/** Indices into the client tables */
 
enum ClientIndex {
 
	/** Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1 */
 
	MAX_CLIENT_INFO = MAX_CLIENTS + 1,
 
};
 

	
 
struct NetworkCompanyInfo {
 
	char company_name[NETWORK_COMPANY_NAME_LENGTH]; ///< Company name
 
	char password[NETWORK_PASSWORD_LENGTH];         ///< The password for the company
 
	Year inaugurated_year;                          ///< What year the company started in
 
@@ -47,13 +54,13 @@ struct NetworkCompanyInfo {
 
	uint16 num_station[NETWORK_STATION_TYPES];      ///< How many stations are there of this type?
 
	char clients[NETWORK_CLIENTS_LENGTH];           ///< The clients that control this company (Name1, name2, ..)
 
	uint16 months_empty;                            ///< How many months the company is empty
 
};
 

	
 
struct NetworkClientInfo {
 
	uint16 client_index;                            ///< Index of the client (same as ClientState->index)
 
	ClientID client_id;                             ///< Client identifier (same as ClientState->client_id)
 
	char client_name[NETWORK_CLIENT_NAME_LENGTH];   ///< Name of the client
 
	byte client_lang;                               ///< The language of the client
 
	CompanyID client_playas;                        ///< As which company is this client playing (CompanyID)
 
	uint32 client_ip;                               ///< IP-address of the client (so he can be banned)
 
	Date join_date;                                 ///< Gamedate the client has joined
 
	char unique_id[NETWORK_UNIQUE_ID_LENGTH];       ///< Every play sends an unique id so we can indentify him
0 comments (0 inline, 0 general)