changeset 5872:26a968ec2a2f draft

(svn r8461) -Feature: check for NewGRF compatability before actually downloading the map from a game server when connecting from the command prompt and internal console.
author rubidium <rubidium@openttd.org>
date Tue, 30 Jan 2007 17:22:56 +0000
parents bfbdc51e9d02
children 61739d3e3c92
files src/lang/english.txt src/network/core/core.h src/network/core/tcp.h src/network/network.cpp src/network/network_client.cpp src/network/network_data.h src/network/network_server.cpp
diffstat 7 files changed, 106 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1419,6 +1419,7 @@
 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
 STR_NETWORK_ERR_NOCONNECTION                                    :{WHITE} The server didn't answer the request
+STR_NETWORK_ERR_NEWGRF_MISMATCH                                 :{WHITE} Could not connect due to NewGRF mismatch
 STR_NETWORK_ERR_DESYNC                                          :{WHITE} Network-Game synchronisation failed
 STR_NETWORK_ERR_LOSTCONNECTION                                  :{WHITE} Network-Game connection lost
 STR_NETWORK_ERR_SAVEGAMEERROR                                   :{WHITE} Could not load savegame
@@ -1440,6 +1441,7 @@
 STR_NETWORK_ERR_CLIENT_SAVEGAME                                 :could not load map
 STR_NETWORK_ERR_CLIENT_CONNECTION_LOST                          :connection lost
 STR_NETWORK_ERR_CLIENT_PROTOCOL_ERROR                           :protocol error
+STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH                          :NewGRF mismatch
 STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED                           :not authorized
 STR_NETWORK_ERR_CLIENT_NOT_EXPECTED                             :received strange packet
 STR_NETWORK_ERR_CLIENT_WRONG_REVISION                           :wrong revision
--- a/src/network/core/core.h
+++ b/src/network/core/core.h
@@ -19,6 +19,7 @@
 typedef enum {
 	NETWORK_RECV_STATUS_OKAY,             ///< Everything is okay
 	NETWORK_RECV_STATUS_DESYNC,           ///< A desync did occur
+	NETWORK_RECV_STATUS_NEWGRF_MISMATCH,  ///< We did not have the required NewGRFs
 	NETWORK_RECV_STATUS_SAVEGAME,         ///< Something went wrong (down)loading the savegame
 	NETWORK_RECV_STATUS_CONN_LOST,        ///< The conection is 'just' lost
 	NETWORK_RECV_STATUS_MALFORMED_PACKET, ///< We apparently send a malformed packet
--- a/src/network/core/tcp.h
+++ b/src/network/core/tcp.h
@@ -52,6 +52,8 @@
 	PACKET_SERVER_NEWGAME,
 	PACKET_SERVER_RCON,
 	PACKET_CLIENT_RCON,
+	PACKET_SERVER_CHECK_NEWGRFS,
+	PACKET_CLIENT_NEWGRFS_CHECKED,
 	PACKET_END                   ///< Must ALWAYS be on the end of this list!! (period)
 };
 
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -250,9 +250,10 @@
 	}
 
 	switch (res) {
-		case NETWORK_RECV_STATUS_DESYNC:   errorno = NETWORK_ERROR_DESYNC; break;
-		case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
-		default:                           errorno = NETWORK_ERROR_GENERAL; break;
+		case NETWORK_RECV_STATUS_DESYNC:          errorno = NETWORK_ERROR_DESYNC; break;
+		case NETWORK_RECV_STATUS_SAVEGAME:        errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
+		case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
+		default:                                  errorno = NETWORK_ERROR_GENERAL; break;
 	}
 	// This means we fucked up and the server closed the connection
 	if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
@@ -282,6 +283,7 @@
 		STR_NETWORK_ERR_CLIENT_SAVEGAME,
 		STR_NETWORK_ERR_CLIENT_CONNECTION_LOST,
 		STR_NETWORK_ERR_CLIENT_PROTOCOL_ERROR,
