summaryrefslogtreecommitdiff
path: root/src/network/network_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/network_server.cpp')
-rw-r--r--src/network/network_server.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp
index d291bb92a..647358ecf 100644
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -586,6 +586,32 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientSocket *cs, uint1
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_MAP_OK)
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_COMMAND)
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_SET_PASSWORD)
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_RCON)
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 _network_server_packet[] = {
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);