Changeset - r10907:3616576a3216
[Not reviewed]
master
0 15 0
rubidium - 16 years ago 2009-01-23 22:18:06
rubidium@openttd.org
(svn r15242) -Feature: allow moving clients between companies/spectators by the server and the clients themselves (dihedral)
15 files changed with 444 insertions and 11 deletions:
0 comments (0 inline, 0 general)
src/company_cmd.cpp
Show inline comments
 
@@ -752,8 +752,8 @@ CommandCost CmdCompanyCtrl(TileIndex til
 
				break;
 
			}
 

	
 
			/* This is the joining client who wants a new company */
 
			if (_local_company != _network_playas && _network_playas == c->index) {
 
			/* This is the client (or non-dedicated server) who wants a new company */
 
			if (cid == _network_own_client_id) {
 
				assert(_local_company == COMPANY_SPECTATOR);
 
				SetLocalCompany(c->index);
 
				if (!StrEmpty(_settings_client.network.default_company_pass)) {
 
@@ -780,6 +780,7 @@ CommandCost CmdCompanyCtrl(TileIndex til
 
				/* 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) */
 
				CompanyID old_playas = ci->client_playas;
 
				ci->client_playas = c->index;
 
				NetworkUpdateClientInfo(ci->client_id);
 

	
 
@@ -787,6 +788,7 @@ CommandCost CmdCompanyCtrl(TileIndex til
 
					CompanyID company_backup = _local_company;
 
					_network_company_states[c->index].months_empty = 0;
 
					_network_company_states[c->index].password[0] = '\0';
 
					NetworkServerUpdateCompanyPassworded(ci->client_playas, false);
 

	
 
					/* XXX - When a client joins, we automatically set its name to the
 
					* client's name (for some reason). As it stands now only the server
 
@@ -803,6 +805,11 @@ CommandCost CmdCompanyCtrl(TileIndex til
 
					NetworkSend_Command(0, 0, 0, CMD_RENAME_PRESIDENT, NULL, ci->client_name);
 
					_local_company = company_backup;
 
				}
 

	
 
				/* Announce new company on network, if the client was a SPECTATOR before */
 
				if (old_playas == COMPANY_SPECTATOR) {
 
					NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, ci->client_playas + 1);
 
				}
 
			}
 
#endif /* ENABLE_NETWORK */
 
		} break;
src/company_gui.cpp
Show inline comments
 
@@ -13,6 +13,7 @@
 
#include "command_func.h"
 
#include "network/network.h"
 
#include "network/network_gui.h"
 
#include "network/network_func.h"
 
#include "variables.h"
 
#include "roadveh.h"
 
#include "train.h"
 
@@ -1054,6 +1055,7 @@ enum CompanyWindowWidgets {
 
	CW_WIDGET_BUY_SHARE,
 
	CW_WIDGET_SELL_SHARE,
 
	CW_WIDGET_COMPANY_PASSWORD,
 
	CW_WIDGET_COMPANY_JOIN,
 
};
 

	
 
static const Widget _company_widgets[] = {
 
@@ -1069,6 +1071,7 @@ static const Widget _company_widgets[] =
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     0,   179,   158,   169, STR_7077_BUY_25_SHARE_IN_COMPANY,  STR_7079_BUY_25_SHARE_IN_THIS_COMPANY},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   180,   359,   158,   169, STR_7078_SELL_25_SHARE_IN_COMPANY, STR_707A_SELL_25_SHARE_IN_THIS_COMPANY},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   266,   355,   138,   149, STR_COMPANY_PASSWORD,              STR_COMPANY_PASSWORD_TOOLTIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   266,   355,    46,    57, STR_COMPANY_JOIN,                  STR_COMPANY_JOIN_TIP},
 
{   WIDGETS_END},
 
};
 

	
 
@@ -1187,6 +1190,8 @@ struct CompanyWindow : Window
 
		this->SetWidgetHiddenState(CW_WIDGET_BUY_SHARE,        local);
 
		this->SetWidgetHiddenState(CW_WIDGET_SELL_SHARE,       local);
 
		this->SetWidgetHiddenState(CW_WIDGET_COMPANY_PASSWORD, !local || !_networking);
 
		this->SetWidgetHiddenState(CW_WIDGET_COMPANY_JOIN,     local || !_networking);
 
		this->SetWidgetDisabledState(CW_WIDGET_COMPANY_JOIN,   !IsHumanCompany(c->index));
 

	
 
		if (!local) {
 
			if (_settings_game.economy.allow_shares) { // Shares are allowed
 
@@ -1298,6 +1303,22 @@ struct CompanyWindow : Window
 
			case CW_WIDGET_COMPANY_PASSWORD:
 
				if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this);
 
				break;
 

	
 
			case CW_WIDGET_COMPANY_JOIN: {
 
				this->query_widget = CW_WIDGET_COMPANY_JOIN;
 
				CompanyID company = (CompanyID)this->window_number;
 
				if (_network_server) {
 
					NetworkServerDoMove(CLIENT_ID_SERVER, company);
 
					MarkWholeScreenDirty();
 
				} else if (NetworkCompanyIsPassworded(company)) {
 
					/* ask for the password */
 
					ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, 20, 180, this, CS_ALPHANUMERAL, QSF_NONE);
 
				} else {
 
					/* just send the join command */
 
					NetworkClientRequestMove(company);
 
				}
 
				break;
 
			}
 
