Merge branch 'master' into jgrpp-beta
# Conflicts: # src/network/core/game_info.h # src/network/core/udp.cpp # src/network/core/udp.h # src/network/network.cpp # src/network/network_client.cpp # src/network/network_client.h # src/network/network_internal.h # src/network/network_udp.cpp
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include "engine_func.h"
|
||||
#include "landscape.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "network/core/game_info.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_func.h"
|
||||
#include "network/network_base.h"
|
||||
|
@@ -4,7 +4,8 @@ add_files(
|
||||
config.h
|
||||
core.cpp
|
||||
core.h
|
||||
game.h
|
||||
game_info.cpp
|
||||
game_info.h
|
||||
host.cpp
|
||||
host.h
|
||||
os_abstraction.h
|
||||
|
@@ -65,31 +65,3 @@ const char *NetworkGetErrorString(int error)
|
||||
return buffer;
|
||||
}
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/**
|
||||
* Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
|
||||
* @param p the packet to write the data to
|
||||
* @param grf the GRFIdentifier to serialize
|
||||
*/
|
||||
void NetworkSocketHandler::SendGRFIdentifier(Packet *p, const GRFIdentifier *grf)
|
||||
{
|
||||
uint j;
|
||||
p->Send_uint32(grf->grfid);
|
||||
for (j = 0; j < sizeof(grf->md5sum); j++) {
|
||||
p->Send_uint8 (grf->md5sum[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
|
||||
* @param p the packet to read the data from
|
||||
* @param grf the GRFIdentifier to deserialize
|
||||
*/
|
||||
void NetworkSocketHandler::ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf)
|
||||
{
|
||||
uint j;
|
||||
grf->grfid = p->Recv_uint32();
|
||||
for (j = 0; j < sizeof(grf->md5sum); j++) {
|
||||
grf->md5sum[j] = p->Recv_uint8();
|
||||
}
|
||||
}
|
||||
|
@@ -71,8 +71,6 @@ public:
|
||||
*/
|
||||
void Reopen() { this->has_quit = false; }
|
||||
|
||||
void SendGRFIdentifier(Packet *p, const GRFIdentifier *grf);
|
||||
void ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf);
|
||||
void SendCompanyInformation(Packet *p, const struct Company *c, const struct NetworkCompanyStats *stats, uint max_len = NETWORK_COMPANY_NAME_LENGTH);
|
||||
};
|
||||
|
||||
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file game.h Information about a game that is sent between a
|
||||
* game server, game client and masterserver.
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_CORE_GAME_H
|
||||
#define NETWORK_CORE_GAME_H
|
||||
|
||||
#include "config.h"
|
||||
#include "../../newgrf_config.h"
|
||||
#include "../../date_type.h"
|
||||
|
||||
/**
|
||||
* The game information that is not generated on-the-fly and has to
|
||||
* be sent to the clients.
|
||||
*/
|
||||
struct NetworkServerGameInfo {
|
||||
byte clients_on; ///< Current count of clients on server
|
||||
};
|
||||
|
||||
/**
|
||||
* The game information that is sent from the server to the clients.
|
||||
*/
|
||||
struct NetworkGameInfo : NetworkServerGameInfo {
|
||||
GRFConfig *grfconfig; ///< List of NewGRF files used
|
||||
Date start_date; ///< When the game started
|
||||
Date game_date; ///< Current date
|
||||
uint32 map_width; ///< Map width
|
||||
uint32 map_height; ///< Map height
|
||||
char server_name[NETWORK_NAME_LENGTH]; ///< Server name
|
||||
char hostname[NETWORK_HOSTNAME_LENGTH]; ///< Hostname of the server (if any)
|
||||
char short_server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0) (truncated)
|
||||
char server_revision[NETWORK_LONG_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0)
|
||||
bool dedicated; ///< Is this a dedicated server?
|
||||
bool version_compatible; ///< Can we connect to this server or not? (based on server_revision)
|
||||
bool compatible; ///< Can we connect to this server or not? (based on server_revision _and_ grf_match
|
||||
bool use_password; ///< Is this server passworded?
|
||||
byte game_info_version; ///< Version of the game info
|
||||
byte clients_max; ///< Max clients allowed on server
|
||||
byte companies_on; ///< How many started companies do we have
|
||||
byte companies_max; ///< Max companies allowed on server
|
||||
byte spectators_on; ///< How many spectators do we have?
|
||||
byte spectators_max; ///< Max spectators allowed on server
|
||||
byte map_set; ///< Graphical set
|
||||
};
|
||||
|
||||
#endif /* NETWORK_CORE_GAME_H */
|
457
src/network/core/game_info.cpp
Normal file
457
src/network/core/game_info.cpp
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file game_info.cpp Functions to convert NetworkGameInfo to Packet and back.
|
||||
*/
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "game_info.h"
|
||||
#include "../../core/bitmath_func.hpp"
|
||||
#include "../../company_base.h"
|
||||
#include "../../date_func.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../map_func.h"
|
||||
#include "../../settings_type.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../rev.h"
|
||||
#include "../network_func.h"
|
||||
#include "../network.h"
|
||||
#include "packet.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
extern const uint8 _out_of_band_grf_md5[16];
|
||||
|
||||
/**
|
||||
* How many hex digits of the git hash to include in network revision string.
|
||||
* Determined as 10 hex digits + 2 characters for -g/-u/-m prefix.
|
||||
*/
|
||||
static const uint GITHASH_SUFFIX_LEN = 12;
|
||||
|
||||
NetworkServerGameInfo _network_game_info; ///< Information about our game.
|
||||
|
||||
/**
|
||||
* Get the network version string used by this build.
|
||||
* The returned string is guaranteed to be at most NETWORK_REVISON_LENGTH bytes.
|
||||
*/
|
||||
const char *GetNetworkRevisionString()
|
||||
{
|
||||
/* This will be allocated on heap and never free'd, but only once so not a "real" leak. */
|
||||
static char *network_revision = nullptr;
|
||||
|
||||
if (!network_revision) {
|
||||
/* Start by taking a chance on the full revision string. */
|
||||
network_revision = stredup(_openttd_revision);
|
||||
/* Ensure it's not longer than the packet buffer length. */
|
||||
if (strlen(network_revision) >= NETWORK_REVISION_LENGTH) network_revision[NETWORK_REVISION_LENGTH - 1] = '\0';
|
||||
|
||||
/* Tag names are not mangled further. */
|
||||
if (_openttd_revision_tagged) {
|
||||
DEBUG(net, 1, "Network revision name is '%s'", network_revision);
|
||||
return network_revision;
|
||||
}
|
||||
|
||||
/* Prepare a prefix of the git hash.
|
||||
* Size is length + 1 for terminator, +2 for -g prefix. */
|
||||
assert(_openttd_revision_modified < 3);
|
||||
char githash_suffix[GITHASH_SUFFIX_LEN + 1] = "-";
|
||||
githash_suffix[1] = "gum"[_openttd_revision_modified];
|
||||
for (uint i = 2; i < GITHASH_SUFFIX_LEN; i++) {
|
||||
githash_suffix[i] = _openttd_revision_hash[i-2];
|
||||
}
|
||||
|
||||
/* Where did the hash start in the original string?
|
||||
* Overwrite from that position, unless that would go past end of packet buffer length. */
|
||||
ptrdiff_t hashofs = strrchr(_openttd_revision, '-') - _openttd_revision;
|
||||
if (hashofs + strlen(githash_suffix) + 1 > NETWORK_REVISION_LENGTH) hashofs = strlen(network_revision) - strlen(githash_suffix);
|
||||
/* Replace the git hash in revision string. */
|
||||
strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH);
|
||||
assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than
|
||||
DEBUG(net, 1, "Network revision name is '%s'", network_revision);
|
||||
}
|
||||
|
||||
return network_revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the git hash from the revision string.
|
||||
* @param revstr The revision string (formatted as DATE-BRANCH-GITHASH).
|
||||
* @return The git has part of the revision.
|
||||
*/
|
||||
static const char *ExtractNetworkRevisionHash(const char *revstr)
|
||||
{
|
||||
return strrchr(revstr, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given version string is compatible with our version.
|
||||
* First tries to match the full string, if that fails, attempts to compare just git hashes.
|
||||
* @param other the version string to compare to
|
||||
*/
|
||||
bool IsNetworkCompatibleVersion(const char *other, bool extended)
|
||||
{
|
||||
if (strncmp(GetNetworkRevisionString(), other, (extended ? NETWORK_LONG_REVISION_LENGTH : NETWORK_REVISION_LENGTH) - 1) == 0) return true;
|
||||
|
||||
/* If this version is tagged, then the revision string must be a complete match,
|
||||
* since there is no git hash suffix in it.
|
||||
* This is needed to avoid situations like "1.9.0-beta1" comparing equal to "2.0.0-beta1". */
|
||||
if (_openttd_revision_tagged) return false;
|
||||
|
||||
const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString());
|
||||
const char *hash2 = ExtractNetworkRevisionHash(other);
|
||||
return hash1 != nullptr && hash2 != nullptr && strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an game entry is compatible with our client.
|
||||
*/
|
||||
void CheckGameCompatibility(NetworkGameInfo &ngi)
|
||||
{
|
||||
/* Check if we are allowed on this server based on the revision-check. */
|
||||
ngi.version_compatible = IsNetworkCompatibleVersion(ngi.server_revision);
|
||||
ngi.compatible = ngi.version_compatible;
|
||||
|
||||
/* Check if we have all the GRFs on the client-system too. */
|
||||
for (const GRFConfig *c = ngi.grfconfig; c != nullptr; c = c->next) {
|
||||
if (c->status == GCS_NOT_FOUND) ngi.compatible = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill a NetworkGameInfo structure with the latest information of the server.
|
||||
* @param ngi the NetworkGameInfo struct to fill with data.
|
||||
*/
|
||||
void FillNetworkGameInfo(NetworkGameInfo &ngi)
|
||||
{
|
||||
/* Update some game_info */
|
||||
ngi.clients_on = _network_game_info.clients_on;
|
||||
ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
|
||||
|
||||
ngi.use_password = !StrEmpty(_settings_client.network.server_password);
|
||||
ngi.clients_max = _settings_client.network.max_clients;
|
||||
ngi.companies_on = (byte)Company::GetNumItems();
|
||||
ngi.companies_max = _settings_client.network.max_companies;
|
||||
ngi.spectators_on = NetworkSpectatorCount();
|
||||
ngi.spectators_max = _settings_client.network.max_spectators;
|
||||
ngi.game_date = _date;
|
||||
ngi.map_width = MapSizeX();
|
||||
ngi.map_height = MapSizeY();
|
||||
ngi.map_set = _settings_game.game_creation.landscape;
|
||||
ngi.dedicated = _network_dedicated;
|
||||
ngi.grfconfig = _grfconfig;
|
||||
|
||||
strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name));
|
||||
strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision));
|
||||
strecpy(ngi.short_server_revision, _openttd_revision, lastof(ngi.short_server_revision));
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that is called for every GRFConfig that is read when receiving
|
||||
* a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
|
||||
* function must set all appropriate fields. This GRF is later appended to
|
||||
* the grfconfig list of the NetworkGameInfo.
|
||||
* @param config the GRF to handle.
|
||||
*/
|
||||
static void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
|
||||
{
|
||||
/* Find the matching GRF file */
|
||||
const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum);
|
||||
if (f == nullptr) {
|
||||
/* Don't know the GRF, so mark game incompatible and the (possibly)
|
||||
* already resolved name for this GRF (another server has sent the
|
||||
* name of the GRF already */
|
||||
config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true);
|
||||
config->status = GCS_NOT_FOUND;
|
||||
} else {
|
||||
config->filename = f->filename;
|
||||
config->name = f->name;
|
||||
config->info = f->info;
|
||||
config->url = f->url;
|
||||
}
|
||||
SetBit(config->flags, GCF_COPY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the NetworkGameInfo struct to the packet.
|
||||
* @param p the packet to write the data to.
|
||||
* @param info the NetworkGameInfo struct to serialize from.
|
||||
*/
|
||||
void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
|
||||
{
|
||||
p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
|
||||
|
||||
/*
|
||||
* Please observe the order.
|
||||
* The parts must be read in the same order as they are sent!
|
||||
*/
|
||||
|
||||
/* Update the documentation in game_info.h on changes
|
||||
* to the NetworkGameInfo wire-protocol! */
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 4 */
|
||||
{
|
||||
/* Only send the GRF Identification (GRF_ID and MD5 checksum) of
|
||||
* the GRFs that are needed, i.e. the ones that the server has
|
||||
* selected in the NewGRF GUI and not the ones that are used due
|
||||
* to the fact that they are in [newgrf-static] in openttd.cfg */
|
||||
const GRFConfig *c;
|
||||
uint count = 0;
|
||||
|
||||
/* Count number of GRFs to send information about */
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) count++;
|
||||
}
|
||||
p->Send_uint8(std::min<uint>(count, NETWORK_MAX_GRF_COUNT)); // Send number of GRFs
|
||||
|
||||
/* Send actual GRF Identifications */
|
||||
uint index = 0;
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) {
|
||||
if (index == NETWORK_MAX_GRF_COUNT - 1 && count > NETWORK_MAX_GRF_COUNT) {
|
||||
/* Send fake GRF ID */
|
||||
|
||||
p->Send_uint32(0x56D2B000);
|
||||
p->Send_binary((const char*) _out_of_band_grf_md5, 16);
|
||||
} else if (index >= NETWORK_MAX_GRF_COUNT) {
|
||||
break;
|
||||
} else {
|
||||
SerializeGRFIdentifier(p, &c->ident);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 3 */
|
||||
p->Send_uint32(info->game_date);
|
||||
p->Send_uint32(info->start_date);
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 2 */
|
||||
p->Send_uint8 (info->companies_max);
|
||||
p->Send_uint8 (info->companies_on);
|
||||
p->Send_uint8 (info->spectators_max);
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 1 */
|
||||
p->Send_string(info->server_name);
|
||||
p->Send_string(info->server_revision);
|
||||
p->Send_uint8 (0); // Used to be server-lang.
|
||||
p->Send_bool (info->use_password);
|
||||
p->Send_uint8 (info->clients_max);
|
||||
p->Send_uint8 (info->clients_on);
|
||||
p->Send_uint8 (info->spectators_on);
|
||||
p->Send_string(""); // Used to be map-name.
|
||||
p->Send_uint16(info->map_width);
|
||||
p->Send_uint16(info->map_height);
|
||||
p->Send_uint8 (info->map_set);
|
||||
p->Send_bool (info->dedicated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the NetworkGameInfo struct to the packet
|
||||
* @param p the packet to write the data to
|
||||
* @param info the NetworkGameInfo struct to serialize
|
||||
*/
|
||||
void SerializeNetworkGameInfoExtended(Packet *p, const NetworkGameInfo *info, uint16 flags, uint16 version)
|
||||
{
|
||||
p->Send_uint8(0); // version num
|
||||
|
||||
p->Send_uint32(info->game_date);
|
||||
p->Send_uint32(info->start_date);
|
||||
p->Send_uint8 (info->companies_max);
|
||||
p->Send_uint8 (info->companies_on);
|
||||
p->Send_uint8 (info->spectators_max);
|
||||
p->Send_string(info->server_name);
|
||||
p->Send_string(info->server_revision);
|
||||
p->Send_uint8 (0); // Used to be server-lang.
|
||||
p->Send_bool (info->use_password);
|
||||
p->Send_uint8 (info->clients_max);
|
||||
p->Send_uint8 (info->clients_on);
|
||||
p->Send_uint8 (info->spectators_on);
|
||||
p->Send_string(""); // Used to be map-name.
|
||||
p->Send_uint32(info->map_width);
|
||||
p->Send_uint32(info->map_height);
|
||||
p->Send_uint8 (info->map_set);
|
||||
p->Send_bool (info->dedicated);
|
||||
|
||||
{
|
||||
/* Only send the GRF Identification (GRF_ID and MD5 checksum) of
|
||||
* the GRFs that are needed, i.e. the ones that the server has
|
||||
* selected in the NewGRF GUI and not the ones that are used due
|
||||
* to the fact that they are in [newgrf-static] in openttd.cfg */
|
||||
const GRFConfig *c;
|
||||
uint count = 0;
|
||||
|
||||
/* Count number of GRFs to send information about */
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) count++;
|
||||
}
|
||||
p->Send_uint32(count); // Send number of GRFs
|
||||
|
||||
/* Send actual GRF Identifications */
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) {
|
||||
SerializeGRFIdentifier(p, &c->ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the NetworkGameInfo struct from the packet.
|
||||
* @param p the packet to read the data from.
|
||||
* @param info the NetworkGameInfo to deserialize into.
|
||||
*/
|
||||
void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info)
|
||||
{
|
||||
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
|
||||
|
||||
info->game_info_version = p->Recv_uint8();
|
||||
|
||||
/*
|
||||
* Please observe the order.
|
||||
* The parts must be read in the same order as they are sent!
|
||||
*/
|
||||
|
||||
/* Update the documentation in game_info.h on changes
|
||||
* to the NetworkGameInfo wire-protocol! */
|
||||
|
||||
switch (info->game_info_version) {
|
||||
case 4: {
|
||||
GRFConfig **dst = &info->grfconfig;
|
||||
uint i;
|
||||
uint num_grfs = p->Recv_uint8();
|
||||
|
||||
/* Broken/bad data. It cannot have that many NewGRFs. */
|
||||
if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
|
||||
|
||||
for (i = 0; i < num_grfs; i++) {
|
||||
GRFConfig *c = new GRFConfig();
|
||||
DeserializeGRFIdentifier(p, &c->ident);
|
||||
HandleIncomingNetworkGameInfoGRFConfig(c);
|
||||
|
||||
/* Append GRFConfig to the list */
|
||||
*dst = c;
|
||||
dst = &c->next;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
}
|
||||
|
||||
case 3:
|
||||
info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
FALLTHROUGH;
|
||||
|
||||
case 2:
|
||||
info->companies_max = p->Recv_uint8 ();
|
||||
info->companies_on = p->Recv_uint8 ();
|
||||
info->spectators_max = p->Recv_uint8 ();
|
||||
FALLTHROUGH;
|
||||
|
||||
case 1:
|
||||
p->Recv_string(info->server_name, sizeof(info->server_name));
|
||||
p->Recv_string(info->server_revision, sizeof(info->server_revision));
|
||||
p->Recv_uint8 (); // Used to contain server-lang.
|
||||
info->use_password = p->Recv_bool ();
|
||||
info->clients_max = p->Recv_uint8 ();
|
||||
info->clients_on = p->Recv_uint8 ();
|
||||
info->spectators_on = p->Recv_uint8 ();
|
||||
if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
|
||||
info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
|
||||
info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
|
||||
}
|
||||
while (p->Recv_uint8() != 0) {} // Used to contain the map-name.
|
||||
info->map_width = p->Recv_uint16();
|
||||
info->map_height = p->Recv_uint16();
|
||||
info->map_set = p->Recv_uint8 ();
|
||||
info->dedicated = p->Recv_bool ();
|
||||
|
||||
if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the NetworkGameInfo struct from the packet
|
||||
* @param p the packet to read the data from
|
||||
* @param info the NetworkGameInfo to deserialize into
|
||||
*/
|
||||
void DeserializeNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info)
|
||||
{
|
||||
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
|
||||
|
||||
const uint8 version = p->Recv_uint8();
|
||||
if (version > 0) return; // Unknown version
|
||||
|
||||
info->game_info_version = 255;
|
||||
|
||||
info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
info->companies_max = p->Recv_uint8 ();
|
||||
info->companies_on = p->Recv_uint8 ();
|
||||
info->spectators_max = p->Recv_uint8 ();
|
||||
p->Recv_string(info->server_name, sizeof(info->server_name));
|
||||
p->Recv_string(info->server_revision, sizeof(info->server_revision));
|
||||
p->Recv_uint8 (); // Used to contain server-lang.
|
||||
info->use_password = p->Recv_bool ();
|
||||
info->clients_max = p->Recv_uint8 ();
|
||||
info->clients_on = p->Recv_uint8 ();
|
||||
info->spectators_on = p->Recv_uint8 ();
|
||||
while (p->Recv_uint8() != 0) {} // Used to contain the map-name.
|
||||
info->map_width = p->Recv_uint32();
|
||||
info->map_height = p->Recv_uint32();
|
||||
info->map_set = p->Recv_uint8 ();
|
||||
info->dedicated = p->Recv_bool ();
|
||||
|
||||
{
|
||||
GRFConfig **dst = &info->grfconfig;
|
||||
uint i;
|
||||
uint num_grfs = p->Recv_uint32();
|
||||
|
||||
/* Broken/bad data. It cannot have that many NewGRFs. */
|
||||
if (num_grfs > MAX_NON_STATIC_GRF_COUNT) return;
|
||||
|
||||
for (i = 0; i < num_grfs; i++) {
|
||||
GRFConfig *c = new GRFConfig();
|
||||
DeserializeGRFIdentifier(p, &c->ident);
|
||||
HandleIncomingNetworkGameInfoGRFConfig(c);
|
||||
|
||||
/* Append GRFConfig to the list */
|
||||
*dst = c;
|
||||
dst = &c->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
|
||||
* @param p the packet to write the data to.
|
||||
* @param grf the GRFIdentifier to serialize.
|
||||
*/
|
||||
void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf)
|
||||
{
|
||||
uint j;
|
||||
p->Send_uint32(grf->grfid);
|
||||
for (j = 0; j < sizeof(grf->md5sum); j++) {
|
||||
p->Send_uint8(grf->md5sum[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
|
||||
* @param p the packet to read the data from.
|
||||
* @param grf the GRFIdentifier to deserialize.
|
||||
*/
|
||||
void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf)
|
||||
{
|
||||
uint j;
|
||||
grf->grfid = p->Recv_uint32();
|
||||
for (j = 0; j < sizeof(grf->md5sum); j++) {
|
||||
grf->md5sum[j] = p->Recv_uint8();
|
||||
}
|
||||
}
|
109
src/network/core/game_info.h
Normal file
109
src/network/core/game_info.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file game_info.h Convert NetworkGameInfo to Packet and back.
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_CORE_GAME_INFO_H
|
||||
#define NETWORK_CORE_GAME_INFO_H
|
||||
|
||||
#include "config.h"
|
||||
#include "core.h"
|
||||
#include "../../newgrf_config.h"
|
||||
#include "../../date_type.h"
|
||||
|
||||
/*
|
||||
* NetworkGameInfo has several revisions which we still need to support on the
|
||||
* wire. The table below shows the version and size for each field of the
|
||||
* serialized NetworkGameInfo.
|
||||
*
|
||||
* Version: Bytes: Description:
|
||||
* all 1 the version of this packet's structure
|
||||
*
|
||||
* 4+ 1 number of GRFs attached (n)
|
||||
* 4+ n * 20 unique identifier for GRF files. Consists of:
|
||||
* - one 4 byte variable with the GRF ID
|
||||
* - 16 bytes (sent sequentially) for the MD5 checksum
|
||||
* of the GRF
|
||||
*
|
||||
* 3+ 4 current game date in days since 1-1-0 (DMY)
|
||||
* 3+ 4 game introduction date in days since 1-1-0 (DMY)
|
||||
*
|
||||
* 2+ 1 maximum number of companies allowed on the server
|
||||
* 2+ 1 number of companies on the server
|
||||
* 2+ 1 maximum number of spectators allowed on the server
|
||||
*
|
||||
* 1+ var string with the name of the server
|
||||
* 1+ var string with the revision of the server
|
||||
* 1+ 1 the language run on the server
|
||||
* (0 = any, 1 = English, 2 = German, 3 = French)
|
||||
* 1+ 1 whether the server uses a password (0 = no, 1 = yes)
|
||||
* 1+ 1 maximum number of clients allowed on the server
|
||||
* 1+ 1 number of clients on the server
|
||||
* 1+ 1 number of spectators on the server
|
||||
* 1 & 2 2 current game date in days since 1-1-1920 (DMY)
|
||||
* 1 & 2 2 game introduction date in days since 1-1-1920 (DMY)
|
||||
* 1+ var string with the name of the map
|
||||
* 1+ 2 width of the map in tiles
|
||||
* 1+ 2 height of the map in tiles
|
||||
* 1+ 1 type of map:
|
||||
* (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland)
|
||||
* 1+ 1 whether the server is dedicated (0 = no, 1 = yes)
|
||||
*/
|
||||
|
||||
/**
|
||||
* The game information that is not generated on-the-fly and has to
|
||||
* be sent to the clients.
|
||||
*/
|
||||
struct NetworkServerGameInfo {
|
||||
byte clients_on; ///< Current count of clients on server
|
||||
};
|
||||
|
||||
/**
|
||||
* The game information that is sent from the server to the clients.
|
||||
*/
|
||||
struct NetworkGameInfo : NetworkServerGameInfo {
|
||||
GRFConfig *grfconfig; ///< List of NewGRF files used
|
||||
Date start_date; ///< When the game started
|
||||
Date game_date; ///< Current date
|
||||
uint32 map_width; ///< Map width
|
||||
uint32 map_height; ///< Map height
|
||||
char server_name[NETWORK_NAME_LENGTH]; ///< Server name
|
||||
char hostname[NETWORK_HOSTNAME_LENGTH]; ///< Hostname of the server (if any)
|
||||
char short_server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0) (truncated)
|
||||
char server_revision[NETWORK_LONG_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0)
|
||||
bool dedicated; ///< Is this a dedicated server?
|
||||
bool version_compatible; ///< Can we connect to this server or not? (based on server_revision)
|
||||
bool compatible; ///< Can we connect to this server or not? (based on server_revision _and_ grf_match
|
||||
bool use_password; ///< Is this server passworded?
|
||||
byte game_info_version; ///< Version of the game info
|
||||
byte clients_max; ///< Max clients allowed on server
|
||||
byte companies_on; ///< How many started companies do we have
|
||||
byte companies_max; ///< Max companies allowed on server
|
||||
byte spectators_on; ///< How many spectators do we have?
|
||||
byte spectators_max; ///< Max spectators allowed on server
|
||||
byte map_set; ///< Graphical set
|
||||
};
|
||||
|
||||
extern NetworkServerGameInfo _network_game_info;
|
||||
|
||||
const char *GetNetworkRevisionString();
|
||||
bool IsNetworkCompatibleVersion(const char *other, bool extended = false);
|
||||
void CheckGameCompatibility(NetworkGameInfo &ngi);
|
||||
|
||||
void FillNetworkGameInfo(NetworkGameInfo &ngi);
|
||||
|
||||
void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf);
|
||||
void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf);
|
||||
|
||||
void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info);
|
||||
void DeserializeNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info);
|
||||
void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info);
|
||||
void SerializeNetworkGameInfoExtended(Packet *p, const NetworkGameInfo *info, uint16 flags, uint16 version);
|
||||
|
||||
#endif /* NETWORK_CORE_GAME_INFO_H */
|
@@ -27,6 +27,8 @@ static const char* _packet_game_type_names[] {
|
||||
"SERVER_ERROR",
|
||||
"CLIENT_COMPANY_INFO",
|
||||
"SERVER_COMPANY_INFO",
|
||||
"CLIENT_GAME_INFO",
|
||||
"SERVER_GAME_INFO",
|
||||
"SERVER_CHECK_NEWGRFS",
|
||||
"CLIENT_NEWGRFS_CHECKED",
|
||||
"SERVER_NEED_GAME_PASSWORD",
|
||||
@@ -135,6 +137,8 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet *p)
|
||||
case PACKET_SERVER_BANNED: return this->Receive_SERVER_BANNED(p);
|
||||
case PACKET_CLIENT_JOIN: return this->Receive_CLIENT_JOIN(p);
|
||||
case PACKET_SERVER_ERROR: return this->Receive_SERVER_ERROR(p);
|
||||
case PACKET_CLIENT_GAME_INFO: return this->Receive_CLIENT_GAME_INFO(p);
|
||||
case PACKET_SERVER_GAME_INFO: return this->Receive_SERVER_GAME_INFO(p);
|
||||
case PACKET_CLIENT_COMPANY_INFO: return this->Receive_CLIENT_COMPANY_INFO(p);
|
||||
case PACKET_SERVER_COMPANY_INFO: return this->Receive_SERVER_COMPANY_INFO(p);
|
||||
case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(p);
|
||||
@@ -225,6 +229,8 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p) { ret
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_BANNED); }
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_JOIN); }
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_ERROR); }
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_INFO); }
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO); }
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_INFO); }
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_INFO); }
|
||||
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); }
|
||||
|
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
enum PacketGameType {
|
||||
/*
|
||||
* These first three pair of packets (thus six in
|
||||
* These first four pair of packets (thus eight in
|
||||
* total) must remain in this order for backward
|
||||
* and forward compatibility between clients that
|
||||
* are trying to join directly.
|
||||
@@ -43,6 +43,10 @@ enum PacketGameType {
|
||||
PACKET_CLIENT_COMPANY_INFO, ///< Request information about all companies.
|
||||
PACKET_SERVER_COMPANY_INFO, ///< Information about a single company.
|
||||
|
||||
/* Packets used to get the game info. */
|
||||
PACKET_CLIENT_GAME_INFO, ///< Request information about the server.
|
||||
PACKET_SERVER_GAME_INFO, ///< Information about the server.
|
||||
|
||||
/*
|
||||
* Packets after here assume that the client
|
||||
* and server are running the same version. As
|
||||
@@ -195,6 +199,19 @@ protected:
|
||||
*/
|
||||
virtual NetworkRecvStatus Receive_SERVER_ERROR(Packet *p);
|
||||
|
||||
/**
|
||||
* Request game information.
|
||||
* @param p The packet that was just received.
|
||||
*/
|
||||
virtual NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet *p);
|
||||
|
||||
/**
|
||||
* Sends information about the game.
|
||||
* Serialized NetworkGameInfo. See game_info.h for details.
|
||||
* @param p The packet that was just received.
|
||||
*/
|
||||
virtual NetworkRecvStatus Receive_SERVER_GAME_INFO(Packet *p);
|
||||
|
||||
/**
|
||||
* Request company information (in detail).
|
||||
* @param p The packet that was just received.
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "../../debug.h"
|
||||
#include "../../rev.h"
|
||||
#include "../network_func.h"
|
||||
#include "game_info.h"
|
||||
|
||||
#include "tcp_http.h"
|
||||
|
||||
|
@@ -13,13 +13,10 @@
|
||||
#include "../../date_func.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../core/random_func.hpp"
|
||||
#include "../../fios.h"
|
||||
#include "udp.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
extern const uint8 _out_of_band_grf_md5[16];
|
||||
|
||||
/**
|
||||
* Create an UDP socket but don't listen yet.
|
||||
* @param bind the addresses to bind to.
|
||||
@@ -186,258 +183,6 @@ void NetworkUDPSocketHandler::ReceivePackets()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the NetworkGameInfo struct to the packet
|
||||
* @param p the packet to write the data to
|
||||
* @param info the NetworkGameInfo struct to serialize
|
||||
*/
|
||||
void NetworkUDPSocketHandler::SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
|
||||
{
|
||||
p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
|
||||
|
||||
/*
|
||||
* Please observe the order.
|
||||
* The parts must be read in the same order as they are sent!
|
||||
*/
|
||||
|
||||
/* Update the documentation in udp.h on changes
|
||||
* to the NetworkGameInfo wire-protocol! */
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 4 */
|
||||
{
|
||||
/* Only send the GRF Identification (GRF_ID and MD5 checksum) of
|
||||
* the GRFs that are needed, i.e. the ones that the server has
|
||||
* selected in the NewGRF GUI and not the ones that are used due
|
||||
* to the fact that they are in [newgrf-static] in openttd.cfg */
|
||||
const GRFConfig *c;
|
||||
uint count = 0;
|
||||
|
||||
/* Count number of GRFs to send information about */
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) count++;
|
||||
}
|
||||
p->Send_uint8(std::min<uint>(count, NETWORK_MAX_GRF_COUNT)); // Send number of GRFs
|
||||
|
||||
/* Send actual GRF Identifications */
|
||||
uint index = 0;
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) {
|
||||
if (index == NETWORK_MAX_GRF_COUNT - 1 && count > NETWORK_MAX_GRF_COUNT) {
|
||||
/* Send fake GRF ID */
|
||||
|
||||
p->Send_uint32(0x56D2B000);
|
||||
p->Send_binary((const char*) _out_of_band_grf_md5, 16);
|
||||
} else if (index >= NETWORK_MAX_GRF_COUNT) {
|
||||
break;
|
||||
} else {
|
||||
this->SendGRFIdentifier(p, &c->ident);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 3 */
|
||||
p->Send_uint32(info->game_date);
|
||||
p->Send_uint32(info->start_date);
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 2 */
|
||||
p->Send_uint8 (info->companies_max);
|
||||
p->Send_uint8 (info->companies_on);
|
||||
p->Send_uint8 (info->spectators_max);
|
||||
|
||||
/* NETWORK_GAME_INFO_VERSION = 1 */
|
||||
p->Send_string(info->server_name);
|
||||
p->Send_string(info->short_server_revision);
|
||||
p->Send_uint8 (0); // Used to be server-lang.
|
||||
p->Send_bool (info->use_password);
|
||||
p->Send_uint8 (info->clients_max);
|
||||
p->Send_uint8 (info->clients_on);
|
||||
p->Send_uint8 (info->spectators_on);
|
||||
p->Send_string(""); // Used to be map-name.
|
||||
p->Send_uint16(info->map_width);
|
||||
p->Send_uint16(info->map_height);
|
||||
p->Send_uint8 (info->map_set);
|
||||
p->Send_bool (info->dedicated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the NetworkGameInfo struct to the packet
|
||||
* @param p the packet to write the data to
|
||||
* @param info the NetworkGameInfo struct to serialize
|
||||
*/
|
||||
void NetworkUDPSocketHandler::SendNetworkGameInfoExtended(Packet *p, const NetworkGameInfo *info, uint16 flags, uint16 version)
|
||||
{
|
||||
p->Send_uint8(0); // version num
|
||||
|
||||
p->Send_uint32(info->game_date);
|
||||
p->Send_uint32(info->start_date);
|
||||
p->Send_uint8 (info->companies_max);
|
||||
p->Send_uint8 (info->companies_on);
|
||||
p->Send_uint8 (info->spectators_max);
|
||||
p->Send_string(info->server_name);
|
||||
p->Send_string(info->server_revision);
|
||||
p->Send_uint8 (0); // Used to be server-lang.
|
||||
p->Send_bool (info->use_password);
|
||||
p->Send_uint8 (info->clients_max);
|
||||
p->Send_uint8 (info->clients_on);
|
||||
p->Send_uint8 (info->spectators_on);
|
||||
p->Send_string(""); // Used to be map-name.
|
||||
p->Send_uint32(info->map_width);
|
||||
p->Send_uint32(info->map_height);
|
||||
p->Send_uint8 (info->map_set);
|
||||
p->Send_bool (info->dedicated);
|
||||
|
||||
{
|
||||
/* Only send the GRF Identification (GRF_ID and MD5 checksum) of
|
||||
* the GRFs that are needed, i.e. the ones that the server has
|
||||
* selected in the NewGRF GUI and not the ones that are used due
|
||||
* to the fact that they are in [newgrf-static] in openttd.cfg */
|
||||
const GRFConfig *c;
|
||||
uint count = 0;
|
||||
|
||||
/* Count number of GRFs to send information about */
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) count++;
|
||||
}
|
||||
p->Send_uint32(count); // Send number of GRFs
|
||||
|
||||
/* Send actual GRF Identifications */
|
||||
for (c = info->grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) {
|
||||
this->SendGRFIdentifier(p, &c->ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the NetworkGameInfo struct from the packet
|
||||
* @param p the packet to read the data from
|
||||
* @param info the NetworkGameInfo to deserialize into
|
||||
*/
|
||||
void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info)
|
||||
{
|
||||
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
|
||||
|
||||
info->game_info_version = p->Recv_uint8();
|
||||
|
||||
/*
|
||||
* Please observe the order.
|
||||
* The parts must be read in the same order as they are sent!
|
||||
*/
|
||||
|
||||
/* Update the documentation in udp.h on changes
|
||||
* to the NetworkGameInfo wire-protocol! */
|
||||
|
||||
switch (info->game_info_version) {
|
||||
case 4: {
|
||||
GRFConfig **dst = &info->grfconfig;
|
||||
uint i;
|
||||
uint num_grfs = p->Recv_uint8();
|
||||
|
||||
/* Broken/bad data. It cannot have that many NewGRFs. */
|
||||
if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
|
||||
|
||||
for (i = 0; i < num_grfs; i++) {
|
||||
GRFConfig *c = new GRFConfig();
|
||||
this->ReceiveGRFIdentifier(p, &c->ident);
|
||||
this->HandleIncomingNetworkGameInfoGRFConfig(c);
|
||||
|
||||
/* Append GRFConfig to the list */
|
||||
*dst = c;
|
||||
dst = &c->next;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
}
|
||||
|
||||
case 3:
|
||||
info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
FALLTHROUGH;
|
||||
|
||||
case 2:
|
||||
info->companies_max = p->Recv_uint8 ();
|
||||
info->companies_on = p->Recv_uint8 ();
|
||||
info->spectators_max = p->Recv_uint8 ();
|
||||
FALLTHROUGH;
|
||||
|
||||
case 1:
|
||||
p->Recv_string(info->server_name, sizeof(info->server_name));
|
||||
p->Recv_string(info->server_revision, sizeof(info->server_revision));
|
||||
p->Recv_uint8 (); // Used to contain server-lang.
|
||||
info->use_password = p->Recv_bool ();
|
||||
info->clients_max = p->Recv_uint8 ();
|
||||
info->clients_on = p->Recv_uint8 ();
|
||||
info->spectators_on = p->Recv_uint8 ();
|
||||
if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
|
||||
info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
|
||||
info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
|
||||
}
|
||||
while (p->Recv_uint8() != 0) {} // Used to contain the map-name.
|
||||
info->map_width = p->Recv_uint16();
|
||||
info->map_height = p->Recv_uint16();
|
||||
info->map_set = p->Recv_uint8 ();
|
||||
info->dedicated = p->Recv_bool ();
|
||||
|
||||
if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Deserializes the NetworkGameInfo struct from the packet
|
||||
* @param p the packet to read the data from
|
||||
* @param info the NetworkGameInfo to deserialize into
|
||||
*/
|
||||
void NetworkUDPSocketHandler::ReceiveNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info)
|
||||
{
|
||||
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
|
||||
|
||||
const uint8 version = p->Recv_uint8();
|
||||
if (version > 0) return; // Unknown version
|
||||
|
||||
info->game_info_version = 255;
|
||||
|
||||
info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
|
||||
info->companies_max = p->Recv_uint8 ();
|
||||
info->companies_on = p->Recv_uint8 ();
|
||||
info->spectators_max = p->Recv_uint8 ();
|
||||
p->Recv_string(info->server_name, sizeof(info->server_name));
|
||||
p->Recv_string(info->server_revision, sizeof(info->server_revision));
|
||||
p->Recv_uint8 (); // Used to contain server-lang.
|
||||
info->use_password = p->Recv_bool ();
|
||||
info->clients_max = p->Recv_uint8 ();
|
||||
info->clients_on = p->Recv_uint8 ();
|
||||
info->spectators_on = p->Recv_uint8 ();
|
||||
while (p->Recv_uint8() != 0) {} // Used to contain the map-name.
|
||||
info->map_width = p->Recv_uint32();
|
||||
info->map_height = p->Recv_uint32();
|
||||
info->map_set = p->Recv_uint8 ();
|
||||
info->dedicated = p->Recv_bool ();
|
||||
|
||||
{
|
||||
GRFConfig **dst = &info->grfconfig;
|
||||
uint i;
|
||||
uint num_grfs = p->Recv_uint32();
|
||||
|
||||
/* Broken/bad data. It cannot have that many NewGRFs. */
|
||||
if (num_grfs > MAX_NON_STATIC_GRF_COUNT) return;
|
||||
|
||||
for (i = 0; i < num_grfs; i++) {
|
||||
GRFConfig *c = new GRFConfig();
|
||||
this->ReceiveGRFIdentifier(p, &c->ident);
|
||||
this->HandleIncomingNetworkGameInfoGRFConfig(c);
|
||||
|
||||
/* Append GRFConfig to the list */
|
||||
*dst = c;
|
||||
dst = &c->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming packets by sending it to the correct function.
|
||||
* @param p the received packet
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#define NETWORK_CORE_UDP_H
|
||||
|
||||
#include "address.h"
|
||||
#include "game.h"
|
||||
#include "packet.h"
|
||||
|
||||
#include <vector>
|
||||
@@ -80,40 +79,7 @@ protected:
|
||||
|
||||
/**
|
||||
* Return of server information to the client.
|
||||
* This packet has several legacy versions, so we list the version and size of each "field":
|
||||
*
|
||||
* Version: Bytes: Description:
|
||||
* all 1 the version of this packet's structure
|
||||
*
|
||||
* 4+ 1 number of GRFs attached (n)
|
||||
* 4+ n * 20 unique identifier for GRF files. Consists of:
|
||||
* - one 4 byte variable with the GRF ID
|
||||
* - 16 bytes (sent sequentially) for the MD5 checksum
|
||||
* of the GRF
|
||||
*
|
||||
* 3+ 4 current game date in days since 1-1-0 (DMY)
|
||||
* 3+ 4 game introduction date in days since 1-1-0 (DMY)
|
||||
*
|
||||
* 2+ 1 maximum number of companies allowed on the server
|
||||
* 2+ 1 number of companies on the server
|
||||
* 2+ 1 maximum number of spectators allowed on the server
|
||||
*
|
||||
* 1+ var string with the name of the server
|
||||
* 1+ var string with the revision of the server
|
||||
* 1+ 1 the language run on the server
|
||||
* (0 = any, 1 = English, 2 = German, 3 = French)
|
||||
* 1+ 1 whether the server uses a password (0 = no, 1 = yes)
|
||||
* 1+ 1 maximum number of clients allowed on the server
|
||||
* 1+ 1 number of clients on the server
|
||||
* 1+ 1 number of spectators on the server
|
||||
* 1 & 2 2 current game date in days since 1-1-1920 (DMY)
|
||||
* 1 & 2 2 game introduction date in days since 1-1-1920 (DMY)
|
||||
* 1+ var string with the name of the map
|
||||
* 1+ 2 width of the map in tiles
|
||||
* 1+ 2 height of the map in tiles
|
||||
* 1+ 1 type of map:
|
||||
* (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland)
|
||||
* 1+ 1 whether the server is dedicated (0 = no, 1 = yes)
|
||||
* Serialized NetworkGameInfo. See game_info.h for details.
|
||||
* @param p The received packet.
|
||||
* @param client_addr The origin of the packet.
|
||||
*/
|
||||
@@ -237,15 +203,6 @@ protected:
|
||||
|
||||
void HandleUDPPacket(Packet *p, NetworkAddress *client_addr);
|
||||
|
||||
/**
|
||||
* Function that is called for every GRFConfig that is read when receiving
|
||||
* a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
|
||||
* function must set all appropriate fields. This GRF is later appended to
|
||||
* the grfconfig list of the NetworkGameInfo.
|
||||
* @param config the GRF to handle
|
||||
*/
|
||||
virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) { NOT_REACHED(); }
|
||||
|
||||
virtual void Receive_EX_MULTI(Packet *p, NetworkAddress *client_addr);
|
||||
public:
|
||||
NetworkUDPSocketHandler(NetworkAddressList *bind = nullptr);
|
||||
@@ -258,11 +215,6 @@ public:
|
||||
|
||||
void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false, bool short_mtu = false);
|
||||
void ReceivePackets();
|
||||
|
||||
void SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info);
|
||||
void SendNetworkGameInfoExtended(Packet *p, const NetworkGameInfo *info, uint16 flags, uint16 version);
|
||||
void ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info);
|
||||
void ReceiveNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info);
|
||||
};
|
||||
|
||||
#endif /* NETWORK_CORE_UDP_H */
|
||||
|
@@ -56,7 +56,6 @@ 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?
|
||||
bool _network_settings_access; ///< Can this client change server settings?
|
||||
NetworkServerGameInfo _network_game_info; ///< Information about our game.
|
||||
NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies.
|
||||
ClientID _network_own_client_id; ///< Our client identifier.
|
||||
ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client.
|
||||
@@ -632,13 +631,14 @@ public:
|
||||
{
|
||||
_networking = true;
|
||||
new ClientNetworkGameSocketHandler(s);
|
||||
MyClient::SendCompanyInformationQuery();
|
||||
MyClient::SendInformationQuery();
|
||||
}
|
||||
};
|
||||
|
||||
/* Query a server to fetch his game-info
|
||||
* If game_info is true, only the gameinfo is fetched,
|
||||
* else only the client_info is fetched */
|
||||
/**
|
||||
* Query a server to fetch his game-info.
|
||||
* @param address the address to query.
|
||||
*/
|
||||
void NetworkTCPQueryServer(NetworkAddress address)
|
||||
{
|
||||
if (!_network_available) return;
|
||||
@@ -1177,15 +1177,6 @@ void NetworkShutDown()
|
||||
NetworkCoreShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given version string is compatible with our version.
|
||||
* @param other the version string to compare to
|
||||
*/
|
||||
bool IsNetworkCompatibleVersion(const char *other, bool extended)
|
||||
{
|
||||
return strncmp(_openttd_revision, other, (extended ? NETWORK_LONG_REVISION_LENGTH : NETWORK_REVISION_LENGTH) - 1) == 0;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
extern "C" {
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "../stdafx.h"
|
||||
#include "../strings_func.h"
|
||||
#include "../date_func.h"
|
||||
#include "core/game_info.h"
|
||||
#include "network_admin.h"
|
||||
#include "network_base.h"
|
||||
#include "network_server.h"
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "core/address.h"
|
||||
#include "../core/pool_type.hpp"
|
||||
#include "../company_type.h"
|
||||
#include "../date_type.h"
|
||||
|
||||
/** Type for the pool with client information. */
|
||||
typedef Pool<NetworkClientInfo, ClientIndex, 8, MAX_CLIENT_SLOTS, PT_NCLIENT> NetworkClientInfoPool;
|
||||
|
@@ -23,10 +23,11 @@
|
||||
#include "../gfx_func.h"
|
||||
#include "../error.h"
|
||||
#include "../rev.h"
|
||||
#include "../fios.h"
|
||||
#include "core/game_info.h"
|
||||
#include "network.h"
|
||||
#include "network_base.h"
|
||||
#include "network_client.h"
|
||||
#include "network_gamelist.h"
|
||||
#include "../core/backup_type.hpp"
|
||||
#include "../thread.h"
|
||||
#include "../crashlog.h"
|
||||
@@ -404,15 +405,18 @@ static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1);
|
||||
* DEF_CLIENT_SEND_COMMAND has no parameters
|
||||
************/
|
||||
|
||||
/** Query the server for company information. */
|
||||
NetworkRecvStatus ClientNetworkGameSocketHandler::SendCompanyInformationQuery()
|
||||
/**
|
||||
* Query the server for server information.
|
||||
*/
|
||||
NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery()
|
||||
{
|
||||
my_client->status = STATUS_COMPANY_INFO;
|
||||
_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
|
||||
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
||||
|
||||
Packet *p = new Packet(PACKET_CLIENT_COMPANY_INFO, SHRT_MAX);
|
||||
my_client->SendPacket(p);
|
||||
my_client->SendPacket(new Packet(PACKET_CLIENT_GAME_INFO));
|
||||
my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO));
|
||||
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
|
||||
@@ -686,6 +690,28 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *
|
||||
return NETWORK_RECV_STATUS_SERVER_BANNED;
|
||||
}
|
||||
|
||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p)
|
||||
{
|
||||
if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_INACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
|
||||
NetworkGameList *item = GetLobbyGameInfo();
|
||||
|
||||
/* Clear any existing GRFConfig chain. */
|
||||
ClearGRFConfigList(&item->info.grfconfig);
|
||||
/* Retrieve the NetworkGameInfo from the packet. */
|
||||
DeserializeNetworkGameInfo(p, &item->info);
|
||||
/* Check for compatability with the client. */
|
||||
CheckGameCompatibility(item->info);
|
||||
/* Ensure we consider the server online. */
|
||||
item->online = true;
|
||||
|
||||
SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
|
||||
|
||||
/* We will receive company info next, so keep connection open. */
|
||||
if (this->status == STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_OKAY;
|
||||
return NETWORK_RECV_STATUS_CLOSE_QUERY;
|
||||
}
|
||||
|
||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p)
|
||||
{
|
||||
if (this->status != STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
@@ -847,7 +873,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P
|
||||
/* Check all GRFs */
|
||||
for (; grf_count > 0; grf_count--) {
|
||||
GRFIdentifier c;
|
||||
this->ReceiveGRFIdentifier(p, &c);
|
||||
DeserializeGRFIdentifier(p, &c);
|
||||
|
||||
/* Check whether we know this GRF */
|
||||
const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);
|
||||
|
@@ -50,6 +50,7 @@ protected:
|
||||
NetworkRecvStatus Receive_SERVER_FULL(Packet *p) override;
|
||||
NetworkRecvStatus Receive_SERVER_BANNED(Packet *p) override;
|
||||
NetworkRecvStatus Receive_SERVER_ERROR(Packet *p) override;
|
||||
NetworkRecvStatus Receive_SERVER_GAME_INFO(Packet *p) override;
|
||||
NetworkRecvStatus Receive_SERVER_COMPANY_INFO(Packet *p) override;
|
||||
NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet *p) override;
|
||||
NetworkRecvStatus Receive_SERVER_NEED_GAME_PASSWORD(Packet *p) override;
|
||||
@@ -90,7 +91,7 @@ public:
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
static NetworkRecvStatus SendCompanyInformationQuery();
|
||||
static NetworkRecvStatus SendInformationQuery();
|
||||
|
||||
static NetworkRecvStatus SendJoin();
|
||||
static NetworkRecvStatus SendCommand(const CommandPacket *cp);
|
||||
|
@@ -22,8 +22,8 @@
|
||||
#include "../gfx_type.h"
|
||||
#include "../openttd.h"
|
||||
#include "../company_type.h"
|
||||
#include "../string_type.h"
|
||||
|
||||
extern NetworkServerGameInfo _network_game_info;
|
||||
extern NetworkCompanyState *_network_company_states;
|
||||
|
||||
extern ClientID _network_own_client_id;
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#define NETWORK_GAMELIST_H
|
||||
|
||||
#include "core/address.h"
|
||||
#include "core/game_info.h"
|
||||
#include "network_type.h"
|
||||
|
||||
/** Structure with information shown in the game list (GUI) */
|
||||
|
@@ -1499,10 +1499,10 @@ struct NetworkLobbyWindow : public Window {
|
||||
break;
|
||||
|
||||
case WID_NL_REFRESH: // Refresh
|
||||
NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
|
||||
NetworkUDPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // general data
|
||||
/* Clear the information so removed companies don't remain */
|
||||
for (auto &company : this->company_info) company = {};
|
||||
|
||||
NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1570,8 +1570,7 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
|
||||
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START);
|
||||
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
|
||||
|
||||
NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
|
||||
NetworkUDPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // general data
|
||||
NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
|
||||
|
||||
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
|
||||
}
|
||||
@@ -1587,6 +1586,16 @@ NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company)
|
||||
return (lobby != nullptr && company < MAX_COMPANIES) ? &lobby->company_info[company] : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game information for the lobby.
|
||||
* @return the game info struct to write the (downloaded) data to.
|
||||
*/
|
||||
NetworkGameList *GetLobbyGameInfo()
|
||||
{
|
||||
NetworkLobbyWindow *lobby = dynamic_cast<NetworkLobbyWindow *>(FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY));
|
||||
return lobby != nullptr ? lobby->server : nullptr;
|
||||
}
|
||||
|
||||
/* The window below gives information about the connected clients
|
||||
* and also makes able to kick them (if server) and stuff like that. */
|
||||
|
||||
|
@@ -11,9 +11,11 @@
|
||||
#define NETWORK_GUI_H
|
||||
|
||||
#include "../company_type.h"
|
||||
#include "../date_type.h"
|
||||
#include "../economy_type.h"
|
||||
#include "../window_type.h"
|
||||
#include "network_type.h"
|
||||
#include "network_gamelist.h"
|
||||
|
||||
void ShowNetworkNeedPassword(NetworkPasswordType npt);
|
||||
void ShowNetworkGiveMoneyWindow(CompanyID company);
|
||||
@@ -37,5 +39,6 @@ struct NetworkCompanyInfo : NetworkCompanyStats {
|
||||
};
|
||||
|
||||
NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company);
|
||||
NetworkGameList *GetLobbyGameInfo();
|
||||
|
||||
#endif /* NETWORK_GUI_H */
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "core/tcp_game.h"
|
||||
|
||||
#include "../command_type.h"
|
||||
#include "../date_type.h"
|
||||
|
||||
#ifdef RANDOM_DEBUG
|
||||
/**
|
||||
@@ -98,8 +99,6 @@ void NetworkAddServer(const char *b);
|
||||
void NetworkRebuildHostList();
|
||||
void UpdateNetworkGameWindow();
|
||||
|
||||
bool IsNetworkCompatibleVersion(const char *version, bool extended = false);
|
||||
|
||||
/* From network_command.cpp */
|
||||
/**
|
||||
* Everything we need to know about a command to be able to execute it.
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "../stdafx.h"
|
||||
#include "../strings_func.h"
|
||||
#include "../date_func.h"
|
||||
#include "core/game_info.h"
|
||||
#include "network_admin.h"
|
||||
#include "network_server.h"
|
||||
#include "network_udp.h"
|
||||
@@ -356,6 +357,20 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendClientInfo(NetworkClientIn
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
|
||||
/** Send the client information about the server. */
|
||||
NetworkRecvStatus ServerNetworkGameSocketHandler::SendGameInfo()
|
||||
{
|
||||
NetworkGameInfo ngi;
|
||||
FillNetworkGameInfo(ngi);
|
||||
|
||||
Packet *p = new Packet(PACKET_SERVER_GAME_INFO, SHRT_MAX);
|
||||
SerializeNetworkGameInfo(p, &ngi);
|
||||
|
||||
this->SendPacket(p);
|
||||
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
|
||||
/** Send the client information about the companies. */
|
||||
NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo()
|
||||
{
|
||||
@@ -495,7 +510,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
|
||||
|
||||
p->Send_uint32 (grf_count);
|
||||
for (c = _grfconfig; c != nullptr; c = c->next) {
|
||||
if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
|
||||
if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(p, &c->ident);
|
||||
}
|
||||
|
||||
this->SendPacket(p);
|
||||
@@ -864,6 +879,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendSettingsAccessUpdate(bool
|
||||
* DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
|
||||
************/
|
||||
|
||||
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p)
|
||||
{
|
||||
return this->SendGameInfo();
|
||||
}
|
||||
|
||||
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p)
|
||||
{
|
||||
return this->SendCompanyInfo();
|
||||
|
@@ -24,6 +24,7 @@ extern NetworkClientSocketPool _networkclientsocket_pool;
|
||||
class ServerNetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkGameSocketHandler, public TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED> {
|
||||
protected:
|
||||
NetworkRecvStatus Receive_CLIENT_JOIN(Packet *p) override;
|
||||
NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet *p) override;
|
||||
NetworkRecvStatus Receive_CLIENT_COMPANY_INFO(Packet *p) override;
|
||||
NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet *p) override;
|
||||
NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet *p) override;
|
||||
@@ -43,6 +44,7 @@ protected:
|
||||
NetworkRecvStatus Receive_CLIENT_NEWGRFS_CHECKED(Packet *p) override;
|
||||
NetworkRecvStatus Receive_CLIENT_MOVE(Packet *p) override;
|
||||
|
||||
NetworkRecvStatus SendGameInfo();
|
||||
NetworkRecvStatus SendCompanyInfo();
|
||||
NetworkRecvStatus SendNewGRFCheck();
|
||||
NetworkRecvStatus SendWelcome();
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#ifndef NETWORK_TYPE_H
|
||||
#define NETWORK_TYPE_H
|
||||
|
||||
#include "core/game.h"
|
||||
#include "core/config.h"
|
||||
|
||||
/** How many clients can we have */
|
||||
static const uint MAX_CLIENTS = 255;
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include "../date_func.h"
|
||||
#include "../map_func.h"
|
||||
#include "../debug.h"
|
||||
#include "core/game_info.h"
|
||||
#include "network_gamelist.h"
|
||||
#include "network_internal.h"
|
||||
#include "network_udp.h"
|
||||
@@ -192,27 +193,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, Networ
|
||||
}
|
||||
|
||||
NetworkGameInfo ngi;
|
||||
|
||||
/* Update some game_info */
|
||||
ngi.clients_on = _network_game_info.clients_on;
|
||||
ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
|
||||
|
||||
ngi.use_password = !StrEmpty(_settings_client.network.server_password);
|
||||
ngi.clients_max = _settings_client.network.max_clients;
|
||||
ngi.companies_on = (byte)Company::GetNumItems();
|
||||
ngi.companies_max = _settings_client.network.max_companies;
|
||||
ngi.spectators_on = NetworkSpectatorCount();
|
||||
ngi.spectators_max = _settings_client.network.max_spectators;
|
||||
ngi.game_date = _date;
|
||||
ngi.map_width = MapSizeX();
|
||||
ngi.map_height = MapSizeY();
|
||||
ngi.map_set = _settings_game.game_creation.landscape;
|
||||
ngi.dedicated = _network_dedicated;
|
||||
ngi.grfconfig = _grfconfig;
|
||||
|
||||
strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name));
|
||||
strecpy(ngi.server_revision, _openttd_revision, lastof(ngi.server_revision));
|
||||
strecpy(ngi.short_server_revision, _openttd_revision, lastof(ngi.short_server_revision));
|
||||
FillNetworkGameInfo(ngi);
|
||||
|
||||
if (p->CanReadFromPacket(8) && p->Recv_uint32() == FIND_SERVER_EXTENDED_TOKEN) {
|
||||
this->Reply_CLIENT_FIND_SERVER_extended(p, client_addr, &ngi);
|
||||
@@ -220,7 +201,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, Networ
|
||||
}
|
||||
|
||||
Packet packet(PACKET_UDP_SERVER_RESPONSE);
|
||||
this->SendNetworkGameInfo(&packet, &ngi);
|
||||
SerializeNetworkGameInfo(&packet, &ngi);
|
||||
|
||||
/* Let the client know that we are here */
|
||||
this->SendPacket(&packet, client_addr);
|
||||
@@ -234,7 +215,7 @@ void ServerNetworkUDPSocketHandler::Reply_CLIENT_FIND_SERVER_extended(Packet *p,
|
||||
uint16 version = p->Recv_uint16();
|
||||
|
||||
Packet packet(PACKET_UDP_EX_SERVER_RESPONSE, SHRT_MAX);
|
||||
this->SendNetworkGameInfoExtended(&packet, ngi, flags, version);
|
||||
SerializeNetworkGameInfoExtended(&packet, ngi, flags, version);
|
||||
|
||||
/* Let the client know that we are here */
|
||||
this->SendPacket(&packet, client_addr, false, false, true);
|
||||
@@ -335,7 +316,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ
|
||||
|
||||
/* The name could be an empty string, if so take the filename */
|
||||
strecpy(name, info.name, lastof(name));
|
||||
this->SendGRFIdentifier(&packet, &info.ident);
|
||||
SerializeGRFIdentifier(&packet, &info.ident);
|
||||
packet.Send_string(name);
|
||||
}
|
||||
|
||||
@@ -348,7 +329,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ
|
||||
|
||||
for (i = 0; i < num_grfs; i++) {
|
||||
GRFInfo info;
|
||||
this->ReceiveGRFIdentifier(p, &info.ident);
|
||||
DeserializeGRFIdentifier(p, &info.ident);
|
||||
|
||||
if (memcmp(info.ident.md5sum, _out_of_band_grf_md5, 16) == 0) {
|
||||
if (info.ident.grfid == 0x56D2B000) {
|
||||
@@ -393,7 +374,6 @@ protected:
|
||||
void Receive_EX_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr) override;
|
||||
void Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr) override;
|
||||
void Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr) override;
|
||||
void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) override;
|
||||
public:
|
||||
virtual ~ClientNetworkUDPSocketHandler() {}
|
||||
};
|
||||
@@ -420,14 +400,20 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE_Common(Packet *p, Ne
|
||||
/* Find next item */
|
||||
item = NetworkGameListAddItem(*client_addr);
|
||||
|
||||
/* Clear any existing GRFConfig chain. */
|
||||
ClearGRFConfigList(&item->info.grfconfig);
|
||||
if (extended) {
|
||||
this->ReceiveNetworkGameInfoExtended(p, &item->info);
|
||||
/* Retrieve the NetworkGameInfo from the packet. */
|
||||
DeserializeNetworkGameInfoExtended(p, &item->info);
|
||||
} else {
|
||||
this->ReceiveNetworkGameInfo(p, &item->info);
|
||||
/* Retrieve the NetworkGameInfo from the packet. */
|
||||
DeserializeNetworkGameInfo(p, &item->info);
|
||||
}
|
||||
/* Check for compatability with the client. */
|
||||
CheckGameCompatibility(item->info);
|
||||
/* Ensure we consider the server online. */
|
||||
item->online = true;
|
||||
|
||||
item->info.compatible = true;
|
||||
{
|
||||
/* Checks whether there needs to be a request for names of GRFs and makes
|
||||
* the request if necessary. GRFs that need to be requested are the GRFs
|
||||
@@ -447,7 +433,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE_Common(Packet *p, Ne
|
||||
|
||||
packet.Send_uint8(in_request_count);
|
||||
for (i = 0; i < in_request_count; i++) {
|
||||
this->SendGRFIdentifier(&packet, &in_request[i]->ident);
|
||||
SerializeGRFIdentifier(&packet, &in_request[i]->ident);
|
||||
}
|
||||
|
||||
this->SendPacket(&packet, &item->address);
|
||||
@@ -476,12 +462,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE_Common(Packet *p, Ne
|
||||
strecat(item->info.server_name, " (IPv6)", lastof(item->info.server_name));
|
||||
}
|
||||
|
||||
/* Check if we are allowed on this server based on the revision-match */
|
||||
item->info.version_compatible = IsNetworkCompatibleVersion(item->info.server_revision, extended);
|
||||
item->info.compatible &= item->info.version_compatible; // Already contains match for GRFs
|
||||
|
||||
item->online = true;
|
||||
|
||||
UpdateNetworkGameWindow();
|
||||
}
|
||||
|
||||
@@ -535,7 +515,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
|
||||
char name[NETWORK_GRF_NAME_LENGTH];
|
||||
GRFIdentifier c;
|
||||
|
||||
this->ReceiveGRFIdentifier(p, &c);
|
||||
DeserializeGRFIdentifier(p, &c);
|
||||
p->Recv_string(name, sizeof(name));
|
||||
|
||||
/* An empty name is not possible under normal circumstances
|
||||
@@ -552,25 +532,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
|
||||
}
|
||||
}
|
||||
|
||||
void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
|
||||
{
|
||||
/* Find the matching GRF file */
|
||||
const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum);
|
||||
if (f == nullptr) {
|
||||
/* Don't know the GRF, so mark game incompatible and the (possibly)
|
||||
* already resolved name for this GRF (another server has sent the
|
||||
* name of the GRF already */
|
||||
config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true);
|
||||
config->status = GCS_NOT_FOUND;
|
||||
} else {
|
||||
config->filename = f->filename;
|
||||
config->name = f->name;
|
||||
config->info = f->info;
|
||||
config->url = f->url;
|
||||
}
|
||||
SetBit(config->flags, GCF_COPY);
|
||||
}
|
||||
|
||||
/** Broadcast to all ips */
|
||||
static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
|
||||
{
|
||||
|
Reference in New Issue
Block a user