changeset 15860:bb167d01deb9 draft

(svn r20542) -Codechange: generalise the setting of "p2" to the ClientID.
author rubidium <rubidium@openttd.org>
date Wed, 18 Aug 2010 17:06:45 +0000
parents e4a43875449c
children 21b343faad7f
files src/command.cpp src/command_type.h src/company_cmd.cpp src/console_cmds.cpp src/network/network_server.cpp
diffstat 5 files changed, 36 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -14,6 +14,7 @@
 #include "landscape.h"
 #include "gui.h"
 #include "command_func.h"
+#include "network/network_type.h"
 #include "network/network.h"
 #include "genworld.h"
 #include "newgrf_storage.h"
@@ -283,7 +284,7 @@
 
 	DEF_CMD(CmdMoneyCheat,                           CMD_OFFLINE), // CMD_MONEY_CHEAT
 	DEF_CMD(CmdBuildCanal,                              CMD_AUTO), // CMD_BUILD_CANAL
-	DEF_CMD(CmdCompanyCtrl,                        CMD_SPECTATOR), // CMD_COMPANY_CTRL
+	DEF_CMD(CmdCompanyCtrl,        CMD_SPECTATOR | CMD_CLIENT_ID), // CMD_COMPANY_CTRL
 
 	DEF_CMD(CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO), // CMD_LEVEL_LAND; test run might clear tiles multiple times, in execution that only happens once
 
@@ -499,6 +500,10 @@
 	int x = TileX(tile) * TILE_SIZE;
 	int y = TileY(tile) * TILE_SIZE;
 
+#ifdef ENABLE_NETWORK
+	if (only_sending && GetCommandFlags(cmd) & CMD_CLIENT_ID) p2 = CLIENT_ID_SERVER;
+#endif
+
 	CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only);
 	if (res.Failed()) {
 		/* Only show the error when it's for us. */
@@ -568,6 +573,11 @@
 	/* Flags get send to the DoCommand */
 	DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags);
 
+#ifdef ENABLE_NETWORK
+	/* Make sure p2 is properly set to a ClientID. */
+	assert(!(cmd_flags & CMD_CLIENT_ID) || p2 != 0);
+#endif
+
 	/* Do not even think about executing out-of-bounds tile-commands */
 	if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (cmd_flags & CMD_ALL_TILES) == 0))) return_dcpi(CMD_ERROR, false);
 
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -332,6 +332,7 @@
 	CMD_ALL_TILES = 0x10, ///< allow this command also on MP_VOID tiles
 	CMD_NO_TEST   = 0x20, ///< the command's output may differ between test and execute due to town rating changes etc.
 	CMD_NO_WATER  = 0x40, ///< set the DC_NO_WATER flag on this command
+	CMD_CLIENT_ID = 0x80, ///< set p2 with the ClientID of the sending client.
 };
 
 /**
--- a/src/company_cmd.cpp
+++ b/src/company_cmd.cpp
@@ -572,7 +572,7 @@
 	if (n < (uint)_settings_game.difficulty.max_no_competitors) {
 		/* Send a command to all clients to start up a new AI.
 		 * Works fine for Multiplayer and Singleplayer */
-		DoCommandP(0, 1, INVALID_COMPANY, CMD_COMPANY_CTRL);
+		DoCommandP(0, 1 | INVALID_COMPANY << 16, 0, CMD_COMPANY_CTRL);
 	}
 }
 #endif /* ENABLE_AI */
@@ -745,46 +745,30 @@
  * @param tile unused
  * @param flags operation to perform
  * @param p1 various functionality
- * - p1 = 0 - create a new company, Which company (network) it will be is in p2
- * - p1 = 1 - create a new AI company
- * - p1 = 2 - delete a company. Company is identified by p2
- * @param p2 various functionality, dictated by p1
- * - p1 = 0 - ClientID of the newly created client
- * - p1 = 1 - CompanyID to start AI (INVALID_COMPANY for first available)
- * - p1 = 2 - CompanyID of the that is getting deleted
+ * - bits 0..15:
+ *        = 0 - create a new company
+ *        = 1 - create a new AI company
+ *        = 2 - delete a company
+ * - bits 16..24: CompanyID
+ * @param p2 ClientID
  * @param text unused
  * @return the cost of this operation or an error
- *
- * @todo In the case of p1=0, create new company, the clientID of the new client is in parameter
- * p2. This parameter is passed in at function DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
- * on the server itself. First of all this is unbelievably ugly; second of all, well,
- * it IS ugly! <b>Someone fix this up :)</b> So where to fix?@n
- * @arg - network_server.c:838 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)@n
- * @arg - network_client.c:536 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP) from where the map has been received
  */
 CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
 	InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0);
+	CompanyID company_id = (CompanyID)GB(p1, 16, 8);
+	ClientID client_id = (ClientID)p2;
 
