mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r14730) -Codechange: remove the need for networkclientsockets and networkclientinfo structs to be in a contiguous piece of memory and put them in a pool.
-Note: 255 should really be enough for now... making it any more means network protocol bumps.
This commit is contained in:
parent
94dd23aaf8
commit
afddfcb2b1
|
@ -16,30 +16,25 @@
|
|||
#include "tcp.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "../../oldpool_func.h"
|
||||
|
||||
/** Very ugly temporary hack !!! */
|
||||
void NetworkClientSocket::Initialize()
|
||||
/** Make very sure the preconditions given in network_type.h are actually followed */
|
||||
assert_compile(MAX_CLIENT_SLOTS == (MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK) << NCI_BITS_PER_POOL_BLOCK);
|
||||
assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS);
|
||||
|
||||
typedef ClientIndex NetworkClientSocketID;
|
||||
DEFINE_OLD_POOL_GENERIC(NetworkClientSocket, NetworkClientSocket);
|
||||
|
||||
NetworkClientSocket::NetworkClientSocket(ClientID client_id)
|
||||
{
|
||||
this->sock = INVALID_SOCKET;
|
||||
|
||||
this->client_id = INVALID_CLIENT_ID;
|
||||
this->last_frame = 0;
|
||||
this->last_frame_server = 0;
|
||||
this->lag_test = 0;
|
||||
|
||||
this->client_id = client_id;
|
||||
this->status = STATUS_INACTIVE;
|
||||
this->has_quit = false;
|
||||
this->writable = false;
|
||||
|
||||
this->packet_queue = NULL;
|
||||
this->packet_recv = NULL;
|
||||
|
||||
this->command_queue = NULL;
|
||||
}
|
||||
|
||||
void NetworkClientSocket::Destroy()
|
||||
NetworkClientSocket::~NetworkClientSocket()
|
||||
{
|
||||
closesocket(this->sock);
|
||||
if (this->sock != INVALID_SOCKET) closesocket(this->sock);
|
||||
this->writable = false;
|
||||
this->has_quit = true;
|
||||
|
||||
|
@ -57,6 +52,10 @@ void NetworkClientSocket::Destroy()
|
|||
free(this->command_queue);
|
||||
this->command_queue = p;
|
||||
}
|
||||
|
||||
this->sock = INVALID_SOCKET;
|
||||
this->client_id = INVALID_CLIENT_ID;
|
||||
this->status = STATUS_INACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,12 +84,17 @@ enum ClientStatus {
|
|||
STATUS_ACTIVE, ///< The client is active within in the game
|
||||
};
|
||||
|
||||
|
||||
class NetworkClientSocket;
|
||||
DECLARE_OLD_POOL(NetworkClientSocket, NetworkClientSocket, NCI_BITS_PER_POOL_BLOCK, MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK);
|
||||
|
||||
/** Base socket handler for all TCP sockets */
|
||||
class NetworkClientSocket : public NetworkSocketHandler {
|
||||
class NetworkClientSocket : public PoolItem<NetworkClientSocket, ClientIndex, &_NetworkClientSocket_pool>, public NetworkSocketHandler {
|
||||
/* TODO: rewrite into a proper class */
|
||||
private:
|
||||
Packet *packet_queue; ///< Packets that are awaiting delivery
|
||||
Packet *packet_recv; ///< Partially received packet
|
||||
NetworkClientInfo *info; ///< Client info related to this socket
|
||||
public:
|
||||
ClientID client_id; ///< Client identifier
|
||||
uint32 last_frame; ///< Last frame we have executed
|
||||
|
@ -102,8 +107,6 @@ public:
|
|||
CommandPacket *command_queue; ///< The command-queue awaiting delivery
|
||||
|
||||
NetworkRecvStatus CloseConnection();
|
||||
void Initialize();
|
||||
void Destroy();
|
||||
|
||||
void Send_Packet(Packet *packet);
|
||||
bool Send_Packets();
|
||||
|
@ -111,27 +114,24 @@ public:
|
|||
|
||||
Packet *Recv_Packet(NetworkRecvStatus *status);
|
||||
|
||||
inline bool IsValid() const { return this->IsConnected(); }
|
||||
inline NetworkClientInfo *GetInfo() const
|
||||
{
|
||||
extern NetworkClientSocket _clients[MAX_CLIENTS];
|
||||
return GetNetworkClientInfo(this - _clients);
|
||||
}
|
||||
};
|
||||
NetworkClientSocket(ClientID client_id = INVALID_CLIENT_ID);
|
||||
~NetworkClientSocket();
|
||||
|
||||
// Here we keep track of the clients
|
||||
// (and the client uses [0] for his own communication)
|
||||
extern NetworkClientSocket _clients[MAX_CLIENTS];
|
||||
#define GetNetworkClientSocket(i) (&_clients[i])
|
||||
inline bool IsValid() const { return this->IsConnected(); }
|
||||
inline void SetInfo(NetworkClientInfo *info) { assert(info != NULL && this->info == NULL); this->info = info; }
|
||||
inline NetworkClientInfo *GetInfo() const { return this->info; }
|
||||
};
|
||||
|
||||
static inline bool IsValidNetworkClientSocketIndex(ClientIndex index)
|
||||
{
|
||||
return (uint)index < MAX_CLIENTS && GetNetworkClientSocket(index)->IsValid();
|
||||
return (uint)index < GetNetworkClientSocketPoolSize() && GetNetworkClientSocket(index)->IsValid();
|
||||
}
|
||||
|
||||
#define FOR_ALL_CLIENT_SOCKETS_FROM(d, start) for (d = GetNetworkClientSocket(start); d != GetNetworkClientSocket(MAX_CLIENTS); d++) if (d->IsValid())
|
||||
#define FOR_ALL_CLIENT_SOCKETS_FROM(d, start) for (d = (start < GetNetworkClientSocketPoolSize() ? GetNetworkClientSocket(start) : NULL); d != NULL; d = (d->index + 1U < GetNetworkClientSocketPoolSize()) ? GetNetworkClientSocket(d->index + 1U) : NULL) if (d->IsValid())
|
||||
#define FOR_ALL_CLIENT_SOCKETS(d) FOR_ALL_CLIENT_SOCKETS_FROM(d, 0)
|
||||
|
||||
typedef NetworkClientSocket NetworkTCPSocketHandler;
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
#endif /* NETWORK_CORE_TCP_H */
|
||||
|
|
|
@ -42,15 +42,18 @@
|
|||
#endif /* DEBUG_DUMP_COMMANDS */
|
||||
#include "table/strings.h"
|
||||
#include "../company_base.h"
|
||||
#include "../oldpool_func.h"
|
||||
|
||||
DECLARE_POSTFIX_INCREMENT(ClientID);
|
||||
|
||||
typedef ClientIndex NetworkClientInfoID;
|
||||
DEFINE_OLD_POOL_GENERIC(NetworkClientInfo, NetworkClientInfo);
|
||||
|
||||
bool _network_server; ///< network-server is active
|
||||
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?
|
||||
NetworkServerGameInfo _network_game_info;
|
||||
NetworkClientInfo _network_client_info[MAX_CLIENT_SLOTS];
|
||||
NetworkCompanyState *_network_company_states = NULL;
|
||||
ClientID _network_own_client_id;
|
||||
ClientID _redirect_console_to_client;
|
||||
|
@ -83,12 +86,6 @@ extern NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket
|
|||
extern NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket
|
||||
extern NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket
|
||||
|
||||
// Here we keep track of the clients
|
||||
// (and the client uses [0] for his own communication)
|
||||
NetworkClientSocket _clients[MAX_CLIENTS];
|
||||
|
||||
|
||||
|
||||
// The listen socket for the server
|
||||
static SOCKET _listensocket;
|
||||
|
||||
|
@ -316,9 +313,6 @@ static void NetworkClientError(NetworkRecvStatus res, NetworkClientSocket* cs)
|
|||
if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
|
||||
res != NETWORK_RECV_STATUS_SERVER_BANNED) {
|
||||
SEND_COMMAND(PACKET_CLIENT_ERROR)(errorno);
|
||||
|
||||
// Dequeue all commands before closing the socket
|
||||
GetNetworkClientSocket(0)->Send_Packets();
|
||||
}
|
||||
|
||||
_switch_mode = SM_MENU;
|
||||
|
@ -419,30 +413,24 @@ void ParseConnectionString(const char **company, const char **port, char *connec
|
|||
// Used both by the server and the client
|
||||
static NetworkClientSocket *NetworkAllocClient(SOCKET s)
|
||||
{
|
||||
NetworkClientSocket *cs;
|
||||
byte client_no = 0;
|
||||
|
||||
if (_network_server) {
|
||||
// Can we handle a new client?
|
||||
if (_network_clients_connected >= MAX_CLIENTS) return NULL;
|
||||
if (_network_game_info.clients_on >= _settings_client.network.max_clients) return NULL;
|
||||
|
||||
// Register the login
|
||||
client_no = _network_clients_connected++;
|
||||
_network_clients_connected++;
|
||||
}
|
||||
|
||||
cs = GetNetworkClientSocket(client_no);
|
||||
cs->Initialize();
|
||||
NetworkClientSocket *cs = new NetworkClientSocket(INVALID_CLIENT_ID);
|
||||
cs->sock = s;
|
||||
cs->last_frame = _frame_counter;
|
||||
cs->last_frame_server = _frame_counter;
|
||||
|
||||
if (_network_server) {
|
||||
NetworkClientInfo *ci = cs->GetInfo();
|
||||
memset(ci, 0, sizeof(*ci));
|
||||
|
||||
cs->client_id = _network_client_id++;
|
||||
ci->client_id = cs->client_id;
|
||||
NetworkClientInfo *ci = new NetworkClientInfo(cs->client_id);
|
||||
cs->SetInfo(ci);
|
||||
ci->client_playas = COMPANY_INACTIVE_CLIENT;
|
||||
ci->join_date = _date;
|
||||
|
||||
|
@ -455,12 +443,7 @@ static NetworkClientSocket *NetworkAllocClient(SOCKET s)
|
|||
// Close a connection
|
||||
void NetworkCloseClient(NetworkClientSocket *cs)
|
||||
{
|
||||
NetworkClientInfo *ci;
|
||||
// Socket is already dead
|
||||
if (cs->sock == INVALID_SOCKET) {
|
||||
cs->has_quit = true;
|
||||
return;
|
||||
}
|
||||
assert(cs->sock != INVALID_SOCKET);
|
||||
|
||||
DEBUG(net, 1, "Closed client connection %d", cs->client_id);
|
||||
|
||||
|
@ -491,31 +474,16 @@ void NetworkCloseClient(NetworkClientSocket *cs)
|
|||
NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", CLIENT_ID_SERVER);
|
||||
}
|
||||
|
||||
cs->Destroy();
|
||||
|
||||
// Close the gap in the client-list
|
||||
ci = cs->GetInfo();
|
||||
|
||||
if (_network_server) {
|
||||
// We just lost one client :(
|
||||
if (cs->status >= STATUS_AUTH) _network_game_info.clients_on--;
|
||||
_network_clients_connected--;
|
||||
|
||||
while ((cs + 1) != GetNetworkClientSocket(MAX_CLIENTS) && (cs + 1)->sock != INVALID_SOCKET) {
|
||||
*cs = *(cs + 1);
|
||||
*ci = *(ci + 1);
|
||||
cs++;
|
||||
ci++;
|
||||
}
|
||||
|
||||
InvalidateWindow(WC_CLIENT_LIST, 0);
|
||||
}
|
||||
|
||||
// Reset the status of the last socket
|
||||
cs->sock = INVALID_SOCKET;
|
||||
cs->status = STATUS_INACTIVE;
|
||||
cs->client_id = INVALID_CLIENT_ID;
|
||||
ci->client_id = INVALID_CLIENT_ID;
|
||||
delete cs->GetInfo();
|
||||
delete cs;
|
||||
|
||||
CheckMinActiveClients();
|
||||
}
|
||||
|
@ -697,22 +665,20 @@ static void NetworkClose()
|
|||
|
||||
free(_network_company_states);
|
||||
_network_company_states = NULL;
|
||||
|
||||
_NetworkClientSocket_pool.CleanPool();
|
||||
_NetworkClientInfo_pool.CleanPool();
|
||||
}
|
||||
|
||||
// Inits the network (cleans sockets and stuff)
|
||||
static void NetworkInitialize()
|
||||
{
|
||||
NetworkClientSocket *cs;
|
||||
|
||||
_local_command_queue = NULL;
|
||||
|
||||
// Clean all client-sockets
|
||||
for (cs = _clients; cs != &_clients[MAX_CLIENTS]; cs++) {
|
||||
cs->Initialize();
|
||||
}
|
||||
|
||||
// Clean the client_info memory
|
||||
memset(&_network_client_info, 0, sizeof(_network_client_info));
|
||||
_NetworkClientSocket_pool.CleanPool();
|
||||
_NetworkClientSocket_pool.AddBlockToPool();
|
||||
_NetworkClientInfo_pool.CleanPool();
|
||||
_NetworkClientInfo_pool.AddBlockToPool();
|
||||
|
||||
_sync_frame = 0;
|
||||
_network_first_time = true;
|
||||
|
@ -817,8 +783,6 @@ bool NetworkClientConnectGame(const char *host, uint16 port)
|
|||
|
||||
static void NetworkInitGameInfo()
|
||||
{
|
||||
NetworkClientInfo *ci;
|
||||
|
||||
if (StrEmpty(_settings_client.network.server_name)) {
|
||||
snprintf(_settings_client.network.server_name, sizeof(_settings_client.network.server_name), "Unnamed Server");
|
||||
}
|
||||
|
@ -827,12 +791,7 @@ static void NetworkInitGameInfo()
|
|||
_network_game_info.clients_on = _network_dedicated ? 0 : 1;
|
||||
_network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
|
||||
|
||||
// We use _network_client_info[MAX_CLIENT_SLOTS - 1] to store the server-data in it
|
||||
// The client identifier is CLIENT_ID_SERVER ( = 1)
|
||||
ci = &_network_client_info[MAX_CLIENT_SLOTS - 1];
|
||||
memset(ci, 0, sizeof(*ci));
|
||||
|
||||
ci->client_id = CLIENT_ID_SERVER;
|
||||
NetworkClientInfo *ci = new NetworkClientInfo(CLIENT_ID_SERVER);
|
||||
ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : _local_company;
|
||||
|
||||
strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name));
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
#ifdef ENABLE_NETWORK
|
||||
|
||||
#include "network_type.h"
|
||||
#include "../oldpool.h"
|
||||
|
||||
struct NetworkClientInfo {
|
||||
DECLARE_OLD_POOL(NetworkClientInfo, NetworkClientInfo, NCI_BITS_PER_POOL_BLOCK, MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK);
|
||||
|
||||
struct NetworkClientInfo : PoolItem<NetworkClientInfo, ClientIndex, &_NetworkClientInfo_pool> {
|
||||
ClientID client_id; ///< Client identifier (same as ClientState->client_id)
|
||||
char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the client
|
||||
byte client_lang; ///< The language of the client
|
||||
|
@ -18,21 +21,18 @@ struct NetworkClientInfo {
|
|||
Date join_date; ///< Gamedate the client has joined
|
||||
char unique_id[NETWORK_UNIQUE_ID_LENGTH]; ///< Every play sends an unique id so we can indentify him
|
||||
|
||||
NetworkClientInfo(ClientID client_id = INVALID_CLIENT_ID) : client_id(client_id) {}
|
||||
~NetworkClientInfo() { client_id = INVALID_CLIENT_ID; }
|
||||
|
||||
inline bool IsValid() const { return client_id != INVALID_CLIENT_ID; }
|
||||
};
|
||||
|
||||
static NetworkClientInfo *GetNetworkClientInfo(int ci)
|
||||
{
|
||||
extern NetworkClientInfo _network_client_info[MAX_CLIENT_SLOTS];
|
||||
return &_network_client_info[ci];
|
||||
}
|
||||
|
||||
static inline bool IsValidNetworkClientInfoIndex(ClientIndex index)
|
||||
{
|
||||
return (uint)index < MAX_CLIENT_SLOTS && GetNetworkClientInfo(index)->IsValid();
|
||||
return (uint)index < GetNetworkClientInfoPoolSize() && GetNetworkClientInfo(index)->IsValid();
|
||||
}
|
||||
|
||||
#define FOR_ALL_CLIENT_INFOS_FROM(d, start) for (ci = GetNetworkClientInfo(start); ci != GetNetworkClientInfo(MAX_CLIENT_SLOTS); ci++) if (ci->IsValid())
|
||||
#define FOR_ALL_CLIENT_INFOS_FROM(d, start) for (d = GetNetworkClientInfo(start); d != NULL; d = (d->index + 1U < GetNetworkClientInfoPoolSize()) ? GetNetworkClientInfo(d->index + 1U) : NULL) if (d->IsValid())
|
||||
#define FOR_ALL_CLIENT_INFOS(d) FOR_ALL_CLIENT_INFOS_FROM(d, 0)
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
|
|
@ -301,8 +301,13 @@ struct NetworkChatWindow : public QueryStringBaseWindow {
|
|||
/* First, try clients */
|
||||
if (*item < MAX_CLIENT_SLOTS) {
|
||||
/* Skip inactive clients */
|
||||
while (GetNetworkClientInfo(*item)->client_id == INVALID_CLIENT_ID && *item < MAX_CLIENT_SLOTS) (*item)++;
|
||||
if (*item < MAX_CLIENT_SLOTS) return GetNetworkClientInfo(*item)->client_name;
|
||||
NetworkClientInfo *ci;
|
||||
FOR_ALL_CLIENT_INFOS_FROM(ci, *item + 1) break;
|
||||
if (ci != NULL) {
|
||||
*item = ci->index;
|
||||
return ci->client_name;
|
||||
}
|
||||
*item = MAX_CLIENT_SLOTS;
|
||||
}
|
||||
|
||||
/* Then, try townnames */
|
||||
|
|
|
@ -420,23 +420,15 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
|
|||
}
|
||||
|
||||
// We don't have this client_id yet, find an empty client_id, and put the data there
|
||||
for (int i = 0; i < MAX_CLIENT_SLOTS; i++) {
|
||||
ci = GetNetworkClientInfo(i);
|
||||
if (!ci->IsValid()) break;
|
||||
}
|
||||
if (ci != GetNetworkClientInfo(MAX_CLIENT_SLOTS)) {
|
||||
ci->client_id = client_id;
|
||||
ci->client_playas = playas;
|
||||
ci = new NetworkClientInfo(client_id);
|
||||
ci->client_playas = playas;
|
||||
if (client_id == _network_own_client_id) MY_CLIENT->SetInfo(ci);
|
||||
|
||||
strecpy(ci->client_name, name, lastof(ci->client_name));
|
||||
strecpy(ci->client_name, name, lastof(ci->client_name));
|
||||
|
||||
InvalidateWindow(WC_CLIENT_LIST, 0);
|
||||
InvalidateWindow(WC_CLIENT_LIST, 0);
|
||||
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
|
||||
// Here the program should never ever come.....
|
||||
return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
|
||||
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
|
||||
|
@ -765,9 +757,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
|
|||
ci = NetworkFindClientInfoFromClientID(client_id);
|
||||
if (ci != NULL) {
|
||||
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str);
|
||||
|
||||
// The client is gone, give the NetworkClientInfo free
|
||||
ci->client_id = INVALID_CLIENT_ID;
|
||||
delete ci;
|
||||
}
|
||||
|
||||
InvalidateWindow(WC_CLIENT_LIST, 0);
|
||||
|
@ -786,9 +776,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
|
|||
ci = NetworkFindClientInfoFromClientID(client_id);
|
||||
if (ci != NULL) {
|
||||
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str);
|
||||
|
||||
// The client is gone, give the NetworkClientInfo free
|
||||
ci->client_id = INVALID_CLIENT_ID;
|
||||
delete ci;
|
||||
} else {
|
||||
DEBUG(net, 0, "Unknown client (%d) is leaving the game", client_id);
|
||||
}
|
||||
|
|
|
@ -967,7 +967,7 @@ struct NetworkStartServerWindow : public QueryStringBaseWindow {
|
|||
case NSSW_CLIENTS_TXT: // Click on number of clients
|
||||
this->widget_id = NSSW_CLIENTS_TXT;
|
||||
SetDParam(0, _settings_client.network.max_clients);
|
||||
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, this, CS_NUMERAL, QSF_NONE);
|
||||
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 4, 50, this, CS_NUMERAL, QSF_NONE);
|
||||
break;
|
||||
|
||||
case NSSW_COMPANIES_TXT: // Click on number of companies
|
||||
|
@ -979,7 +979,7 @@ struct NetworkStartServerWindow : public QueryStringBaseWindow {
|
|||
case NSSW_SPECTATORS_TXT: // Click on number of spectators
|
||||
this->widget_id = NSSW_SPECTATORS_TXT;
|
||||
SetDParam(0, _settings_client.network.max_spectators);
|
||||
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, this, CS_NUMERAL, QSF_NONE);
|
||||
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 4, 50, this, CS_NUMERAL, QSF_NONE);
|
||||
break;
|
||||
|
||||
case NSSW_LANGUAGE_BTN: { // Language
|
||||
|
|
|
@ -917,7 +917,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
|
|||
* 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... */
|
||||
cp->company = OWNER_BEGIN;
|
||||
cp->p2 = cs - _clients; // XXX - UGLY! p2 is mis-used to get the client-id in CmdCompanyCtrl
|
||||
cp->p2 = cs->index; // XXX - UGLY! p2 is mis-used to get the client-id in CmdCompanyCtrl
|
||||
}
|
||||
|
||||
// The frame can be executed in the same frame as the next frame-packet
|
||||
|
|
|
@ -13,12 +13,18 @@
|
|||
#include "core/game.h"
|
||||
|
||||
enum {
|
||||
/** How many clients can we have */
|
||||
MAX_CLIENTS = 255,
|
||||
|
||||
/** The number of bits per pool client block */
|
||||
NCI_BITS_PER_POOL_BLOCK = 3, // => 8 items per block
|
||||
/**
|
||||
* How many clients can we have? Like.. MAX_COMPANIES is the amount of
|
||||
* companies that can really play.. so.. a max of 3 spectators.. gives us..
|
||||
* MAX_COMPANIES + 3
|
||||
* The number of slots; must be a multiple of (1 << NCI_BITS_PER_POOL_BLOCK)
|
||||
* and be at least 1 more than MAX_CLIENTS. It must furthermore be less than
|
||||
* or equal to 256 as client indices (sent over the network) are 8 bits.
|
||||
* It needs 1 more for the dedicated server.
|
||||
*/
|
||||
MAX_CLIENTS = MAX_COMPANIES + 3,
|
||||
MAX_CLIENT_SLOTS = 256,
|
||||
|
||||
/** Maximum number of internet interfaces supported. */
|
||||
MAX_INTERFACES = 9,
|
||||
|
@ -36,10 +42,7 @@ enum ClientID {
|
|||
};
|
||||
|
||||
/** Indices into the client tables */
|
||||
enum ClientIndex {
|
||||
/** Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1. This due to the (dedicated) server taking one slot. */
|
||||
MAX_CLIENT_SLOTS = MAX_CLIENTS + 1,
|
||||
};
|
||||
typedef uint8 ClientIndex;
|
||||
|
||||
/** Simple calculated statistics of a company */
|
||||
struct NetworkCompanyStats {
|
||||
|
|
Loading…
Reference in New Issue