(svn r6816) -Codechange: Some coding style, variable localization, const correctness.
-Codechange: 'quited' is not a word, use has_quit instead for NetworkClientState
This commit is contained in:
		@@ -420,14 +420,12 @@ static void PlayersCheckBankrupt(Player *p)
 | 
			
		||||
				p->bankrupt_timeout = 0x456;
 | 
			
		||||
			} else {
 | 
			
		||||
#ifdef ENABLE_NETWORK
 | 
			
		||||
				/* If we are the server make sure it is clear that this player is not active */
 | 
			
		||||
				if (IsHumanPlayer(owner) && _network_server) {
 | 
			
		||||
					// If we are the server, make sure it is clear that his player is no
 | 
			
		||||
					//  longer with us!
 | 
			
		||||
					NetworkClientInfo *ci;
 | 
			
		||||
					NetworkClientState *cs;
 | 
			
		||||
					const NetworkClientState *cs;
 | 
			
		||||
					/* Find all clients that were in control of this company */
 | 
			
		||||
					FOR_ALL_CLIENTS(cs) {
 | 
			
		||||
						ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
						NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
						if (ci->client_playas == owner) {
 | 
			
		||||
							ci->client_playas = PLAYER_SPECTATOR;
 | 
			
		||||
							// Send the new info to all the clients
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								network.c
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								network.c
									
									
									
									
									
								
							@@ -221,7 +221,7 @@ static void ServerStartError(const char *error)
 | 
			
		||||
	NetworkError(STR_NETWORK_ERR_SERVER_START);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void NetworkClientError(byte res, NetworkClientState* cs)
 | 
			
		||||
static void NetworkClientError(NetworkRecvStatus res, NetworkClientState* cs)
 | 
			
		||||
{
 | 
			
		||||
	// First, send a CLIENT_ERROR to the server, so he knows we are
 | 
			
		||||
	//  disconnection (and why!)
 | 
			
		||||
@@ -229,7 +229,7 @@ static void NetworkClientError(byte res, NetworkClientState* cs)
 | 
			
		||||
 | 
			
		||||
	// We just want to close the connection..
 | 
			
		||||
	if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
 | 
			
		||||
		cs->quited = true;
 | 
			
		||||
		cs->has_quit = true;
 | 
			
		||||
		NetworkCloseClient(cs);
 | 
			
		||||
		_networking = false;
 | 
			
		||||
 | 
			
		||||
@@ -289,11 +289,11 @@ char *GetNetworkErrorMsg(char *buf, NetworkErrorCode err)
 | 
			
		||||
/* Count the number of active clients connected */
 | 
			
		||||
static uint NetworkCountPlayers(void)
 | 
			
		||||
{
 | 
			
		||||
	NetworkClientState *cs;
 | 
			
		||||
	const NetworkClientState *cs;
 | 
			
		||||
	uint count = 0;
 | 
			
		||||
 | 
			
		||||
	FOR_ALL_CLIENTS(cs) {
 | 
			
		||||
		NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
		const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
		if (IsValidPlayer(ci->client_playas)) count++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -543,34 +543,28 @@ void ParseConnectionString(const char **player, const char **port, char *connect
 | 
			
		||||
static NetworkClientState *NetworkAllocClient(SOCKET s)
 | 
			
		||||
{
 | 
			
		||||
	NetworkClientState *cs;
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
	byte client_no;
 | 
			
		||||
 | 
			
		||||
	client_no = 0;
 | 
			
		||||
	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 >= _network_game_info.clients_max)
 | 
			
		||||
			return NULL;
 | 
			
		||||
		if (_network_clients_connected >= MAX_CLIENTS) return NULL;
 | 
			
		||||
		if (_network_game_info.clients_on >= _network_game_info.clients_max) return NULL;
 | 
			
		||||
 | 
			
		||||
		// Register the login
 | 
			
		||||
		client_no = _network_clients_connected++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cs = &_clients[client_no];
 | 
			
		||||
	cs = DEREF_CLIENT(client_no);
 | 
			
		||||
	memset(cs, 0, sizeof(*cs));
 | 
			
		||||
	cs->socket = s;
 | 
			
		||||
	cs->last_frame = 0;
 | 
			
		||||
	cs->quited = false;
 | 
			
		||||
	cs->has_quit = false;
 | 
			
		||||
 | 
			
		||||
	cs->last_frame = _frame_counter;
 | 
			
		||||
	cs->last_frame_server = _frame_counter;
 | 
			
		||||
 | 
			
		||||
	if (_network_server) {
 | 
			
		||||
		ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
		NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
		memset(ci, 0, sizeof(*ci));
 | 
			
		||||
 | 
			
		||||
		cs->index = _network_client_index++;
 | 
			
		||||
@@ -590,13 +584,13 @@ void NetworkCloseClient(NetworkClientState *cs)
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
	// Socket is already dead
 | 
			
		||||
	if (cs->socket == INVALID_SOCKET) {
 | 
			
		||||
		cs->quited = true;
 | 
			
		||||
		cs->has_quit = true;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUG(net, 1) ("[NET] Closed client connection");
 | 
			
		||||
 | 
			
		||||
	if (!cs->quited && _network_server && cs->status > STATUS_INACTIVE) {
 | 
			
		||||
	if (!cs->has_quit && _network_server && cs->status > STATUS_INACTIVE) {
 | 
			
		||||
		// We did not receive a leave message from this client...
 | 
			
		||||
		NetworkErrorCode errorno = NETWORK_ERROR_CONNECTION_LOST;
 | 
			
		||||
		char str[100];
 | 
			
		||||
@@ -625,7 +619,7 @@ void NetworkCloseClient(NetworkClientState *cs)
 | 
			
		||||
 | 
			
		||||
	closesocket(cs->socket);
 | 
			
		||||
	cs->writable = false;
 | 
			
		||||
	cs->quited = true;
 | 
			
		||||
	cs->has_quit = true;
 | 
			
		||||
 | 
			
		||||
	// Free all pending and partially received packets
 | 
			
		||||
	while (cs->packet_queue != NULL) {
 | 
			
		||||
@@ -683,21 +677,17 @@ static bool NetworkConnect(const char *hostname, int port)
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!SetNoDelay(s))
 | 
			
		||||
		DEBUG(net, 1)("[NET] Setting TCP_NODELAY failed");
 | 
			
		||||
	if (!SetNoDelay(s)) DEBUG(net, 1)("[NET] Setting TCP_NODELAY failed");
 | 
			
		||||
 | 
			
		||||
	sin.sin_family = AF_INET;
 | 
			
		||||
	sin.sin_addr.s_addr = NetworkResolveHost(hostname);
 | 
			
		||||
	sin.sin_port = htons(port);
 | 
			
		||||
	_network_last_host_ip = sin.sin_addr.s_addr;
 | 
			
		||||
 | 
			
		||||
	if (connect(s, (struct sockaddr*) &sin, sizeof(sin)) != 0) {
 | 
			
		||||
		// We failed to connect for which reason what so ever
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	/* We failed to connect for which reason what so ever */
 | 
			
		||||
	if (connect(s, (struct sockaddr*) &sin, sizeof(sin)) != 0) return false;
 | 
			
		||||
 | 
			
		||||
	if (!SetNonBlocking(s))
 | 
			
		||||
		DEBUG(net, 0)("[NET] Setting non-blocking failed"); // XXX should this be an error?
 | 
			
		||||
	if (!SetNonBlocking(s)) DEBUG(net, 0)("[NET] Setting non-blocking failed"); // XXX should this be an error?
 | 
			
		||||
 | 
			
		||||
	// in client mode, only the first client field is used. it's pointing to the server.
 | 
			
		||||
	NetworkAllocClient(s);
 | 
			
		||||
@@ -711,7 +701,6 @@ static bool NetworkConnect(const char *hostname, int port)
 | 
			
		||||
static void NetworkAcceptClients(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_in sin;
 | 
			
		||||
	SOCKET s;
 | 
			
		||||
	NetworkClientState *cs;
 | 
			
		||||
	uint i;
 | 
			
		||||
	bool banned;
 | 
			
		||||
@@ -720,10 +709,8 @@ static void NetworkAcceptClients(void)
 | 
			
		||||
	assert(_listensocket != INVALID_SOCKET);
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		socklen_t sin_len;
 | 
			
		||||
 | 
			
		||||
		sin_len = sizeof(sin);
 | 
			
		||||
		s = accept(_listensocket, (struct sockaddr*)&sin, &sin_len);
 | 
			
		||||
		socklen_t sin_len = sizeof(sin);
 | 
			
		||||
		SOCKET s = accept(_listensocket, (struct sockaddr*)&sin, &sin_len);
 | 
			
		||||
		if (s == INVALID_SOCKET) return;
 | 
			
		||||
 | 
			
		||||
		SetNonBlocking(s); // XXX error handling?
 | 
			
		||||
@@ -735,8 +722,7 @@ static void NetworkAcceptClients(void)
 | 
			
		||||
		/* Check if the client is banned */
 | 
			
		||||
		banned = false;
 | 
			
		||||
		for (i = 0; i < lengthof(_network_ban_list); i++) {
 | 
			
		||||
			if (_network_ban_list[i] == NULL)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (_network_ban_list[i] == NULL) continue;
 | 
			
		||||
 | 
			
		||||
			if (sin.sin_addr.s_addr == inet_addr(_network_ban_list[i])) {
 | 
			
		||||
				Packet *p = NetworkSend_Init(PACKET_SERVER_BANNED);
 | 
			
		||||
@@ -756,8 +742,7 @@ static void NetworkAcceptClients(void)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/* If this client is banned, continue with next client */
 | 
			
		||||
		if (banned)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (banned) continue;
 | 
			
		||||
 | 
			
		||||
		cs = NetworkAllocClient(s);
 | 
			
		||||
		if (cs == NULL) {
 | 
			
		||||
@@ -781,12 +766,7 @@ static void NetworkAcceptClients(void)
 | 
			
		||||
		//  the client stays inactive
 | 
			
		||||
		cs->status = STATUS_INACTIVE;
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			// Save the IP of the client
 | 
			
		||||
			NetworkClientInfo *ci;
 | 
			
		||||
			ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
			ci->client_ip = sin.sin_addr.s_addr;
 | 
			
		||||
		}
 | 
			
		||||
		DEREF_CLIENT_INFO(cs)->client_ip = sin.sin_addr.s_addr; // Save the IP of the client
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -795,11 +775,8 @@ static bool NetworkListen(void)
 | 
			
		||||
{
 | 
			
		||||
	SOCKET ls;
 | 
			
		||||
	struct sockaddr_in sin;
 | 
			
		||||
	int port;
 | 
			
		||||
 | 
			
		||||
	port = _network_server_port;
 | 
			
		||||
 | 
			
		||||
	DEBUG(net, 1) ("[NET] Listening on %s:%d", _network_server_bind_ip_host, port);
 | 
			
		||||
	DEBUG(net, 1) ("[NET] Listening on %s:%d", _network_server_bind_ip_host, _network_server_port);
 | 
			
		||||
 | 
			
		||||
	ls = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
	if (ls == INVALID_SOCKET) {
 | 
			
		||||
@@ -816,12 +793,11 @@ static bool NetworkListen(void)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!SetNonBlocking(ls))
 | 
			
		||||
		DEBUG(net, 0)("[NET] Setting non-blocking failed"); // XXX should this be an error?
 | 
			
		||||
	if (!SetNonBlocking(ls)) DEBUG(net, 0)("[NET] Setting non-blocking failed"); // XXX should this be an error?
 | 
			
		||||
 | 
			
		||||
	sin.sin_family = AF_INET;
 | 
			
		||||
	sin.sin_addr.s_addr = _network_server_bind_ip;
 | 
			
		||||
	sin.sin_port = htons(port);
 | 
			
		||||
	sin.sin_port = htons(_network_server_port);
 | 
			
		||||
 | 
			
		||||
	if (bind(ls, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
 | 
			
		||||
		ServerStartError("bind() failed");
 | 
			
		||||
@@ -896,9 +872,7 @@ NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool
 | 
			
		||||
 | 
			
		||||
	NetworkDisconnect();
 | 
			
		||||
 | 
			
		||||
	if (game_info) {
 | 
			
		||||
		return NetworkUDPQueryServer(host, port);
 | 
			
		||||
	}
 | 
			
		||||
	if (game_info) return NetworkUDPQueryServer(host, port);
 | 
			
		||||
 | 
			
		||||
	NetworkInitialize();
 | 
			
		||||
 | 
			
		||||
@@ -907,17 +881,13 @@ NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool
 | 
			
		||||
	// Try to connect
 | 
			
		||||
	_networking = NetworkConnect(host, port);
 | 
			
		||||
 | 
			
		||||
//	ttd_strlcpy(_network_last_host, host, sizeof(_network_last_host));
 | 
			
		||||
//	_network_last_port = port;
 | 
			
		||||
 | 
			
		||||
	// We are connected
 | 
			
		||||
	if (_networking) {
 | 
			
		||||
		SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)();
 | 
			
		||||
		return NULL;
 | 
			
		||||
	} else { // No networking, close everything down again
 | 
			
		||||
		NetworkDisconnect();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// No networking, close everything down again
 | 
			
		||||
	NetworkDisconnect();
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -952,7 +922,7 @@ void NetworkAddServer(const char *b)
 | 
			
		||||
void NetworkRebuildHostList(void)
 | 
			
		||||
{
 | 
			
		||||
	uint i = 0;
 | 
			
		||||
	NetworkGameList *item = _network_game_list;
 | 
			
		||||
	const NetworkGameList *item = _network_game_list;
 | 
			
		||||
	while (item != NULL && i != lengthof(_network_host_list)) {
 | 
			
		||||
		if (item->manually) {
 | 
			
		||||
			free(_network_host_list[i]);
 | 
			
		||||
@@ -968,7 +938,7 @@ void NetworkRebuildHostList(void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Used by clients, to connect to a server
 | 
			
		||||
bool NetworkClientConnectGame(const char* host, unsigned short port)
 | 
			
		||||
bool NetworkClientConnectGame(const char *host, uint16 port)
 | 
			
		||||
{
 | 
			
		||||
	if (!_network_available) return false;
 | 
			
		||||
 | 
			
		||||
@@ -1050,8 +1020,7 @@ bool NetworkServerStart(void)
 | 
			
		||||
	if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
 | 
			
		||||
 | 
			
		||||
	NetworkInitialize();
 | 
			
		||||
	if (!NetworkListen())
 | 
			
		||||
		return false;
 | 
			
		||||
	if (!NetworkListen()) return false;
 | 
			
		||||
 | 
			
		||||
	// Try to start UDP-server
 | 
			
		||||
	_network_udp_server = true;
 | 
			
		||||
@@ -1123,8 +1092,7 @@ void NetworkDisconnect(void)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_network_advertise)
 | 
			
		||||
		NetworkUDPRemoveAdvertise();
 | 
			
		||||
	if (_network_advertise) NetworkUDPRemoveAdvertise();
 | 
			
		||||
 | 
			
		||||
	DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
 | 
			
		||||
 | 
			
		||||
@@ -1158,9 +1126,7 @@ static bool NetworkReceive(void)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// take care of listener port
 | 
			
		||||
	if (_network_server) {
 | 
			
		||||
		FD_SET(_listensocket, &read_fd);
 | 
			
		||||
	}
 | 
			
		||||
	if (_network_server) FD_SET(_listensocket, &read_fd);
 | 
			
		||||
 | 
			
		||||
	tv.tv_sec = tv.tv_usec = 0; // don't block at all.
 | 
			
		||||
#if !defined(__MORPHOS__) && !defined(__AMIGA__)
 | 
			
		||||
@@ -1171,9 +1137,7 @@ static bool NetworkReceive(void)
 | 
			
		||||
	if (n == -1 && !_network_server) NetworkError(STR_NETWORK_ERR_LOSTCONNECTION);
 | 
			
		||||
 | 
			
		||||
	// accept clients..
 | 
			
		||||
	if (_network_server && FD_ISSET(_listensocket, &read_fd)) {
 | 
			
		||||
		NetworkAcceptClients();
 | 
			
		||||
	}
 | 
			
		||||
	if (_network_server && FD_ISSET(_listensocket, &read_fd)) NetworkAcceptClients();
 | 
			
		||||
 | 
			
		||||
	// read stuff from clients
 | 
			
		||||
	FOR_ALL_CLIENTS(cs) {
 | 
			
		||||
@@ -1182,10 +1146,10 @@ static bool NetworkReceive(void)
 | 
			
		||||
			if (_network_server) {
 | 
			
		||||
				NetworkServer_ReadPackets(cs);
 | 
			
		||||
			} else {
 | 
			
		||||
				byte res;
 | 
			
		||||
				NetworkRecvStatus res;
 | 
			
		||||
 | 
			
		||||
				// The client already was quiting!
 | 
			
		||||
				if (cs->quited) return false;
 | 
			
		||||
				if (cs->has_quit) return false;
 | 
			
		||||
 | 
			
		||||
				res = NetworkClient_ReadPackets(cs);
 | 
			
		||||
				if (res != NETWORK_RECV_STATUS_OKAY) {
 | 
			
		||||
@@ -1227,8 +1191,7 @@ static void NetworkHandleLocalQueue(void)
 | 
			
		||||
 | 
			
		||||
		// The queue is always in order, which means
 | 
			
		||||
		// that the first element will be executed first.
 | 
			
		||||
		if (_frame_counter < cp->frame)
 | 
			
		||||
			break;
 | 
			
		||||
		if (_frame_counter < cp->frame) break;
 | 
			
		||||
 | 
			
		||||
		if (_frame_counter > cp->frame) {
 | 
			
		||||
			// If we reach here, it means for whatever reason, we've already executed
 | 
			
		||||
@@ -1347,9 +1310,7 @@ void NetworkGameLoop(void)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// Else, keep on going till _frame_counter_max
 | 
			
		||||
			if (_frame_counter_max > _frame_counter) {
 | 
			
		||||
				NetworkDoClientLoop();
 | 
			
		||||
			}
 | 
			
		||||
			if (_frame_counter_max > _frame_counter) NetworkDoClientLoop();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -229,7 +229,7 @@ void NetworkShutDown(void);
 | 
			
		||||
void NetworkGameLoop(void);
 | 
			
		||||
void NetworkUDPGameLoop(void);
 | 
			
		||||
bool NetworkServerStart(void);
 | 
			
		||||
bool NetworkClientConnectGame(const char* host, unsigned short port);
 | 
			
		||||
bool NetworkClientConnectGame(const char *host, uint16 port);
 | 
			
		||||
void NetworkReboot(void);
 | 
			
		||||
void NetworkDisconnect(void);
 | 
			
		||||
 | 
			
		||||
@@ -252,6 +252,6 @@ static inline void NetworkShutDown(void) {}
 | 
			
		||||
/* These variables must always be registered! */
 | 
			
		||||
VARDEF bool _network_dedicated;  ///< are we a dedicated server?
 | 
			
		||||
VARDEF bool _network_advertise;  ///< is the server advertising to the master server?
 | 
			
		||||
VARDEF PlayerID _network_playas; ///< an id to play as..
 | 
			
		||||
VARDEF PlayerID _network_playas; ///< an id to play as.. (see players.h:Players)
 | 
			
		||||
 | 
			
		||||
#endif /* NETWORK_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -283,19 +283,17 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO)
 | 
			
		||||
 | 
			
		||||
	company_info_version = NetworkRecv_uint8(MY_CLIENT, p);
 | 
			
		||||
 | 
			
		||||
	if (!MY_CLIENT->quited && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
 | 
			
		||||
	if (!MY_CLIENT->has_quit && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
 | 
			
		||||
		byte total;
 | 
			
		||||
		byte current;
 | 
			
		||||
 | 
			
		||||
		total = NetworkRecv_uint8(MY_CLIENT, p);
 | 
			
		||||
 | 
			
		||||
		// There is no data at all..
 | 
			
		||||
		if (total == 0)
 | 
			
		||||
			return NETWORK_RECV_STATUS_CLOSE_QUERY;
 | 
			
		||||
		if (total == 0) return NETWORK_RECV_STATUS_CLOSE_QUERY;
 | 
			
		||||
 | 
			
		||||
		current = NetworkRecv_uint8(MY_CLIENT, p);
 | 
			
		||||
		if (current >= MAX_PLAYERS)
 | 
			
		||||
			return NETWORK_RECV_STATUS_CLOSE_QUERY;
 | 
			
		||||
		if (!IsValidPlayer(current)) return NETWORK_RECV_STATUS_CLOSE_QUERY;
 | 
			
		||||
 | 
			
		||||
		NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].company_name, sizeof(_network_player_info[current].company_name));
 | 
			
		||||
		_network_player_info[current].inaugurated_year = NetworkRecv_uint32(MY_CLIENT, p);
 | 
			
		||||
@@ -333,14 +331,10 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
 | 
			
		||||
	NetworkRecv_string(MY_CLIENT, p, name, sizeof(name));
 | 
			
		||||
	NetworkRecv_string(MY_CLIENT, p, unique_id, sizeof(unique_id));
 | 
			
		||||
 | 
			
		||||
	if (MY_CLIENT->quited)
 | 
			
		||||
		return NETWORK_RECV_STATUS_CONN_LOST;
 | 
			
		||||
	if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
 | 
			
		||||
 | 
			
		||||
	/* Do we receive a change of data? Most likely we changed playas */
 | 
			
		||||
	if (index == _network_own_client_index) {
 | 
			
		||||
		_network_playas = playas;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	if (index == _network_own_client_index) _network_playas = playas;
 | 
			
		||||
 | 
			
		||||
	ci = NetworkFindClientInfoFromIndex(index);
 | 
			
		||||
	if (ci != NULL) {
 | 
			
		||||
@@ -458,8 +452,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
 | 
			
		||||
 | 
			
		||||
	maptype = NetworkRecv_uint8(MY_CLIENT, p);
 | 
			
		||||
 | 
			
		||||
	if (MY_CLIENT->quited)
 | 
			
		||||
		return NETWORK_RECV_STATUS_CONN_LOST;
 | 
			
		||||
	if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
 | 
			
		||||
 | 
			
		||||
	// First packet, init some stuff
 | 
			
		||||
	if (maptype == MAP_PACKET_START) {
 | 
			
		||||
@@ -511,18 +504,19 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
 | 
			
		||||
		// Say we received the map and loaded it correctly!
 | 
			
		||||
		SEND_COMMAND(PACKET_CLIENT_MAP_OK)();
 | 
			
		||||
 | 
			
		||||
		// new company/spectator (invalid player) or company we want to join is not active
 | 
			
		||||
		/* New company/spectator (invalid player) or company we want to join is not active
 | 
			
		||||
		 * Switch local player to spectator and await the server's judgement */
 | 
			
		||||
		if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayer(_network_playas) ||
 | 
			
		||||
				!GetPlayer(_network_playas)->is_active) {
 | 
			
		||||
 | 
			
		||||
			_local_player = PLAYER_SPECTATOR;
 | 
			
		||||
 | 
			
		||||
			if (_network_playas == PLAYER_SPECTATOR) {
 | 
			
		||||
				// The client wants to be a spectator..
 | 
			
		||||
				_local_player = PLAYER_SPECTATOR;
 | 
			
		||||
				DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
 | 
			
		||||
			} else {
 | 
			
		||||
				/* We have arrived and ready to start playing; send a command to make a new player;
 | 
			
		||||
				 * the server will give us a client-id and let us in */
 | 
			
		||||
				_local_player = PLAYER_SPECTATOR;
 | 
			
		||||
				NetworkSend_Command(0, 0, 0, CMD_PLAYER_CTRL, NULL);
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
@@ -609,7 +603,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
 | 
			
		||||
{
 | 
			
		||||
	NetworkAction action = NetworkRecv_uint8(MY_CLIENT, p);
 | 
			
		||||
	char msg[MAX_TEXT_MSG_LEN];
 | 
			
		||||
	NetworkClientInfo *ci = NULL, *ci_to;
 | 
			
		||||
	const NetworkClientInfo *ci = NULL, *ci_to;
 | 
			
		||||
	uint16 index;
 | 
			
		||||
	char name[NETWORK_NAME_LENGTH];
 | 
			
		||||
	bool self_send;
 | 
			
		||||
@@ -814,7 +808,7 @@ NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs)
 | 
			
		||||
 | 
			
		||||
	while (res == NETWORK_RECV_STATUS_OKAY && (p = NetworkRecv_Packet(cs, &res)) != NULL) {
 | 
			
		||||
		byte type = NetworkRecv_uint8(MY_CLIENT, p);
 | 
			
		||||
		if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->quited) {
 | 
			
		||||
		if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->has_quit) {
 | 
			
		||||
			res = _network_client_packet[type](p);
 | 
			
		||||
		} else {
 | 
			
		||||
			res = NETWORK_RECV_STATUS_MALFORMED_PACKET;
 | 
			
		||||
 
 | 
			
		||||
@@ -191,7 +191,7 @@ bool NetworkSend_Packets(NetworkClientState *cs)
 | 
			
		||||
uint8 NetworkRecv_uint8(NetworkClientState *cs, Packet *packet)
 | 
			
		||||
{
 | 
			
		||||
	/* Don't allow reading from a closed socket */
 | 
			
		||||
	if (cs->quited) return 0;
 | 
			
		||||
	if (cs->has_quit) return 0;
 | 
			
		||||
 | 
			
		||||
	/* Check if variable is within packet-size */
 | 
			
		||||
	if (packet->pos + 1 > packet->size) {
 | 
			
		||||
@@ -207,7 +207,7 @@ uint16 NetworkRecv_uint16(NetworkClientState *cs, Packet *packet)
 | 
			
		||||
	uint16 n;
 | 
			
		||||
 | 
			
		||||
	/* Don't allow reading from a closed socket */
 | 
			
		||||
	if (cs->quited) return 0;
 | 
			
		||||
	if (cs->has_quit) return 0;
 | 
			
		||||
 | 
			
		||||
	/* Check if variable is within packet-size */
 | 
			
		||||
	if (packet->pos + 2 > packet->size) {
 | 
			
		||||
@@ -225,7 +225,7 @@ uint32 NetworkRecv_uint32(NetworkClientState *cs, Packet *packet)
 | 
			
		||||
	uint32 n;
 | 
			
		||||
 | 
			
		||||
	/* Don't allow reading from a closed socket */
 | 
			
		||||
	if (cs->quited) return 0;
 | 
			
		||||
	if (cs->has_quit) return 0;
 | 
			
		||||
 | 
			
		||||
	/* Check if variable is within packet-size */
 | 
			
		||||
	if (packet->pos + 4 > packet->size) {
 | 
			
		||||
@@ -245,7 +245,7 @@ uint64 NetworkRecv_uint64(NetworkClientState *cs, Packet *packet)
 | 
			
		||||
	uint64 n;
 | 
			
		||||
 | 
			
		||||
	/* Don't allow reading from a closed socket */
 | 
			
		||||
	if (cs->quited) return 0;
 | 
			
		||||
	if (cs->has_quit) return 0;
 | 
			
		||||
 | 
			
		||||
	/* Check if variable is within packet-size */
 | 
			
		||||
	if (packet->pos + 8 > packet->size) {
 | 
			
		||||
@@ -271,7 +271,7 @@ void NetworkRecv_string(NetworkClientState *cs, Packet *p, char *buffer, size_t
 | 
			
		||||
	char *bufp = buffer;
 | 
			
		||||
 | 
			
		||||
	/* Don't allow reading from a closed socket */
 | 
			
		||||
	if (cs->quited) return;
 | 
			
		||||
	if (cs->has_quit) return;
 | 
			
		||||
 | 
			
		||||
	pos = p->pos;
 | 
			
		||||
	while (--size > 0 && pos < p->size && (*buffer++ = p->buffer[pos++]) != '\0') {}
 | 
			
		||||
 
 | 
			
		||||
@@ -120,7 +120,7 @@ typedef struct NetworkClientState {
 | 
			
		||||
 | 
			
		||||
	ClientStatus status;
 | 
			
		||||
	bool writable; // is client ready to write to?
 | 
			
		||||
	bool quited;
 | 
			
		||||
	bool has_quit;
 | 
			
		||||
 | 
			
		||||
	Packet *packet_queue; // Packets that are awaiting delivery
 | 
			
		||||
	Packet *packet_recv; // Partially received packet
 | 
			
		||||
 
 | 
			
		||||
@@ -100,7 +100,7 @@ enum {
 | 
			
		||||
// called when a new server is found on the network
 | 
			
		||||
void UpdateNetworkGameWindow(bool unselect)
 | 
			
		||||
{
 | 
			
		||||
	Window  *w = FindWindowById(WC_NETWORK_WINDOW, 0);
 | 
			
		||||
	Window *w = FindWindowById(WC_NETWORK_WINDOW, 0);
 | 
			
		||||
 | 
			
		||||
	if (w != NULL) {
 | 
			
		||||
		if (unselect) WP(w, network_ql_d).n.server = NULL;
 | 
			
		||||
@@ -118,7 +118,7 @@ static int CDECL NGameNameSorter(const void *a, const void *b)
 | 
			
		||||
	const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
 | 
			
		||||
	int r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
 | 
			
		||||
 | 
			
		||||
	return (_internal_sort_order & 1) ? -r : r;
 | 
			
		||||
	return _internal_sort_order ? -r : r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Qsort function to sort by the amount of clients online on a
 | 
			
		||||
@@ -134,7 +134,7 @@ static int CDECL NGameClientSorter(const void *a, const void *b)
 | 
			
		||||
	if (r == 0) r = cmp1->info.clients_max - cmp2->info.clients_max;
 | 
			
		||||
	if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
 | 
			
		||||
 | 
			
		||||
	return (_internal_sort_order & 1) ? -r : r;
 | 
			
		||||
	return _internal_sort_order ? -r : r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Qsort function to sort by joinability. If both servers are the
 | 
			
		||||
@@ -149,7 +149,7 @@ static int CDECL NGameAllowedSorter(const void *a, const void *b)
 | 
			
		||||
	if (r == 0) r = cmp1->info.use_password - cmp2->info.use_password;
 | 
			
		||||
	if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
 | 
			
		||||
 | 
			
		||||
	return (_internal_sort_order & 1) ? -r : r;
 | 
			
		||||
	return _internal_sort_order ? -r : r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** (Re)build the network game list as its amount has changed because
 | 
			
		||||
@@ -195,7 +195,7 @@ static void SortNetworkGameList(network_ql_d *nqld)
 | 
			
		||||
	if (!(nqld->l.flags & VL_RESORT)) return;
 | 
			
		||||
	if (nqld->l.list_length == 0) return;
 | 
			
		||||
 | 
			
		||||
	_internal_sort_order = nqld->l.flags & VL_DESC;
 | 
			
		||||
	_internal_sort_order = !!(nqld->l.flags & VL_DESC);
 | 
			
		||||
	qsort(nqld->sort_list, nqld->l.list_length, sizeof(nqld->sort_list[0]), ngame_sorter[nqld->l.sort_type]);
 | 
			
		||||
 | 
			
		||||
	/* After sorting ngl->sort_list contains the sorted items. Put these back
 | 
			
		||||
@@ -1062,7 +1062,7 @@ static const NetworkClientInfo *NetworkFindClientInfo(byte client_no)
 | 
			
		||||
static void ClientList_Kick(byte client_no)
 | 
			
		||||
{
 | 
			
		||||
	if (client_no < MAX_PLAYERS)
 | 
			
		||||
		SEND_COMMAND(PACKET_SERVER_ERROR)(&_clients[client_no], NETWORK_ERROR_KICKED);
 | 
			
		||||
		SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ClientList_Ban(byte client_no)
 | 
			
		||||
@@ -1078,7 +1078,7 @@ static void ClientList_Ban(byte client_no)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (client_no < MAX_PLAYERS)
 | 
			
		||||
		SEND_COMMAND(PACKET_SERVER_ERROR)(&_clients[client_no], NETWORK_ERROR_KICKED);
 | 
			
		||||
		SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ClientList_GiveMoney(byte client_no)
 | 
			
		||||
@@ -1202,7 +1202,7 @@ static Window *PopupClientList(Window *w, int client_no, int x, int y)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A server can kick clients (but not hisself)
 | 
			
		||||
	// A server can kick clients (but not himself)
 | 
			
		||||
	if (_network_server && _network_own_client_index != ci->client_index) {
 | 
			
		||||
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK);
 | 
			
		||||
		_clientlist_proc[i++] = &ClientList_Kick;
 | 
			
		||||
@@ -1282,8 +1282,7 @@ static void ClientListPopupWndProc(Window *w, WindowEvent *e)
 | 
			
		||||
		// Our mouse hoovers over an action? Select it!
 | 
			
		||||
		int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
 | 
			
		||||
 | 
			
		||||
		if (index == -1 || index == WP(w,menu_d).sel_index)
 | 
			
		||||
			return;
 | 
			
		||||
		if (index == -1 || index == WP(w,menu_d).sel_index) return;
 | 
			
		||||
 | 
			
		||||
		WP(w,menu_d).sel_index = index;
 | 
			
		||||
		SetWindowDirty(w);
 | 
			
		||||
@@ -1537,9 +1536,7 @@ static const char *ChatTabCompletionNextItem(uint *item)
 | 
			
		||||
 */
 | 
			
		||||
static char *ChatTabCompletionFindText(char *buf)
 | 
			
		||||
{
 | 
			
		||||
	char *p;
 | 
			
		||||
 | 
			
		||||
	p = strrchr(buf, ' ');
 | 
			
		||||
	char *p = strrchr(buf, ' ');
 | 
			
		||||
	if (p == NULL) return buf;
 | 
			
		||||
 | 
			
		||||
	*p = '\0';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										131
									
								
								network_server.c
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								network_server.c
									
									
									
									
									
								
							@@ -43,10 +43,8 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkClientState *cs,
 | 
			
		||||
	//    String: The unique id of the client
 | 
			
		||||
	//
 | 
			
		||||
 | 
			
		||||
	Packet *p;
 | 
			
		||||
 | 
			
		||||
	if (ci->client_index != NETWORK_EMPTY_INDEX) {
 | 
			
		||||
		p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
 | 
			
		||||
		Packet *p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
 | 
			
		||||
		NetworkSend_uint16(p, ci->client_index);
 | 
			
		||||
		NetworkSend_uint8 (p, ci->client_playas);
 | 
			
		||||
		NetworkSend_string(p, ci->client_name);
 | 
			
		||||
@@ -72,7 +70,7 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)
 | 
			
		||||
	byte active = ActivePlayerCount();
 | 
			
		||||
 | 
			
		||||
	if (active == 0) {
 | 
			
		||||
		Packet *p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
 | 
			
		||||
		p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
 | 
			
		||||
 | 
			
		||||
		NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
 | 
			
		||||
		NetworkSend_uint8 (p, active);
 | 
			
		||||
@@ -140,10 +138,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, Netwo
 | 
			
		||||
	//    uint8:  ErrorID (see network_data.h, NetworkErrorCode)
 | 
			
		||||
	//
 | 
			
		||||
 | 
			
		||||
	NetworkClientState *new_cs;
 | 
			
		||||
	char str[100];
 | 
			
		||||
	char client_name[NETWORK_CLIENT_NAME_LENGTH];
 | 
			
		||||
 | 
			
		||||
	Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
 | 
			
		||||
 | 
			
		||||
	NetworkSend_uint8(p, error);
 | 
			
		||||
@@ -153,6 +148,9 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, Netwo
 | 
			
		||||
 | 
			
		||||
	// Only send when the current client was in game
 | 
			
		||||
	if (cs->status > STATUS_AUTH) {
 | 
			
		||||
		NetworkClientState *new_cs;
 | 
			
		||||
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 | 
			
		||||
 | 
			
		||||
		NetworkGetClientName(client_name, sizeof(client_name), cs);
 | 
			
		||||
 | 
			
		||||
		DEBUG(net, 2) ("[NET] '%s' made an error and has been disconnected. Reason: %s", client_name, str);
 | 
			
		||||
@@ -173,7 +171,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, Netwo
 | 
			
		||||
		DEBUG(net, 2) ("[NET] Client %d made an error and has been disconnected. Reason: %s", cs->index, str);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cs->quited = true;
 | 
			
		||||
	cs->has_quit = true;
 | 
			
		||||
 | 
			
		||||
	// Make sure the data get's there before we close the connection
 | 
			
		||||
	NetworkSend_Packets(cs);
 | 
			
		||||
@@ -269,7 +267,6 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
 | 
			
		||||
	//      last 2 are repeated MAX_PLAYERS time
 | 
			
		||||
	//
 | 
			
		||||
 | 
			
		||||
	char filename[256];
 | 
			
		||||
	static FILE *file_pointer;
 | 
			
		||||
	static uint sent_packets; // How many packets we did send succecfully last time
 | 
			
		||||
 | 
			
		||||
@@ -278,7 +275,9 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
 | 
			
		||||
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cs->status == STATUS_AUTH) {
 | 
			
		||||
		char filename[256];
 | 
			
		||||
		Packet *p;
 | 
			
		||||
 | 
			
		||||
		// Make a dump of the current game
 | 
			
		||||
@@ -312,9 +311,9 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
 | 
			
		||||
			Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
 | 
			
		||||
			NetworkSend_uint8(p, MAP_PACKET_NORMAL);
 | 
			
		||||
			res = (int)fread(p->buffer + p->size, 1, SEND_MTU - p->size, file_pointer);
 | 
			
		||||
			if (ferror(file_pointer)) {
 | 
			
		||||
				error("Error reading temporary network savegame!");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (ferror(file_pointer)) error("Error reading temporary network savegame!");
 | 
			
		||||
 | 
			
		||||
			p->size += res;
 | 
			
		||||
			NetworkSend_Packet(p, cs);
 | 
			
		||||
			if (feof(file_pointer)) {
 | 
			
		||||
@@ -592,7 +591,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
 | 
			
		||||
	client_lang = NetworkRecv_uint8(cs, p);
 | 
			
		||||
	NetworkRecv_string(cs, p, unique_id, sizeof(unique_id));
 | 
			
		||||
 | 
			
		||||
	if (cs->quited) return;
 | 
			
		||||
	if (cs->has_quit) return;
 | 
			
		||||
 | 
			
		||||
	// join another company does not affect these values
 | 
			
		||||
	switch (playas) {
 | 
			
		||||
@@ -652,7 +651,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
 | 
			
		||||
{
 | 
			
		||||
	NetworkPasswordType type;
 | 
			
		||||
	char password[NETWORK_PASSWORD_LENGTH];
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
	const NetworkClientInfo *ci;
 | 
			
		||||
 | 
			
		||||
	type = NetworkRecv_uint8(cs, p);
 | 
			
		||||
	NetworkRecv_string(cs, p, password, sizeof(password));
 | 
			
		||||
@@ -695,11 +694,11 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
 | 
			
		||||
 | 
			
		||||
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
 | 
			
		||||
{
 | 
			
		||||
	NetworkClientState *new_cs;
 | 
			
		||||
	const NetworkClientState *new_cs;
 | 
			
		||||
 | 
			
		||||
	// The client was never joined.. so this is impossible, right?
 | 
			
		||||
	//  Ignore the packet, give the client a warning, and close his connection
 | 
			
		||||
	if (cs->status < STATUS_AUTH || cs->quited) {
 | 
			
		||||
	if (cs->status < STATUS_AUTH || cs->has_quit) {
 | 
			
		||||
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
@@ -721,7 +720,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
 | 
			
		||||
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
 | 
			
		||||
{
 | 
			
		||||
	// Client has the map, now start syncing
 | 
			
		||||
	if (cs->status == STATUS_DONE_MAP && !cs->quited) {
 | 
			
		||||
	if (cs->status == STATUS_DONE_MAP && !cs->has_quit) {
 | 
			
		||||
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 | 
			
		||||
		NetworkClientState *new_cs;
 | 
			
		||||
 | 
			
		||||
@@ -778,6 +777,7 @@ static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *
 | 
			
		||||
		IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -795,7 +795,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
 | 
			
		||||
 | 
			
		||||
	// The client was never joined.. so this is impossible, right?
 | 
			
		||||
	//  Ignore the packet, give the client a warning, and close his connection
 | 
			
		||||
	if (cs->status < STATUS_DONE_MAP || cs->quited) {
 | 
			
		||||
	if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
 | 
			
		||||
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
@@ -809,7 +809,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
 | 
			
		||||
 | 
			
		||||
	callback = NetworkRecv_uint8(cs, p);
 | 
			
		||||
 | 
			
		||||
	if (cs->quited) return;
 | 
			
		||||
	if (cs->has_quit) return;
 | 
			
		||||
 | 
			
		||||
	ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
 | 
			
		||||
@@ -847,9 +847,11 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// XXX - UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
 | 
			
		||||
		/* XXX - Execute the command as a valid player. Normally this would be done by a
 | 
			
		||||
		 * spectator, but that is not allowed any commands. So do an impersonation. The drawback
 | 
			
		||||
		 * of this is that the first company's last_built_tile is also updated... */
 | 
			
		||||
		cp->player = 0;
 | 
			
		||||
		cp->p2 = cs - _clients;
 | 
			
		||||
		cp->p2 = cs - _clients; // XXX - UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The frame can be executed in the same frame as the next frame-packet
 | 
			
		||||
@@ -886,12 +888,12 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
 | 
			
		||||
	//  to us. Display the error and report it to the other clients
 | 
			
		||||
	NetworkClientState *new_cs;
 | 
			
		||||
	char str[100];
 | 
			
		||||
	NetworkErrorCode errorno = NetworkRecv_uint8(cs, p);
 | 
			
		||||
	char client_name[NETWORK_CLIENT_NAME_LENGTH];
 | 
			
		||||
	NetworkErrorCode errorno = NetworkRecv_uint8(cs, p);
 | 
			
		||||
 | 
			
		||||
	// The client was never joined.. thank the client for the packet, but ignore it
 | 
			
		||||
	if (cs->status < STATUS_DONE_MAP || cs->quited) {
 | 
			
		||||
		cs->quited = true;
 | 
			
		||||
	if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
 | 
			
		||||
		cs->has_quit = true;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -909,7 +911,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cs->quited = true;
 | 
			
		||||
	cs->has_quit = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
 | 
			
		||||
@@ -921,8 +923,8 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
 | 
			
		||||
	char client_name[NETWORK_CLIENT_NAME_LENGTH];
 | 
			
		||||
 | 
			
		||||
	// The client was never joined.. thank the client for the packet, but ignore it
 | 
			
		||||
	if (cs->status < STATUS_DONE_MAP || cs->quited) {
 | 
			
		||||
		cs->quited = true;
 | 
			
		||||
	if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
 | 
			
		||||
		cs->has_quit = true;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -938,7 +940,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cs->quited = true;
 | 
			
		||||
	cs->has_quit = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
 | 
			
		||||
@@ -948,8 +950,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
 | 
			
		||||
	/* The client is trying to catch up with the server */
 | 
			
		||||
	if (cs->status == STATUS_PRE_ACTIVE) {
 | 
			
		||||
		/* The client is not yet catched up? */
 | 
			
		||||
		if (frame + DAY_TICKS < _frame_counter)
 | 
			
		||||
			return;
 | 
			
		||||
		if (frame + DAY_TICKS < _frame_counter) return;
 | 
			
		||||
 | 
			
		||||
		/* Now he is! Unpause the game */
 | 
			
		||||
		cs->status = STATUS_ACTIVE;
 | 
			
		||||
@@ -976,7 +977,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
 | 
			
		||||
void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
 | 
			
		||||
{
 | 
			
		||||
	NetworkClientState *cs;
 | 
			
		||||
	NetworkClientInfo *ci, *ci_own, *ci_to;
 | 
			
		||||
	const NetworkClientInfo *ci, *ci_own, *ci_to;
 | 
			
		||||
 | 
			
		||||
	switch (desttype) {
 | 
			
		||||
	case DESTTYPE_CLIENT:
 | 
			
		||||
@@ -1022,9 +1023,7 @@ void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest,
 | 
			
		||||
			ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
			if (ci->client_playas == dest) {
 | 
			
		||||
				SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
 | 
			
		||||
				if (cs->index == from_index) {
 | 
			
		||||
					show_local = false;
 | 
			
		||||
				}
 | 
			
		||||
				if (cs->index == from_index) show_local = false;
 | 
			
		||||
				ci_to = ci; // Remember a client that is in the company for company-name
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -1033,8 +1032,7 @@ void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest,
 | 
			
		||||
		ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 | 
			
		||||
		if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
 | 
			
		||||
			NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
 | 
			
		||||
			if (from_index == NETWORK_SERVER_INDEX)
 | 
			
		||||
				show_local = false;
 | 
			
		||||
			if (from_index == NETWORK_SERVER_INDEX) show_local = false;
 | 
			
		||||
			ci_to = ci_own;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1086,7 +1084,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
 | 
			
		||||
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
 | 
			
		||||
{
 | 
			
		||||
	char password[NETWORK_PASSWORD_LENGTH];
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
	const NetworkClientInfo *ci;
 | 
			
		||||
 | 
			
		||||
	NetworkRecv_string(cs, p, password, sizeof(password));
 | 
			
		||||
	ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
@@ -1104,8 +1102,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
 | 
			
		||||
	NetworkRecv_string(cs, p, client_name, sizeof(client_name));
 | 
			
		||||
	ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
 | 
			
		||||
	if (cs->quited)
 | 
			
		||||
		return;
 | 
			
		||||
	if (cs->has_quit) return;
 | 
			
		||||
 | 
			
		||||
	if (ci != NULL) {
 | 
			
		||||
		// Display change
 | 
			
		||||
@@ -1190,12 +1187,12 @@ assert_compile(lengthof(_network_server_packet) == PACKET_END);
 | 
			
		||||
void NetworkPopulateCompanyInfo(void)
 | 
			
		||||
{
 | 
			
		||||
	char password[NETWORK_PASSWORD_LENGTH];
 | 
			
		||||
	Player *p;
 | 
			
		||||
	Vehicle *v;
 | 
			
		||||
	Station *s;
 | 
			
		||||
	NetworkClientState *cs;
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
	int i;
 | 
			
		||||
	const Player *p;
 | 
			
		||||
	const Vehicle *v;
 | 
			
		||||
	const Station *s;
 | 
			
		||||
	const NetworkClientState *cs;
 | 
			
		||||
	const NetworkClientInfo *ci;
 | 
			
		||||
	uint i;
 | 
			
		||||
	uint16 months_empty;
 | 
			
		||||
 | 
			
		||||
	FOR_ALL_PLAYERS(p) {
 | 
			
		||||
@@ -1219,11 +1216,11 @@ void NetworkPopulateCompanyInfo(void)
 | 
			
		||||
		// Check the income
 | 
			
		||||
		if (_cur_year - 1 == p->inaugurated_year) {
 | 
			
		||||
			// The player is here just 1 year, so display [2], else display[1]
 | 
			
		||||
			for (i = 0; i < 13; i++) {
 | 
			
		||||
			for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) {
 | 
			
		||||
				_network_player_info[p->index].income -= p->yearly_expenses[2][i];
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			for (i = 0; i < 13; i++) {
 | 
			
		||||
			for (i = 0; i < lengthof(p->yearly_expenses[1]); i++) {
 | 
			
		||||
				_network_player_info[p->index].income -= p->yearly_expenses[1][i];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -1238,11 +1235,10 @@ void NetworkPopulateCompanyInfo(void)
 | 
			
		||||
	// Go through all vehicles and count the type of vehicles
 | 
			
		||||
	FOR_ALL_VEHICLES(v) {
 | 
			
		||||
		if (!IsValidPlayer(v->owner)) continue;
 | 
			
		||||
 | 
			
		||||
		switch (v->type) {
 | 
			
		||||
			case VEH_Train:
 | 
			
		||||
				if (IsFrontEngine(v)) {
 | 
			
		||||
					_network_player_info[v->owner].num_vehicle[0]++;
 | 
			
		||||
				}
 | 
			
		||||
				if (IsFrontEngine(v)) _network_player_info[v->owner].num_vehicle[0]++;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case VEH_Road:
 | 
			
		||||
@@ -1254,9 +1250,7 @@ void NetworkPopulateCompanyInfo(void)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case VEH_Aircraft:
 | 
			
		||||
				if (v->subtype <= 2) {
 | 
			
		||||
					_network_player_info[v->owner].num_vehicle[3]++;
 | 
			
		||||
				}
 | 
			
		||||
				if (v->subtype <= 2) _network_player_info[v->owner].num_vehicle[3]++;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case VEH_Ship:
 | 
			
		||||
@@ -1272,7 +1266,7 @@ void NetworkPopulateCompanyInfo(void)
 | 
			
		||||
	// Go through all stations and count the types of stations
 | 
			
		||||
	FOR_ALL_STATIONS(s) {
 | 
			
		||||
		if (IsValidPlayer(s->owner)) {
 | 
			
		||||
			NetworkPlayerInfo* npi = &_network_player_info[s->owner];
 | 
			
		||||
			NetworkPlayerInfo *npi = &_network_player_info[s->owner];
 | 
			
		||||
 | 
			
		||||
			if (s->facilities & FACIL_TRAIN)      npi->num_station[0]++;
 | 
			
		||||
			if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[1]++;
 | 
			
		||||
@@ -1306,9 +1300,7 @@ void NetworkPopulateCompanyInfo(void)
 | 
			
		||||
void NetworkUpdateClientInfo(uint16 client_index)
 | 
			
		||||
{
 | 
			
		||||
	NetworkClientState *cs;
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
 | 
			
		||||
	ci = NetworkFindClientInfoFromIndex(client_index);
 | 
			
		||||
	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
 | 
			
		||||
 | 
			
		||||
	if (ci == NULL) return;
 | 
			
		||||
 | 
			
		||||
@@ -1334,9 +1326,9 @@ static void NetworkCheckRestartMap(void)
 | 
			
		||||
           (and item 1. happens a year later) */
 | 
			
		||||
static void NetworkAutoCleanCompanies(void)
 | 
			
		||||
{
 | 
			
		||||
	NetworkClientState *cs;
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
	Player *p;
 | 
			
		||||
	const NetworkClientState *cs;
 | 
			
		||||
	const NetworkClientInfo *ci;
 | 
			
		||||
	const Player *p;
 | 
			
		||||
	bool clients_in_company[MAX_PLAYERS];
 | 
			
		||||
 | 
			
		||||
	if (!_network_autoclean_companies) return;
 | 
			
		||||
@@ -1348,6 +1340,7 @@ static void NetworkAutoCleanCompanies(void)
 | 
			
		||||
		ci = DEREF_CLIENT_INFO(cs);
 | 
			
		||||
		if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_network_dedicated) {
 | 
			
		||||
		ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 | 
			
		||||
		if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
 | 
			
		||||
@@ -1366,7 +1359,7 @@ static void NetworkAutoCleanCompanies(void)
 | 
			
		||||
			if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
 | 
			
		||||
				/* Shut the company down */
 | 
			
		||||
				DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
 | 
			
		||||
				IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index+1);
 | 
			
		||||
				IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1);
 | 
			
		||||
			}
 | 
			
		||||
			/* Is the compnay empty for autoclean_protected-months, and there is a protection? */
 | 
			
		||||
			if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
 | 
			
		||||
@@ -1387,7 +1380,6 @@ static void NetworkAutoCleanCompanies(void)
 | 
			
		||||
bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
 | 
			
		||||
{
 | 
			
		||||
	NetworkClientState *new_cs;
 | 
			
		||||
	NetworkClientInfo *ci;
 | 
			
		||||
	bool found_name = false;
 | 
			
		||||
	byte number = 0;
 | 
			
		||||
	char original_name[NETWORK_CLIENT_NAME_LENGTH];
 | 
			
		||||
@@ -1396,6 +1388,8 @@ bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
 | 
			
		||||
	ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
 | 
			
		||||
 | 
			
		||||
	while (!found_name) {
 | 
			
		||||
		const NetworkClientInfo *ci;
 | 
			
		||||
 | 
			
		||||
		found_name = true;
 | 
			
		||||
		FOR_ALL_CLIENTS(new_cs) {
 | 
			
		||||
			ci = DEREF_CLIENT_INFO(new_cs);
 | 
			
		||||
@@ -1408,10 +1402,7 @@ bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
 | 
			
		||||
		// Check if it is the same as the server-name
 | 
			
		||||
		ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 | 
			
		||||
		if (ci != NULL) {
 | 
			
		||||
			if (strcmp(ci->client_name, new_name) == 0) {
 | 
			
		||||
				// Name already in use
 | 
			
		||||
				found_name = false;
 | 
			
		||||
			}
 | 
			
		||||
			if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!found_name) {
 | 
			
		||||
@@ -1433,7 +1424,7 @@ bool NetworkServer_ReadPackets(NetworkClientState *cs)
 | 
			
		||||
	NetworkRecvStatus res;
 | 
			
		||||
	while ((p = NetworkRecv_Packet(cs, &res)) != NULL) {
 | 
			
		||||
		byte type = NetworkRecv_uint8(cs, p);
 | 
			
		||||
		if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->quited) {
 | 
			
		||||
		if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->has_quit) {
 | 
			
		||||
			_network_server_packet[type](cs, p);
 | 
			
		||||
		} else {
 | 
			
		||||
			DEBUG(net, 0)("[NET][Server] Received invalid packet type %d", type);
 | 
			
		||||
@@ -1509,13 +1500,11 @@ void NetworkServer_Tick(bool send_frame)
 | 
			
		||||
			NetworkHandleCommandQueue(cs);
 | 
			
		||||
 | 
			
		||||
			// Send an updated _frame_counter_max to the client
 | 
			
		||||
			if (send_frame)
 | 
			
		||||
				SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
 | 
			
		||||
			if (send_frame) SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
 | 
			
		||||
 | 
			
		||||
#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
 | 
			
		||||
			// Send a sync-check packet
 | 
			
		||||
			if (send_sync)
 | 
			
		||||
				SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
 | 
			
		||||
			if (send_sync) SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -105,7 +105,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE)
 | 
			
		||||
 | 
			
		||||
	game_info_version = NetworkRecv_uint8(&_udp_cs, p);
 | 
			
		||||
 | 
			
		||||
	if (_udp_cs.quited) return;
 | 
			
		||||
	if (_udp_cs.has_quit) return;
 | 
			
		||||
 | 
			
		||||
	DEBUG(net, 6)("[NET][UDP] Server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
 | 
			
		||||
 | 
			
		||||
@@ -247,6 +247,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO)
 | 
			
		||||
			NetworkSend_uint32(packet, ci->join_date);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Also check for the server itself */
 | 
			
		||||
	ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 | 
			
		||||
	if (!IsValidPlayer(ci->client_playas)) {
 | 
			
		||||
@@ -280,8 +281,7 @@ DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST)
 | 
			
		||||
 | 
			
		||||
	ver = NetworkRecv_uint8(&_udp_cs, p);
 | 
			
		||||
 | 
			
		||||
	if (_udp_cs.quited)
 | 
			
		||||
		return;
 | 
			
		||||
	if (_udp_cs.has_quit) return;
 | 
			
		||||
 | 
			
		||||
	if (ver == 1) {
 | 
			
		||||
		for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) {
 | 
			
		||||
@@ -330,14 +330,14 @@ static void NetworkHandleUDPPacket(Packet* p, struct sockaddr_in* client_addr)
 | 
			
		||||
 | 
			
		||||
	/* Fake a client, so we can see when there is an illegal packet */
 | 
			
		||||
	_udp_cs.socket = INVALID_SOCKET;
 | 
			
		||||
	_udp_cs.quited = false;
 | 
			
		||||
	_udp_cs.has_quit = false;
 | 
			
		||||
 | 
			
		||||
	type = NetworkRecv_uint8(&_udp_cs, p);
 | 
			
		||||
 | 
			
		||||
	if (type < PACKET_UDP_END && _network_udp_packet[type] != NULL && !_udp_cs.quited) {
 | 
			
		||||
	if (type < PACKET_UDP_END && _network_udp_packet[type] != NULL && !_udp_cs.has_quit) {
 | 
			
		||||
		_network_udp_packet[type](p, client_addr);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!_udp_cs.quited) {
 | 
			
		||||
		if (!_udp_cs.has_quit) {
 | 
			
		||||
			DEBUG(net, 0)("[NET][UDP] Received invalid packet type %d", type);
 | 
			
		||||
		} else {
 | 
			
		||||
			DEBUG(net, 0)("[NET][UDP] Received illegal packet");
 | 
			
		||||
 
 | 
			
		||||
@@ -484,8 +484,8 @@ int ttd_main(int argc, char *argv[])
 | 
			
		||||
			if (player != NULL) {
 | 
			
		||||
				_network_playas = atoi(player);
 | 
			
		||||
 | 
			
		||||
		    if (_network_playas != PLAYER_SPECTATOR) {
 | 
			
		||||
				  _network_playas--;
 | 
			
		||||
				if (_network_playas != PLAYER_SPECTATOR) {
 | 
			
		||||
					_network_playas--;
 | 
			
		||||
					if (!IsValidPlayer(_network_playas)) return false;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user