#endif /* ENABLE_NETWORK */
 
		}
 
	}
 
@@ -1335,6 +1356,12 @@ struct CompanyWindow : Window
 
			case CW_WIDGET_COMPANY_NAME:
 
				DoCommandP(0, 0, 0, CMD_RENAME_COMPANY | CMD_MSG(STR_700C_CAN_T_CHANGE_COMPANY_NAME), NULL, str);
 
				break;
 

	
 
#ifdef ENABLE_NETWORK
 
			case CW_WIDGET_COMPANY_JOIN:
 
				NetworkClientRequestMove((CompanyID)this->window_number, str);
 
				break;
 
#endif /* ENABLE_NETWORK */
 
		}
 
	}
 
};
src/console_cmds.cpp
Show inline comments
 
@@ -622,6 +622,86 @@ DEF_CONSOLE_CMD(ConKick)
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConJoinCompany)
 
{
 
	if (argc < 2) {
 
		IConsoleHelp("Request joining another company. Usage: join <company-id> [<password>]");
 
		IConsoleHelp("For valid company-id see company list, use 255 for spectator");
 
		return true;
 
	}
 

	
 
	CompanyID company_id = (CompanyID)(atoi(argv[1]) <= MAX_COMPANIES ? atoi(argv[1]) - 1 : atoi(argv[1]));
 

	
 
	/* Check we have a valid company id! */
 
	if (!IsValidCompanyID(company_id) && company_id != COMPANY_SPECTATOR) {
 
		IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_COMPANIES);
 
		return true;
 
	}
 

	
 
	if (NetworkFindClientInfoFromClientID(_network_own_client_id)->client_playas == company_id) {
 
		IConsoleError("You are already there!");
 
		return true;
 
	}
 

	
 
	if (company_id == COMPANY_SPECTATOR && NetworkMaxSpectatorsReached()) {
 
		IConsoleError("Cannot join spectators, maximum number of spectators reached.");
 
		return true;
 
	}
 

	
 
	/* Check if the company requires a password */
 
	if (NetworkCompanyIsPassworded(company_id) && argc < 3) {
 
		IConsolePrintF(CC_ERROR, "Company %d requires a password to join.", company_id + 1);
 
		return true;
 
	}
 

	
 
	/* non-dedicated server may just do the move! */
 
	if (_network_server) {
 
		NetworkServerDoMove(CLIENT_ID_SERVER, company_id);
 
	} else {
 
		NetworkClientRequestMove(company_id, NetworkCompanyIsPassworded(company_id) ? argv[2] : "");
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConMoveClient)
 
{
 
	if (argc < 3) {
 
		IConsoleHelp("Move a client to another company. Usage: move <client-id> <company-id>");
 
		IConsoleHelp("For valid client-id see 'clients', for valid company-id see 'companies', use 255 for moving to spectators");
 
		return true;
 
	}
 

	
 
	const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID((ClientID)atoi(argv[1]));
 
	CompanyID company_id = (CompanyID)(atoi(argv[2]) <= MAX_COMPANIES ? atoi(argv[2]) - 1 : atoi(argv[2]));
 

	
 
	/* check the client exists */
 
	if (ci == NULL) {
 
		IConsoleError("Invalid client-id, check the command 'clients' for valid client-id's.");
 
		return true;
 
	}
 

	
 
	if (!IsValidCompanyID(company_id) && company_id != COMPANY_SPECTATOR) {
 
		IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_COMPANIES);
 
		return true;
 
	}
 

	
 
	if (ci->client_id == CLIENT_ID_SERVER && _network_dedicated) {
 
		IConsoleError("Silly boy, you cannot move the server!");
 
		return true;
 
	}
 

	
 
	if (ci->client_playas == company_id) {
 
		IConsoleError("You cannot move someone to where he/she already is!");
 
		return true;
 
	}
 

	
 
	/* we are the server, so force the update */
 
	NetworkServerDoMove(ci->client_id, company_id);
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConResetCompany)
 