+		STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH,
 		STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED,
 		STR_NETWORK_ERR_CLIENT_NOT_EXPECTED,
 		STR_NETWORK_ERR_CLIENT_WRONG_REVISION,
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -78,6 +78,18 @@
 	NetworkSend_Packet(p, MY_CLIENT);
 }
 
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
+{
+	//
+	// Packet: CLIENT_NEWGRFS_CHECKED
+	// Function: Tell the server that we have the required GRFs
+	// Data:
+	//
+
+	Packet *p = NetworkSend_Init(PACKET_CLIENT_NEWGRFS_CHECKED);
+	NetworkSend_Packet(p, MY_CLIENT);
+}
+
 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password)
 {
 	//
@@ -408,6 +420,37 @@
 	return NETWORK_RECV_STATUS_SERVER_ERROR;
 }
 
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)
+{
+	uint grf_count = NetworkRecv_uint8(MY_CLIENT, p);
+	NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY;
+
+	/* Check all GRFs */
+	for (; grf_count > 0; grf_count--) {
+		GRFConfig c;
+		MY_CLIENT->Recv_GRFIdentifier(p, &c);
+
+		/* Check whether we know this GRF */
+		const GRFConfig *f = FindGRFConfig(c.grfid, c.md5sum);
+		if (f == NULL) {
+			/* We do not know this GRF, bail out of initialization */
+			char buf[sizeof(c.md5sum) * 2 + 1];
+			md5sumToString(buf, lastof(buf), c.md5sum);
+			DEBUG(grf, 0, "NewGRF %08X not found; checksum %s", BSWAP32(c.grfid), buf);
+			ret = NETWORK_RECV_STATUS_NEWGRF_MISMATCH;
+		}
+	}
+
+	if (ret == NETWORK_RECV_STATUS_OKAY) {
+		/* Start receiving the map */
+		SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)();
+	} else {
+		/* NewGRF mismatch, bail out */
+		_switch_mode_errorstr = STR_NETWORK_ERR_NEWGRF_MISMATCH;
+	}
+	return ret;
+}
+
 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
 {
 	NetworkPasswordType type = (NetworkPasswordType)NetworkRecv_uint8(MY_CLIENT, p);
@@ -788,6 +831,8 @@
 	RECEIVE_COMMAND(PACKET_SERVER_NEWGAME),
 	RECEIVE_COMMAND(PACKET_SERVER_RCON),
 	NULL, /*PACKET_CLIENT_RCON,*/
+	RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS),
+	NULL, /*PACKET_CLIENT_NEWGRFS_CHECKED,*/
 };
 
 // If this fails, check the array above with network_data.h
--- a/src/network/network_data.h
+++ b/src/network/network_data.h
@@ -34,6 +34,7 @@
 	NETWORK_ERROR_SAVEGAME_FAILED,
 	NETWORK_ERROR_CONNECTION_LOST,
 	NETWORK_ERROR_ILLEGAL_PACKET,
+	NETWORK_ERROR_NEWGRF_MISMATCH,
 
 	// Signals from servers
 	NETWORK_ERROR_NOT_AUTHORIZED,
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -183,6 +183,32 @@
 	NetworkCloseClient(cs);
 }
 
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHECK_NEWGRFS)(NetworkTCPSocketHandler *cs)
+{
+	//
+	// Packet: PACKET_SERVER_CHECK_NEWGRFS
+	// Function: Sends info about the used GRFs to the client
+	// Data:
+	//      uint8:  Amount of GRFs
+	//    And then for each GRF:
+	//      uint32: GRF ID
+	// 16 * uint8:  MD5 checksum of the GRF
+	//
+
+	Packet *p = NetworkSend_Init(PACKET_SERVER_CHECK_NEWGRFS);
+	const GRFConfig *c;
+	uint grf_count = 0;
+
+	for (c = _grfconfig; c != NULL; c = c->next) grf_count++;
+
+	NetworkSend_uint8 (p, grf_count);
+	for (c = _grfconfig; c != NULL; c = c->next) {
+		cs->Send_GRFIdentifier(p, c);
+	}
+
+	NetworkSend_Packet(p, cs);
+}
+
 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkTCPSocketHandler *cs, NetworkPasswordType type)
 {
 	//
@@ -570,6 +596,22 @@
 	SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
 }
 
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
+{
+	NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
+
+	/* We now want a password from the client else we do not allow him in! */
+	if (_network_game_info.use_password) {
+		SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
+	} else {
+		if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
+			SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
+		} else {
+			SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
+		}
+	}
+}
+
 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
 {
 	char name[NETWORK_CLIENT_NAME_LENGTH];
@@ -636,20 +678,14 @@
 	ci->client_playas = playas;
 	ci->client_lang = client_lang;
 
-	// We now want a password from the client
-	//  else we do not allow him in!
-	if (_network_game_info.use_password) {
-		SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
-	} else {
-		if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
-			SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
-		} else {
-			SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
-		}
-	}
-
 	/* Make sure companies to which people try to join are not autocleaned */
 	if (IsValidPlayer(playas)) _network_player_info[playas].months_empty = 0;
+
+	if (_grfconfig == NULL) {
+		RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(cs, NULL);
+	} else {
+		SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs);
+	}
 }
 
 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
@@ -1184,6 +1220,8 @@
 	NULL, /*PACKET_SERVER_NEWGAME,*/
 	NULL, /*PACKET_SERVER_RCON,*/
 	RECEIVE_COMMAND(PACKET_CLIENT_RCON),
+	NULL, /*PACKET_CLIENT_CHECK_NEWGRFS,*/
+	RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED),
 };
 
 // If this fails, check the array above with network_data.h