-	switch (p1) {
+	switch (GB(p1, 0, 16)) {
 		case 0: { // Create a new company
 			/* This command is only executed in a multiplayer game */
 			if (!_networking) return CMD_ERROR;
 
 #ifdef ENABLE_NETWORK
-
-			/* Joining Client:
-			 * _local_company: COMPANY_SPECTATOR
-			 * cid = clientid
-			 *
-			 * Other client(s)/server:
-			 * _local_company: what they play as
-			 * cid = requested company/company of joining client */
-			ClientID cid = (ClientID)p2;
-
 			/* Has the network client a correct ClientIndex? */
 			if (!(flags & DC_EXEC)) return CommandCost();
-			NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(cid);
+			NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
 			if (ci == NULL) return CommandCost();
 
 			/* Delete multiplayer progress bar */
@@ -802,7 +786,7 @@
 			}
 
 			/* This is the client (or non-dedicated server) who wants a new company */
-			if (cid == _network_own_client_id) {
+			if (client_id == _network_own_client_id) {
 				assert(_local_company == COMPANY_SPECTATOR);
 				SetLocalCompany(c->index);
 				if (!StrEmpty(_settings_client.network.default_company_pass)) {
@@ -817,9 +801,6 @@
 			}
 
 			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) */
 				CompanyID old_playas = ci->client_playas;
 				ci->client_playas = c->index;
 				NetworkUpdateClientInfo(ci->client_id);
@@ -855,12 +836,12 @@
 		case 1: // Make a new AI company
 			if (!(flags & DC_EXEC)) return CommandCost();
 
-			if (p2 != INVALID_COMPANY && (p2 >= MAX_COMPANIES || Company::IsValidID(p2))) return CMD_ERROR;
-			DoStartupNewCompany(true, (CompanyID)p2);
+			if (company_id != INVALID_COMPANY && (company_id >= MAX_COMPANIES || Company::IsValidID(company_id))) return CMD_ERROR;
+			DoStartupNewCompany(true, company_id);
 			break;
 
 		case 2: { // Delete a company
-			Company *c = Company::GetIfValid(p2);
+			Company *c = Company::GetIfValid(company_id);
 			if (c == NULL) return CMD_ERROR;
 
 			if (!(flags & DC_EXEC)) return CommandCost();
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -761,7 +761,7 @@
 	}
 
 	/* It is safe to remove this company */
-	DoCommandP(0, 2, index, CMD_COMPANY_CTRL);
+	DoCommandP(0, 2 | index << 16, 0, CMD_COMPANY_CTRL);
 	IConsolePrint(CC_DEFAULT, "Company deleted.");
 
 	return true;
@@ -1067,7 +1067,7 @@
 	}
 
 	/* Start a new AI company */
-	DoCommandP(0, 1, INVALID_COMPANY, CMD_COMPANY_CTRL);
+	DoCommandP(0, 1 | INVALID_COMPANY << 16, 0, CMD_COMPANY_CTRL);
 
 	return true;
 }
@@ -1102,8 +1102,8 @@
 	}
 
 	/* First kill the company of the AI, then start a new one. This should start the current AI again */
-	DoCommandP(0, 2, company_id, CMD_COMPANY_CTRL);
-	DoCommandP(0, 1, company_id, CMD_COMPANY_CTRL);
+	DoCommandP(0, 2 | company_id << 16, 0, CMD_COMPANY_CTRL);
+	DoCommandP(0, 1 | company_id << 16, 0, CMD_COMPANY_CTRL);
 	IConsolePrint(CC_DEFAULT, "AI reloaded.");
 
 	return true;
@@ -1139,7 +1139,7 @@
 	}
 
 	/* Now kill the company of the AI. */
-	DoCommandP(0, 2, company_id, CMD_COMPANY_CTRL);
+	DoCommandP(0, 2 | company_id << 16, 0, CMD_COMPANY_CTRL);
 	IConsolePrint(CC_DEFAULT, "AI stopped, company deleted.");
 
 	return true;
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -933,12 +933,6 @@
 		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_COMPANY_MISMATCH);
 	}
 
-	/**
-	 * @todo CMD_COMPANY_CTRL with p1 = 0 announces a new company to the server. To give the
-	 * company the correct ID, the server injects p2 and executes the command. Any other p1
-	 * is prohibited. Pretty ugly and should be redone together with its function.
-	 * @see CmdCompanyCtrl()
-	 */
 	if (cp.cmd == CMD_COMPANY_CTRL) {
 		if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
 			return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
@@ -949,9 +943,9 @@
 			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
 			return NETWORK_RECV_STATUS_OKAY;
 		}
+	}
 
-		cp.p2 = cs->client_id;
-	}
+	if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = cs->client_id;
 
 	/* The frame can be executed in the same frame as the next frame-packet
 	 *  That frame just before that frame is saved in _frame_counter_max */
@@ -1505,7 +1499,7 @@
 			/* Is the company empty for autoclean_unprotected-months, and is there no protection? */
 			if (_settings_client.network.autoclean_unprotected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_unprotected && StrEmpty(_network_company_states[c->index].password)) {
 				/* Shut the company down */
-				DoCommandP(0, 2, c->index, CMD_COMPANY_CTRL);
+				DoCommandP(0, 2 | c->index << 16, 0, CMD_COMPANY_CTRL);
 				IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
 			}
 			/* Is the company empty for autoclean_protected-months, and there is a protection? */
@@ -1519,7 +1513,7 @@
 			/* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
 			if (_settings_client.network.autoclean_novehicles != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_novehicles && vehicles_in_company[c->index] == 0) {
 				/* Shut the company down */
-				DoCommandP(0, 2, c->index, CMD_COMPANY_CTRL);
+				DoCommandP(0, 2 | c->index << 16, 0, CMD_COMPANY_CTRL);
 				IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
 			}
 		} else {