{
 
	CompanyID index;
 
@@ -1703,7 +1783,6 @@ void IConsoleStdLibRegister()
 

	
 
	IConsoleCmdRegister("connect",         ConNetworkConnect);
 
	IConsoleCmdHookAdd("connect",          ICONSOLE_HOOK_ACCESS, ConHookClientOnly);
 
	IConsoleAliasRegister("join",          "connect %A");
 
	IConsoleCmdRegister("clients",         ConNetworkClients);
 
	IConsoleCmdHookAdd("clients",          ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("status",          ConStatus);
 
@@ -1714,6 +1793,11 @@ void IConsoleStdLibRegister()
 
	IConsoleCmdRegister("rcon",            ConRcon);
 
	IConsoleCmdHookAdd("rcon",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 

	
 
	IConsoleCmdRegister("join",            ConJoinCompany);
 
	IConsoleCmdHookAdd("join",             ICONSOLE_HOOK_ACCESS, ConHookClientOnly);
 
	IConsoleAliasRegister("spectate",      "join 255");
 
	IConsoleCmdRegister("move",            ConMoveClient);
 
	IConsoleCmdHookAdd("move",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("reset_company",   ConResetCompany);
 
	IConsoleCmdHookAdd("reset_company",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleAliasRegister("clean_company", "reset_company %A");
src/lang/english.txt
Show inline comments
 
@@ -1560,6 +1560,8 @@ STR_NETWORK_GIVE_MONEY_CAPTION          
 
STR_NETWORK_NEED_GAME_PASSWORD_CAPTION                          :{WHITE}Server is protected. Enter password
 
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION                       :{WHITE}Company is protected. Enter password
 
STR_NETWORK_CLIENT_LIST                                         :{WHITE}Client List
 
STR_NETWORK_COMPANY_LIST_SPECTATE                               :{WHITE}Spectate
 
STR_NETWORK_COMPANY_LIST_NEW_COMPANY                            :{WHITE}New Company
 

	
 
STR_NETWORK_ERR_NOTAVAILABLE                                    :{WHITE} No network devices found or compiled without ENABLE_NETWORK
 
STR_NETWORK_ERR_NOSERVER                                        :{WHITE} Could not find any network games
 
@@ -1606,6 +1608,9 @@ STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED
 
############ End of leave-in-this-order
 
STR_NETWORK_CLIENT_LEAVING                                      :leaving
 
STR_NETWORK_CLIENT_JOINED                                       :*** {RAW_STRING} has joined the game
 
STR_NETWORK_CLIENT_COMPANY_JOIN                                 :*** {RAW_STRING} has joined company #{2:NUM}
 
STR_NETWORK_CLIENT_COMPANY_SPECTATE                             :*** {RAW_STRING} has joined spectators
 
STR_NETWORK_CLIENT_COMPANY_NEW                                  :*** {RAW_STRING} has started a new company (#{2:NUM})
 
STR_NETWORK_CLIENT_LEFT                                         :*** {RAW_STRING} has left the game ({2:STRING})
 
STR_NETWORK_NAME_CHANGE                                         :*** {RAW_STRING} has changed his/her name to {RAW_STRING}
 
STR_NETWORK_GIVE_MONEY                                          :*** {RAW_STRING} gave your company {2:CURRENCY}
 
@@ -2405,6 +2410,8 @@ STR_RELOCATE_COMPANY_HEADQUARTERS       
 
STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS                       :{WHITE}Can't build company headquarters...
 
STR_7072_VIEW_HQ                                                :{BLACK}View HQ
 
STR_RELOCATE_HQ                                                 :{BLACK}Relocate HQ
 
STR_COMPANY_JOIN                                                :{BLACK}Join
 
STR_COMPANY_JOIN_TIP                                            :{BLACK}Join and play as this company
 
STR_COMPANY_PASSWORD                                            :{BLACK}Password
 
STR_COMPANY_PASSWORD_TOOLTIP                                    :{BLACK}Password-protect your company to prevent unauthorised users from joining.
 
STR_SET_COMPANY_PASSWORD                                        :{BLACK}Set company password
src/network/core/tcp_game.h
Show inline comments
 
@@ -54,6 +54,10 @@ enum {
 
	PACKET_CLIENT_RCON,
 
	PACKET_SERVER_CHECK_NEWGRFS,
 
	PACKET_CLIENT_NEWGRFS_CHECKED,
 
	PACKET_SERVER_MOVE,
 
	PACKET_CLIENT_MOVE,
 
	PACKET_SERVER_COMPANY_UPDATE,
 
	PACKET_SERVER_CONFIG_UPDATE,
 
	PACKET_END                   ///< Must ALWAYS be on the end of this list!! (period)
 
};
 

	
src/network/network.cpp
Show inline comments
 
@@ -75,6 +75,7 @@ bool _network_first_time;
 
bool _network_udp_server;
 
uint16 _network_udp_broadcast;
 
uint8 _network_advertise_retries;
 
CompanyMask _network_company_passworded; ///< Bitmask of the password status of all companies.
 

	
 
/* Check whether NETWORK_NUM_LANDSCAPES is still in sync with NUM_LANDSCAPE */
 
assert_compile((int)NETWORK_NUM_LANDSCAPES == (int)NUM_LANDSCAPE);
 
@@ -182,6 +183,16 @@ byte NetworkSpectatorCount()
 
	return count;
 
}
 

	
 
/**
 
 * Check if the company we want to join requires a password.
 
 * @param company_id id of the company we want to check the 'passworded' flag for.
 
 * @return true if the company requires a password.
 
 */
 
bool NetworkCompanyIsPassworded(CompanyID company_id)
 
{
 
	return HasBit(_network_company_passworded, company_id);
 
}
 

	
 
// This puts a text-message to the console, or in the future, the chat-box,
 
//  (to keep it all a bit more general)
 
// If 'self_send' is true, this is the client who is sending the message
 
@@ -199,6 +210,18 @@ void NetworkTextMessage(NetworkAction ac
 
			color = CC_DEFAULT;
 
			data = STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED_PLAYERS + data;
 
			break;
 
		case NETWORK_ACTION_COMPANY_SPECTATOR:
 
			color = CC_DEFAULT;
 
			strid = STR_NETWORK_CLIENT_COMPANY_SPECTATE;
 
			break;
 
		case NETWORK_ACTION_COMPANY_JOIN:
 
			color = CC_DEFAULT;
 
			strid = STR_NETWORK_CLIENT_COMPANY_JOIN;
 
			break;
 
		case NETWORK_ACTION_COMPANY_NEW:
 
			color = CC_DEFAULT;
 
			strid = STR_NETWORK_CLIENT_COMPANY_NEW;
 
			break;
 
		case NETWORK_ACTION_JOIN:           strid = STR_NETWORK_CLIENT_JOINED; break;
 
		case NETWORK_ACTION_LEAVE:          strid = STR_NETWORK_CLIENT_LEFT; break;
 
		case NETWORK_ACTION_NAME_CHANGE:    strid = STR_NETWORK_NAME_CHANGE; break;
src/network/network_client.cpp
Show inline comments
 
@@ -7,6 +7,7 @@
 
#include "../stdafx.h"
 
#include "../debug.h"
 
#include "../openttd.h"
 
#include "../gfx_func.h"
 
#include "network_internal.h"
 
#include "core/tcp.h"
 
#include "network_client.h"
 
@@ -25,6 +26,7 @@
 
#include "../company_func.h"
 
#include "../company_base.h"
 
#include "../company_gui.h"
 
#include "../company_type.h"
 
#include "../settings_type.h"
 
#include "../rev.h"
 

	
 
@@ -43,6 +45,11 @@ static uint32 _password_game_seed;
 
/** The other bit of 'entropy' used to generate a salt for the company passwords. */
 
static char _password_server_unique_id[NETWORK_UNIQUE_ID_LENGTH];
 

	
 
/** Maximum number of companies of the currently joined server. */
 
static uint8 _network_server_max_companies;
 
/** Maximum number of spectators of the currently joined server. */
 
static uint8 _network_server_max_spectators;
 

	
 
/** Make sure the unique ID length is the same as a md5 hash. */
 
assert_compile(NETWORK_UNIQUE_ID_LENGTH == 16 * 2 + 1);
 

	
 
@@ -86,6 +93,10 @@ void HashCurrentCompanyPassword(const ch
 

	
 
	const char *new_pw = GenerateCompanyPasswordHash(password);
 
	strecpy(_network_company_states[_local_company].password, new_pw, lastof(_network_company_states[_local_company].password));
 

	
 
	if (_network_server) {
 
		NetworkServerUpdateCompanyPassworded(_local_company, !StrEmpty(_network_company_states[_local_company].password));
 
	}
 
}
 

	
 

	
 
@@ -315,6 +326,14 @@ DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLI
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_MOVE)(CompanyID company, const char *pass)
 
{
 
	Packet *p = NetworkSend_Init(PACKET_CLIENT_MOVE);
 
	p->Send_uint8(company);
 
	p->Send_string(GenerateCompanyPasswordHash(pass));
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 

	
 
// **********
 
// Receiving functions
 
@@ -811,6 +830,51 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MOVE)
 
{
 
	/* Nothing more in this packet... */
 
	ClientID client_id   = (ClientID)p->Recv_uint32();
 
	CompanyID company_id = (CompanyID)p->Recv_uint8();
 

	
 
	if (client_id == 0) {
 
		/* definitely an invalid client id, debug message and do nothing. */
 
		DEBUG(net, 0, "[move] received invalid client index = 0");
 
		return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
	}
 

	
 
	const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
 
	/* Just make sure we do not try to use a client_index that does not exist */
 
	if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
 

	
 
	/* if not valid player, force spectator, else check player exists */
 
	if (!IsValidCompanyID(company_id)) company_id = COMPANY_SPECTATOR;
 

	
 
	if (client_id == _network_own_client_id) {
 
		_network_playas = company_id;
 
		SetLocalCompany(company_id);
 

	
 
		/* Disable any buttons in any windows the client is now not supposed to get to, and do it fast. */
 
		/* Do this ASAP else the client has a chance of sending DoCommands with an incorrect company_id (=kick)! */
 
		MarkWholeScreenDirty();
 
	}
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE)
 
{
 
	_network_server_max_companies = p->Recv_uint8();
 
	_network_server_max_spectators = p->Recv_uint8();
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE)
 
{
 
	_network_company_passworded = p->Recv_uint16();
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 

	
 
// The layout for the receive-functions by the client
 
@@ -855,6 +919,10 @@ static NetworkClientPacket * const _netw
 
	NULL, /*PACKET_CLIENT_RCON,*/
 
	RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS),
 
	NULL, /*PACKET_CLIENT_NEWGRFS_CHECKED,*/
 
	RECEIVE_COMMAND(PACKET_SERVER_MOVE),
 
	NULL, /* PACKET_CLIENT_MOVE */
 
	RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE),
 
	RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE),
 
};
 

	
 
// If this fails, check the array above with network_data.h
 
@@ -897,6 +965,17 @@ void NetworkClientSendRcon(const char *p
 
	SEND_COMMAND(PACKET_CLIENT_RCON)(password, command);
 
}
 

	
 
/**
 
 * Notify the server of this client wanting to be moved to another company.
 
 * @param company_id id of the company the client wishes to be moved to.
 
 * @param pass the password, is only checked on the server end if a password is needed.
 
 * @return void
 
 */
 
void NetworkClientRequestMove(CompanyID company_id, const char *pass)
 
{
 
	SEND_COMMAND(PACKET_CLIENT_MOVE)(company_id, pass);
 
}
 

	
 
void NetworkUpdateClientName()
 
{
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(_network_own_client_id);
 
@@ -946,6 +1025,24 @@ bool NetworkClientPreferTeamChat(const N
 
}
 

	
 
/**
 
 * Check if max_companies has been reached on the server (local check only).
 
 * @return true if the max value has been reached or exceeded, false otherwise.
 
 */
 
bool NetworkMaxCompaniesReached()
 
{
 
	return ActiveCompanyCount() >= (_network_server ? _settings_client.network.max_companies : _network_server_max_companies);
 
}
 

	
 
/**
 
 * Check if max_spectatos has been reached on the server (local check only).
 
 * @return true if the max value has been reached or exceeded, false otherwise.
 
 */
 
bool NetworkMaxSpectatorsReached()
 
{
 
	return NetworkSpectatorCount() >= (_network_server ? _settings_client.network.max_spectators : _network_server_max_spectators);
 
}
 

	
 
/**
 
 * Print all the clients to the console
 
 */
 
void NetworkPrintClients()
src/network/network_client.h
Show inline comments
 
@@ -18,6 +18,7 @@ DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLI
 
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name);
 
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK);
 
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command);
 
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_MOVE)(CompanyID company, const char *pass);
 

	
 
NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientSocket *cs);
 
void NetworkClient_Connected();
src/network/network_func.h
Show inline comments
 
@@ -38,18 +38,24 @@ void NetworkPopulateCompanyStats(Network
 

	
 
void NetworkUpdateClientInfo(ClientID client_id);
 
void NetworkClientConnectGame(NetworkAddress address);
 
void NetworkClientRequestMove(CompanyID company, const char *pass = "");
 
void NetworkClientSendRcon(const char *password, const char *command);
 
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0);
 
void NetworkClientSetPassword(const char *password);
 
bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio);
 
bool NetworkCompanyIsPassworded(CompanyID company_id);
 
bool NetworkMaxCompaniesReached();
 
bool NetworkMaxSpectatorsReached();
 
void NetworkPrintClients();
 

	
 
/*** Commands ran by the server ***/
 
void NetworkServerMonthlyLoop();
 
void NetworkServerYearlyLoop();
 
void NetworkServerChangeOwner(Owner current_owner, Owner new_owner);
 
void NetworkServerSendConfigUpdate();
 
void NetworkServerShowStatusToConsole();
 
bool NetworkServerStart();
 
void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded);
 
bool NetworkServerChangeClientName(ClientID client_id, const char *new_name);
 

	
 
NetworkClientInfo *NetworkFindClientInfoFromIndex(ClientIndex index);
 
@@ -57,6 +63,7 @@ NetworkClientInfo *NetworkFindClientInfo
 
NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
 
const char *GetClientIP(const NetworkClientInfo *ci);
 

	
 
void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
 
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, int64 data = 0);
src/network/network_internal.h
Show inline comments
 
@@ -121,6 +121,8 @@ extern uint16 _network_udp_broadcast;
 

	
 
extern uint8 _network_advertise_retries;
 

	
 
extern CompanyMask _network_company_passworded;
 

	
 
void NetworkTCPQueryServer(NetworkAddress address);
 

	
 
void NetworkAddServer(const char *b);
src/network/network_server.cpp
Show inline comments
 
@@ -586,6 +586,32 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	cs->Send_Packet(p);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_MOVE)(NetworkClientSocket *cs, ClientID client_id, CompanyID company_id)
 
{
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_MOVE);
 

	
 
	p->Send_uint32(client_id);
 
	p->Send_uint8(company_id);
 
	cs->Send_Packet(p);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMPANY_UPDATE)(NetworkClientSocket *cs)
 
{
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_COMPANY_UPDATE);
 

	
 
	p->Send_uint16(_network_company_passworded);
 
	cs->Send_Packet(p);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)
 
{
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_CONFIG_UPDATE);
 

	
 
	p->Send_uint8(_settings_client.network.max_companies);
 
	p->Send_uint8(_settings_client.network.max_spectators);
 
	cs->Send_Packet(p);
 
}
 

	
 
// **********
 
// Receiving functions
 
//   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
 
@@ -803,6 +829,12 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 

	
 
			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "", CLIENT_ID_SERVER, NETWORK_SERVER_MESSAGE_GAME_PAUSED_CONNECT);
 
		}
 

	
 
		/* also update the new client with our max values */
 
		SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(cs);
 

	
 
		/* quickly update the syncing client with company details */
 
		SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(cs);
 
	} else {
 
		// Wrong status for this packet, give a warning to client, and close connection
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
@@ -872,6 +904,12 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
			return;
 
		}
 

	
 
		/* Check if we are full - else it's possible for spectators to send a CMD_COMPANY_CTRL and the company is created regardless of max_companies! */
 
		if (ActiveCompanyCount() >= _settings_client.network.max_companies) {
 
			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
 
			return;
 
		}
 

	
 
		/* XXX - Execute the command as a valid company. Normally this would be done by a
 
		 * spectator, but that is not allowed any commands. So do an impersonation. The drawback
 
		 * of this is that the first company's last_built_tile is also updated... */
 
@@ -1145,6 +1183,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 

	
 
	if (IsValidCompanyID(ci->client_playas)) {
 
		strecpy(_network_company_states[ci->client_playas].password, password, lastof(_network_company_states[ci->client_playas].password));
 
		NetworkServerUpdateCompanyPassworded(ci->client_playas, !StrEmpty(_network_company_states[ci->client_playas].password));
 
	}
 
}
 

	
 
@@ -1197,6 +1236,30 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	return;
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MOVE)
 
{
 
	CompanyID company_id = (Owner)p->Recv_uint8();
 

	
 
	/* Check if the company is valid */
 
	if (!IsValidCompanyID(company_id) && company_id != COMPANY_SPECTATOR) return;
 

	
 
	/* Check if we require a password for this company */
 
	if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
 
		/* we need a password from the client - should be in this packet */
 
		char password[NETWORK_PASSWORD_LENGTH];
 
		p->Recv_string(password, sizeof(password));
 

	
 
		/* Incorrect password sent, return! */
 
		if (strcmp(password, _network_company_states[company_id].password) != 0) {
 
			DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", cs->client_id, company_id + 1);
 
			return;
 
		}
 
	}
 

	
 
	/* if we get here we can move the client */
 
	NetworkServerDoMove(cs->client_id, company_id);
 
}
 

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

	
 
@@ -1240,6 +1303,10 @@ static NetworkServerPacket * const _netw
 
	RECEIVE_COMMAND(PACKET_CLIENT_RCON),
 
	NULL, /*PACKET_CLIENT_CHECK_NEWGRFS,*/
 
	RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED),
 
	NULL, /*PACKET_SERVER_MOVE,*/
 
	RECEIVE_COMMAND(PACKET_CLIENT_MOVE),
 
	NULL, /*PACKET_SERVER_COMPANY_UPDATE,*/
 
	NULL, /*PACKET_SERVER_CONFIG_UPDATE,*/
 
};
 

	
 
// If this fails, check the array above with network_data.h
 
@@ -1394,6 +1461,7 @@ static void NetworkAutoCleanCompanies()
 
				_network_company_states[c->index].password[0] = '\0';
 
				IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
 
				_network_company_states[c->index].months_empty = 0;
 
				NetworkServerUpdateCompanyPassworded(c->index, false);
 
			}
 
		} else {
 
			/* It is not empty, reset the date */
 
@@ -1635,6 +1703,63 @@ void NetworkServerShowStatusToConsole()
 
	}
 
}
 

	
 
/**
 
 * Send Config Update
 
 */
 
void NetworkServerSendConfigUpdate()
 
{
 
	NetworkClientSocket *cs;
 

	
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
 
		SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(cs);
 
	}
 
}
 

	
 
void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
 
{
 
	if (NetworkCompanyIsPassworded(company_id) == passworded) return;
 

	
 
	SB(_network_company_passworded, company_id, 1, !!passworded);
 

	
 
	NetworkClientSocket *cs;
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
 
		SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(cs);
 
	}
 
}
 

	
 
/**
 
 * Handle the tid-bits of moving a client from one company to another.
 
 * @param client_id id of the client we want to move.
 
 * @param company_id id of the company we want to move the client to.
 
 * @return void
 
 **/
 
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
 
{
 
	/* Only allow non-dedicated servers and normal clients to be moved */
 
	if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
 

	
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
 

	
 
	/* No need to waste network resources if the client is in the company already! */
 
	if (ci->client_playas == company_id) return;
 

	
 
	ci->client_playas = company_id;
 

	
 
	if (client_id == CLIENT_ID_SERVER) {
 
		SetLocalCompany(company_id);
 
	} else {
 
		SEND_COMMAND(PACKET_SERVER_MOVE)(NetworkFindClientStateFromClientID(client_id), client_id, company_id);
 
	}
 

	
 
	/* announce the client's move */
 
	NetworkUpdateClientInfo(client_id);
 

	
 
	NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
 
	NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
 

	
 
	CheckMinActiveClients();
 
}
 

	
 
void NetworkServerSendRcon(ClientID client_id, ConsoleColour colour_code, const char *string)
 
{
 
	SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromClientID(client_id), colour_code, string);
src/network/network_server.h
Show inline comments
 
@@ -13,6 +13,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN);
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientSocket *cs, uint16 color, const char *command);
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_MOVE)(NetworkClientSocket *cs, uint16 client_id, CompanyID company_id);
 

	
 
bool NetworkServer_ReadPackets(NetworkClientSocket *cs);
 
void NetworkServer_Tick(bool send_frame);
src/network/network_type.h
Show inline comments
 
@@ -80,6 +80,9 @@ enum NetworkAction {
 
	NETWORK_ACTION_CHAT_CLIENT,
 
	NETWORK_ACTION_GIVE_MONEY,
 
	NETWORK_ACTION_NAME_CHANGE,
 
	NETWORK_ACTION_COMPANY_SPECTATOR,
 
	NETWORK_ACTION_COMPANY_JOIN,
 
	NETWORK_ACTION_COMPANY_NEW,
 
};
 

	
 
/** Messages the server can give */
src/settings.cpp
Show inline comments
 
@@ -1180,6 +1180,13 @@ static int32 UpdateRconPassword(int32 p1
 
	return 0;
 
}
 

	
 
static int32 UpdateClientConfigValues(int32 p1)
 
{
 
	if (_network_server) NetworkServerSendConfigUpdate();
 

	
 
	return 0;
 
}
 

	
 
#endif /* ENABLE_NETWORK */
 

	
 

	
 
@@ -1549,9 +1556,9 @@ const SettingDesc _patch_settings[] = {
 
	 SDTC_BOOL(network.autoclean_companies,              S, NO, false,                        STR_NULL,                                       NULL),
 
	  SDTC_VAR(network.autoclean_unprotected, SLE_UINT8, S,D0|NO,  12,     0,         240, 0, STR_NULL,                                       NULL),
 
	  SDTC_VAR(network.autoclean_protected,   SLE_UINT8, S,D0|NO,  36,     0,         240, 0, STR_NULL,                                       NULL),
 
	  SDTC_VAR(network.max_companies,         SLE_UINT8, S, NO,     8,     1,MAX_COMPANIES,0, STR_NULL,                                       NULL),
 
	  SDTC_VAR(network.max_companies,         SLE_UINT8, S, NO,     8,     1,MAX_COMPANIES,0, STR_NULL,                                       UpdateClientConfigValues),
 
	  SDTC_VAR(network.max_clients,           SLE_UINT8, S, NO,    10,     2, MAX_CLIENTS, 0, STR_NULL,                                       NULL),
 
	  SDTC_VAR(network.max_spectators,        SLE_UINT8, S, NO,    10,     0, MAX_CLIENTS, 0, STR_NULL,                                       NULL),
 
	  SDTC_VAR(network.max_spectators,        SLE_UINT8, S, NO,    10,     0, MAX_CLIENTS, 0, STR_NULL,                                       UpdateClientConfigValues),
 
	  SDTC_VAR(network.restart_game_year,     SLE_INT32, S,D0|NO|NC,0, MIN_YEAR, MAX_YEAR, 1, STR_NULL,                                       NULL),
 
	  SDTC_VAR(network.min_active_clients,    SLE_UINT8, S, NO,     0,     0, MAX_CLIENTS, 0, STR_NULL,                                       UpdateMinActiveClients),
 
	SDTC_OMANY(network.server_lang,           SLE_UINT8, S, NO,     0,    35, "ANY|ENGLISH|GERMAN|FRENCH|BRAZILIAN|BULGARIAN|CHINESE|CZECH|DANISH|DUTCH|ESPERANTO|FINNISH|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|LITHUANIAN|NORWEGIAN|POLISH|PORTUGUESE|ROMANIAN|RUSSIAN|SLOVAK|SLOVENIAN|SPANISH|SWEDISH|TURKISH|UKRAINIAN|AFRIKAANS|CROATIAN|CATALAN|ESTONIAN|GALICIAN|GREEK|LATVIAN", STR_NULL, NULL),
src/toolbar_gui.cpp
Show inline comments
 
@@ -45,6 +45,7 @@
 

	
 
#include "network/network.h"
 
#include "network/network_gui.h"
 
#include "network/network_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 
@@ -199,6 +200,13 @@ static void PopupMainToolbMenu(Window *w
 
	SndPlayFx(SND_15_BEEP);
 
}
 

	
 
/** Enum for the Company Toolbar's network related buttons */
 
enum {
 
	CTMN_CLIENT_LIST = -1, ///< Show the client list
 
	CTMN_NEW_COMPANY = -2, ///< Create a new company
 
	CTMN_SPECTATE    = -3, ///< Become spectator
 
};
 

	
 
/**
 
 * Pop up a generic company list menu.
 
 */
 
@@ -206,17 +214,25 @@ static void PopupMainCompanyToolbMenu(Wi
 
{
 
	DropDownList *list = new DropDownList();
 

	
 
#ifdef ENABLE_NETWORK
 
	if (widget == TBN_COMPANIES && _networking) {
 
		/* Add the client list button for the companies menu */
 
		list->push_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST, -1, false));
 
		list->push_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST, CTMN_CLIENT_LIST, false));
 

	
 
		if (_local_company == COMPANY_SPECTATOR) {
 
			list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached()));
 
		} else {
 
			list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached()));
 
		}
 
	}
 
#endif /* ENABLE_NETWORK */
 

	
 
	for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
 
		if (!IsValidCompanyID(c)) continue;
 
		list->push_back(new DropDownListCompanyItem(c, false, HasBit(grey, c)));
 
	}
 

	
 
	ShowDropDownList(w, list, _local_company == COMPANY_SPECTATOR ? -1 : _local_company, widget, 240, true, true);
 
	ShowDropDownList(w, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : _local_company, widget, 240, true, true);
 
	SndPlayFx(SND_15_BEEP);
 
}
 

	
 
@@ -448,11 +464,33 @@ static void ToolbarCompaniesClick(Window
 

	
 
static void MenuClickCompany(int index)
 
{
 
	if (_networking && index == -1) {
 
		ShowClientList();
 
	} else {
 
		ShowCompany((CompanyID)index);
 
#ifdef ENABLE_NETWORK
 
	if (_networking) {
 
		switch (index) {
 
			case CTMN_CLIENT_LIST:
 
				ShowClientList();
 
				return;
 

	
 
			case CTMN_NEW_COMPANY:
 
				if (_network_server) {
 
					DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
 
				} else {
 
					NetworkSend_Command(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL);
 
				}
 
				return;
 

	
 
			case CTMN_SPECTATE:
 
				if (_network_server) {
 
					NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
 
					MarkWholeScreenDirty();
 
				} else {
 
					NetworkClientRequestMove(COMPANY_SPECTATOR);
 
				}
 
				return;
 
		}
 
	}
 
#endif /* ENABLE_NETWORK */
 
	ShowCompany((CompanyID)index);
 
}
 

	
 
/* --- Graphs button menu --- */
0 comments (0 inline, 0 general)