1
0
Fork 0

(svn r22461) [1.1] -Backport from trunk:

- Fix: [NewGRF] Zero register 0x100 as specified before resolving custom station foundations (r22452)
- Fix: Do not 'log' the NewGRFs in the screenshot when in the menu [FS#4610] (r22450)
- Fix: Keep better accounting of the order in which clients joined; client can't be starved from joining and they get shown the amount of clients waiting in front of them. (r22372, r22370, r22369, r22368, r22367, r22366, r22365, r22364, r22363, r22362, r22361)
- Fix: Delete the client list popup when the client got removed (instead of previously selecting some other client) (r22360, r22359, r22358)
release/1.1
rubidium 2011-05-15 09:38:54 +00:00
parent 829a2c201d
commit 59a11e6626
20 changed files with 187 additions and 177 deletions

View File

@ -556,7 +556,7 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY)
GeneratePresidentName(c); GeneratePresidentName(c);
SetWindowDirty(WC_GRAPH_LEGEND, 0); SetWindowDirty(WC_GRAPH_LEGEND, 0);
SetWindowDirty(WC_TOOLBAR_MENU, 0); SetWindowClassesDirty(WC_CLIENT_LIST_POPUP);
SetWindowDirty(WC_CLIENT_LIST, 0); SetWindowDirty(WC_CLIENT_LIST, 0);
BuildOwnerLegend(); BuildOwnerLegend();
InvalidateWindowData(WC_SMALLMAP, 0, 1); InvalidateWindowData(WC_SMALLMAP, 0, 1);
@ -813,7 +813,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
#ifdef ENABLE_NETWORK #ifdef ENABLE_NETWORK
/* Has the network client a correct ClientIndex? */ /* Has the network client a correct ClientIndex? */
if (!(flags & DC_EXEC)) return CommandCost(); if (!(flags & DC_EXEC)) return CommandCost();
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (ci == NULL) return CommandCost(); if (ci == NULL) return CommandCost();
/* Delete multiplayer progress bar */ /* Delete multiplayer progress bar */

View File

@ -490,7 +490,7 @@ DEF_CONSOLE_CMD(ConClearBuffer)
static bool ConKickOrBan(const char *argv, bool ban) static bool ConKickOrBan(const char *argv, bool ban)
{ {
const char *ip = argv; uint n;
if (strchr(argv, '.') == NULL && strchr(argv, ':') == NULL) { // banning with ID if (strchr(argv, '.') == NULL && strchr(argv, ':') == NULL) { // banning with ID
ClientID client_id = (ClientID)atoi(argv); ClientID client_id = (ClientID)atoi(argv);
@ -504,7 +504,7 @@ static bool ConKickOrBan(const char *argv, bool ban)
return true; return true;
} }
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (ci == NULL) { if (ci == NULL) {
IConsoleError("Invalid client"); IConsoleError("Invalid client");
return true; return true;
@ -517,10 +517,11 @@ static bool ConKickOrBan(const char *argv, bool ban)
} }
/* When banning, kick+ban all clients with that IP */ /* When banning, kick+ban all clients with that IP */
ip = GetClientIP(ci); n = NetworkServerKickOrBanIP(client_id, ban);
} else {
n = NetworkServerKickOrBanIP(argv, ban);
} }
uint n = NetworkServerKickOrBanIP(ip, ban);
if (n == 0) { if (n == 0) {
IConsolePrint(CC_DEFAULT, ban ? "Client not online, address added to banlist" : "Client not found"); IConsolePrint(CC_DEFAULT, ban ? "Client not online, address added to banlist" : "Client not found");
} else { } else {
@ -699,7 +700,7 @@ DEF_CONSOLE_CMD(ConClientNickChange)
return true; return true;
} }
if (NetworkFindClientInfoFromClientID(client_id) == NULL) { if (NetworkClientInfo::GetByClientID(client_id) == NULL) {
IConsoleError("Invalid client"); IConsoleError("Invalid client");
return true; return true;
} }
@ -727,7 +728,7 @@ DEF_CONSOLE_CMD(ConJoinCompany)
return true; return true;
} }
if (NetworkFindClientInfoFromClientID(_network_own_client_id)->client_playas == company_id) { if (NetworkClientInfo::GetByClientID(_network_own_client_id)->client_playas == company_id) {
IConsoleError("You are already there!"); IConsoleError("You are already there!");
return true; return true;
} }
@ -766,7 +767,7 @@ DEF_CONSOLE_CMD(ConMoveClient)
return true; return true;
} }
const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID((ClientID)atoi(argv[1])); const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID((ClientID)atoi(argv[1]));
CompanyID company_id = (CompanyID)(atoi(argv[2]) <= MAX_COMPANIES ? atoi(argv[2]) - 1 : atoi(argv[2])); CompanyID company_id = (CompanyID)(atoi(argv[2]) <= MAX_COMPANIES ? atoi(argv[2]) - 1 : atoi(argv[2]));
/* check the client exists */ /* check the client exists */
@ -828,7 +829,7 @@ DEF_CONSOLE_CMD(ConResetCompany)
IConsoleError("Cannot remove company: a client is connected to that company."); IConsoleError("Cannot remove company: a client is connected to that company.");
return false; return false;
} }
const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER); const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
if (ci->client_playas == index) { if (ci->client_playas == index) {
IConsoleError("Cannot remove company: the server is connected to that company."); IConsoleError("Cannot remove company: the server is connected to that company.");
return true; return true;

View File

@ -377,7 +377,7 @@ struct MainWindow : Window
#ifdef ENABLE_NETWORK #ifdef ENABLE_NETWORK
case GHK_CHAT: // smart chat; send to team if any, otherwise to all case GHK_CHAT: // smart chat; send to team if any, otherwise to all
if (_networking) { if (_networking) {
const NetworkClientInfo *cio = NetworkFindClientInfoFromClientID(_network_own_client_id); const NetworkClientInfo *cio = NetworkClientInfo::GetByClientID(_network_own_client_id);
if (cio == NULL) break; if (cio == NULL) break;
ShowNetworkChatQueryWindow(NetworkClientPreferTeamChat(cio) ? DESTTYPE_TEAM : DESTTYPE_BROADCAST, cio->client_playas); ShowNetworkChatQueryWindow(NetworkClientPreferTeamChat(cio) ? DESTTYPE_TEAM : DESTTYPE_BROADCAST, cio->client_playas);
@ -390,7 +390,7 @@ struct MainWindow : Window
case GHK_CHAT_COMPANY: // send text to all team mates case GHK_CHAT_COMPANY: // send text to all team mates
if (_networking) { if (_networking) {
const NetworkClientInfo *cio = NetworkFindClientInfoFromClientID(_network_own_client_id); const NetworkClientInfo *cio = NetworkClientInfo::GetByClientID(_network_own_client_id);
if (cio == NULL) break; if (cio == NULL) break;
ShowNetworkChatQueryWindow(DESTTYPE_TEAM, cio->client_playas); ShowNetworkChatQueryWindow(DESTTYPE_TEAM, cio->client_playas);

View File

@ -266,7 +266,7 @@ protected:
/** /**
* Notification that another client is currently receiving the map: * Notification that another client is currently receiving the map:
* uint8 Number of clients awaiting the map. * uint8 Number of clients waiting in front of you.
*/ */
DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT); DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT);

View File

@ -108,7 +108,7 @@ NetworkClientInfo::~NetworkClientInfo()
* @param client_id the ClientID to search for * @param client_id the ClientID to search for
* @return return a pointer to the corresponding NetworkClientInfo struct or NULL when not found * @return return a pointer to the corresponding NetworkClientInfo struct or NULL when not found
*/ */
NetworkClientInfo *NetworkFindClientInfoFromClientID(ClientID client_id) /* static */ NetworkClientInfo *NetworkClientInfo::GetByClientID(ClientID client_id)
{ {
NetworkClientInfo *ci; NetworkClientInfo *ci;
@ -124,7 +124,7 @@ NetworkClientInfo *NetworkFindClientInfoFromClientID(ClientID client_id)
* @param client_id the ClientID to search for * @param client_id the ClientID to search for
* @return return a pointer to the corresponding NetworkClientSocket struct or NULL when not found * @return return a pointer to the corresponding NetworkClientSocket struct or NULL when not found
*/ */
NetworkClientSocket *NetworkFindClientStateFromClientID(ClientID client_id) /* static */ NetworkClientSocket *NetworkClientSocket::GetByClientID(ClientID client_id)
{ {
NetworkClientSocket *cs; NetworkClientSocket *cs;
@ -484,7 +484,7 @@ void ParseConnectionString(const char **company, const char **port, char *connec
SetWindowDirty(WC_CLIENT_LIST, 0); SetWindowDirty(WC_CLIENT_LIST, 0);
ServerNetworkGameSocketHandler *cs = new ServerNetworkGameSocketHandler(s); ServerNetworkGameSocketHandler *cs = new ServerNetworkGameSocketHandler(s);
cs->GetInfo()->client_address = address; // Save the IP of the client cs->client_address = address; // Save the IP of the client
} }
/** /**
@ -686,11 +686,6 @@ static void NetworkInitGameInfo()
assert(NetworkClientInfo::CanAllocateItem()); assert(NetworkClientInfo::CanAllocateItem());
NetworkClientInfo *ci = new NetworkClientInfo(CLIENT_ID_SERVER); NetworkClientInfo *ci = new NetworkClientInfo(CLIENT_ID_SERVER);
ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : _local_company; ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : _local_company;
/* Give the server a valid IP; banning it is pointless anyways */
sockaddr_in sock;
memset(&sock, 0, sizeof(sock));
sock.sin_family = AF_INET;
ci->client_address = NetworkAddress((sockaddr*)&sock, sizeof(sock));
strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name)); strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name));
} }

View File

@ -201,12 +201,16 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID clien
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
} }
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientInfo *ci) NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkClientSocket *cs)
{ {
/* Only send data when we're a proper client, not just someone trying to query the server. */
const NetworkClientInfo *ci = cs->GetInfo();
if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO); Packet *p = new Packet(ADMIN_PACKET_SERVER_CLIENT_INFO);
p->Send_uint32(ci->client_id); p->Send_uint32(ci->client_id);
p->Send_string(const_cast<NetworkAddress &>(ci->client_address).GetHostname()); p->Send_string(const_cast<NetworkAddress &>(cs->client_address).GetHostname());
p->Send_string(ci->client_name); p->Send_string(ci->client_name);
p->Send_uint8 (ci->client_lang); p->Send_uint8 (ci->client_lang);
p->Send_uint32(ci->join_date); p->Send_uint32(ci->join_date);
@ -565,14 +569,14 @@ DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_POLL)
case ADMIN_UPDATE_CLIENT_INFO: case ADMIN_UPDATE_CLIENT_INFO:
/* The admin is requesting client info. */ /* The admin is requesting client info. */
const NetworkClientInfo *ci; const NetworkClientSocket *cs;
if (d1 == UINT32_MAX) { if (d1 == UINT32_MAX) {
FOR_ALL_CLIENT_INFOS(ci) { FOR_ALL_CLIENT_SOCKETS(cs) {
this->SendClientInfo(ci); this->SendClientInfo(cs);
} }
} else { } else {
ci = NetworkFindClientInfoFromClientID((ClientID)d1); cs = NetworkClientSocket::GetByClientID((ClientID)d1);
if (ci != NULL) this->SendClientInfo(ci); if (cs != NULL) this->SendClientInfo(cs);
} }
break; break;
@ -649,14 +653,14 @@ DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_CHAT)
* @param ci the client info. * @param ci the client info.
* @param new_client if this is a new client, send the respective packet too. * @param new_client if this is a new client, send the respective packet too.
*/ */
void NetworkAdminClientInfo(const NetworkClientInfo *ci, bool new_client) void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client)
{ {
ServerNetworkAdminSocketHandler *as; ServerNetworkAdminSocketHandler *as;
FOR_ALL_ADMIN_SOCKETS(as) { FOR_ALL_ADMIN_SOCKETS(as) {
if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) { if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) {
as->SendClientInfo(ci); as->SendClientInfo(cs);
if (new_client) { if (new_client) {
as->SendClientJoin(ci->client_id); as->SendClientJoin(cs->client_id);
} }
} }
} }

View File

@ -50,7 +50,7 @@ public:
NetworkRecvStatus SendDate(); NetworkRecvStatus SendDate();
NetworkRecvStatus SendClientJoin(ClientID client_id); NetworkRecvStatus SendClientJoin(ClientID client_id);
NetworkRecvStatus SendClientInfo(const NetworkClientInfo *ci); NetworkRecvStatus SendClientInfo(const NetworkClientSocket *cs);
NetworkRecvStatus SendClientUpdate(const NetworkClientInfo *ci); NetworkRecvStatus SendClientUpdate(const NetworkClientInfo *ci);
NetworkRecvStatus SendClientQuit(ClientID client_id); NetworkRecvStatus SendClientQuit(ClientID client_id);
NetworkRecvStatus SendClientError(ClientID client_id, NetworkErrorCode error); NetworkRecvStatus SendClientError(ClientID client_id, NetworkErrorCode error);
@ -85,7 +85,7 @@ public:
#define FOR_ALL_ADMIN_SOCKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(ServerNetworkAdminSocketHandler, adminsocket_index, var, start) #define FOR_ALL_ADMIN_SOCKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(ServerNetworkAdminSocketHandler, adminsocket_index, var, start)
#define FOR_ALL_ADMIN_SOCKETS(var) FOR_ALL_ADMIN_SOCKETS_FROM(var, 0) #define FOR_ALL_ADMIN_SOCKETS(var) FOR_ALL_ADMIN_SOCKETS_FROM(var, 0)
void NetworkAdminClientInfo(const NetworkClientInfo *ci, bool new_client = false); void NetworkAdminClientInfo(const NetworkClientSocket *cs, bool new_client = false);
void NetworkAdminClientUpdate(const NetworkClientInfo *ci); void NetworkAdminClientUpdate(const NetworkClientInfo *ci);
void NetworkAdminClientQuit(ClientID client_id); void NetworkAdminClientQuit(ClientID client_id);
void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code); void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code);

View File

@ -27,11 +27,12 @@ struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_p
char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the client char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the client
byte client_lang; ///< The language of the client byte client_lang; ///< The language of the client
CompanyID client_playas; ///< As which company is this client playing (CompanyID) CompanyID client_playas; ///< As which company is this client playing (CompanyID)
NetworkAddress client_address; ///< IP-address of the client (so he can be banned)
Date join_date; ///< Gamedate the client has joined Date join_date; ///< Gamedate the client has joined
NetworkClientInfo(ClientID client_id = INVALID_CLIENT_ID) : client_id(client_id) {} NetworkClientInfo(ClientID client_id = INVALID_CLIENT_ID) : client_id(client_id) {}
~NetworkClientInfo(); ~NetworkClientInfo();
static NetworkClientInfo *GetByClientID(ClientID client_id);
}; };
#define FOR_ALL_CLIENT_INFOS_FROM(var, start) FOR_ALL_ITEMS_FROM(NetworkClientInfo, clientinfo_index, var, start) #define FOR_ALL_CLIENT_INFOS_FROM(var, start) FOR_ALL_ITEMS_FROM(NetworkClientInfo, clientinfo_index, var, start)

View File

@ -468,7 +468,7 @@ struct NetworkChatWindow : public QueryStringBaseWindow {
if (widget != NWCW_DESTINATION) return; if (widget != NWCW_DESTINATION) return;
if (this->dtype == DESTTYPE_CLIENT) { if (this->dtype == DESTTYPE_CLIENT) {
SetDParamStr(0, NetworkFindClientInfoFromClientID((ClientID)this->dest)->client_name); SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
} }
Dimension d = GetStringBoundingBox(this->dest_string); Dimension d = GetStringBoundingBox(this->dest_string);
d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
@ -481,7 +481,7 @@ struct NetworkChatWindow : public QueryStringBaseWindow {
if (widget != NWCW_DESTINATION) return; if (widget != NWCW_DESTINATION) return;
if (this->dtype == DESTTYPE_CLIENT) { if (this->dtype == DESTTYPE_CLIENT) {
SetDParamStr(0, NetworkFindClientInfoFromClientID((ClientID)this->dest)->client_name); SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
} }
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, this->dest_string, TC_BLACK, SA_RIGHT); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, this->dest_string, TC_BLACK, SA_RIGHT);
} }

View File

@ -563,7 +563,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CLIENT_INFO)
if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET; if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
ci = NetworkFindClientInfoFromClientID(client_id); ci = NetworkClientInfo::GetByClientID(client_id);
if (ci != NULL) { if (ci != NULL) {
if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) { if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
/* Client name changed, display the change */ /* Client name changed, display the change */
@ -916,7 +916,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHAT)
p->Recv_string(msg, NETWORK_CHAT_LENGTH); p->Recv_string(msg, NETWORK_CHAT_LENGTH);
int64 data = p->Recv_uint64(); int64 data = p->Recv_uint64();
ci_to = NetworkFindClientInfoFromClientID(client_id); ci_to = NetworkClientInfo::GetByClientID(client_id);
if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY; if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY;
/* Did we initiate the action locally? */ /* Did we initiate the action locally? */
@ -925,7 +925,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHAT)
case NETWORK_ACTION_CHAT_CLIENT: case NETWORK_ACTION_CHAT_CLIENT:
/* For speaking to client we need the client-name */ /* For speaking to client we need the client-name */
snprintf(name, sizeof(name), "%s", ci_to->client_name); snprintf(name, sizeof(name), "%s", ci_to->client_name);
ci = NetworkFindClientInfoFromClientID(_network_own_client_id); ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
break; break;
/* For speaking to company or giving money, we need the company-name */ /* For speaking to company or giving money, we need the company-name */
@ -937,7 +937,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHAT)
SetDParam(0, ci_to->client_playas); SetDParam(0, ci_to->client_playas);
GetString(name, str, lastof(name)); GetString(name, str, lastof(name));
ci = NetworkFindClientInfoFromClientID(_network_own_client_id); ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
break; break;
} }
@ -961,7 +961,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_ERROR_QUIT)
ClientID client_id = (ClientID)p->Recv_uint32(); ClientID client_id = (ClientID)p->Recv_uint32();
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (ci != NULL) { if (ci != NULL) {
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8())); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8()));
delete ci; delete ci;
@ -978,7 +978,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_QUIT)
ClientID client_id = (ClientID)p->Recv_uint32(); ClientID client_id = (ClientID)p->Recv_uint32();
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (ci != NULL) { if (ci != NULL) {
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
delete ci; delete ci;
@ -998,7 +998,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_JOIN)
ClientID client_id = (ClientID)p->Recv_uint32(); ClientID client_id = (ClientID)p->Recv_uint32();
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (ci != NULL) { if (ci != NULL) {
NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name); NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name);
} }
@ -1063,7 +1063,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_MOVE)
return NETWORK_RECV_STATUS_MALFORMED_PACKET; return NETWORK_RECV_STATUS_MALFORMED_PACKET;
} }
const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
/* Just make sure we do not try to use a client_index that does not exist */ /* Just make sure we do not try to use a client_index that does not exist */
if (ci == NULL) return NETWORK_RECV_STATUS_OKAY; if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
@ -1176,7 +1176,7 @@ void NetworkClientsToSpectators(CompanyID cid)
void NetworkUpdateClientName() void NetworkUpdateClientName()
{ {
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(_network_own_client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
if (ci == NULL) return; if (ci == NULL) return;
@ -1244,19 +1244,4 @@ bool NetworkMaxSpectatorsReached()
return NetworkSpectatorCount() >= (_network_server ? _settings_client.network.max_spectators : _network_server_max_spectators); return NetworkSpectatorCount() >= (_network_server ? _settings_client.network.max_spectators : _network_server_max_spectators);
} }
/**
* Print all the clients to the console
*/
void NetworkPrintClients()
{
NetworkClientInfo *ci;
FOR_ALL_CLIENT_INFOS(ci) {
IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s",
ci->client_id,
ci->client_name,
ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
GetClientIP(ci));
}
}
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */

View File

@ -68,14 +68,13 @@ bool NetworkServerStart();
void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded); void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded);
bool NetworkServerChangeClientName(ClientID client_id, const char *new_name); bool NetworkServerChangeClientName(ClientID client_id, const char *new_name);
NetworkClientInfo *NetworkFindClientInfoFromClientID(ClientID client_id);
const char *GetClientIP(NetworkClientInfo *ci);
void NetworkServerDoMove(ClientID client_id, CompanyID company_id); void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string); void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string);
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, int64 data = 0, bool from_admin = false); void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, int64 data = 0, bool from_admin = false);
void NetworkServerKickClient(ClientID client_id); void NetworkServerKickClient(ClientID client_id);
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban);
uint NetworkServerKickOrBanIP(const char *ip, bool ban); uint NetworkServerKickOrBanIP(const char *ip, bool ban);
void NetworkInitChatMessage(); void NetworkInitChatMessage();

View File

@ -1693,8 +1693,11 @@ NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company)
extern void DrawCompanyIcon(CompanyID cid, int x, int y); extern void DrawCompanyIcon(CompanyID cid, int x, int y);
/* Every action must be of this form */ /**
typedef void ClientList_Action_Proc(byte client_no); * Prototype for ClientList actions.
* @param ci The information about the current client.
*/
typedef void ClientList_Action_Proc(const NetworkClientInfo *ci);
static const NWidgetPart _nested_client_list_popup_widgets[] = { static const NWidgetPart _nested_client_list_popup_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY, 0), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, 0), EndContainer(),
@ -1702,65 +1705,38 @@ static const NWidgetPart _nested_client_list_popup_widgets[] = {
static const WindowDesc _client_list_popup_desc( static const WindowDesc _client_list_popup_desc(
WDP_AUTO, 0, 0, WDP_AUTO, 0, 0,
WC_TOOLBAR_MENU, WC_CLIENT_LIST, WC_CLIENT_LIST_POPUP, WC_CLIENT_LIST,
0, 0,
_nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets) _nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets)
); );
/* Finds the Xth client-info that is active */
static NetworkClientInfo *NetworkFindClientInfo(byte client_no)
{
NetworkClientInfo *ci;
FOR_ALL_CLIENT_INFOS(ci) {
if (client_no == 0) return ci;
client_no--;
}
return NULL;
}
/* Here we start to define the options out of the menu */ /* Here we start to define the options out of the menu */
static void ClientList_Kick(byte client_no) static void ClientList_Kick(const NetworkClientInfo *ci)
{ {
const NetworkClientInfo *ci = NetworkFindClientInfo(client_no);
if (ci == NULL) return;
NetworkServerKickClient(ci->client_id); NetworkServerKickClient(ci->client_id);
} }
static void ClientList_Ban(byte client_no) static void ClientList_Ban(const NetworkClientInfo *ci)
{ {
NetworkClientInfo *ci = NetworkFindClientInfo(client_no); NetworkServerKickOrBanIP(ci->client_id, true);
if (ci == NULL) return;
NetworkServerKickOrBanIP(GetClientIP(ci), true);
} }
static void ClientList_GiveMoney(byte client_no) static void ClientList_GiveMoney(const NetworkClientInfo *ci)
{ {
if (NetworkFindClientInfo(client_no) != NULL) { ShowNetworkGiveMoneyWindow(ci->client_playas);
ShowNetworkGiveMoneyWindow(NetworkFindClientInfo(client_no)->client_playas);
}
} }
static void ClientList_SpeakToClient(byte client_no) static void ClientList_SpeakToClient(const NetworkClientInfo *ci)
{ {
if (NetworkFindClientInfo(client_no) != NULL) { ShowNetworkChatQueryWindow(DESTTYPE_CLIENT,ci->client_id);
ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, NetworkFindClientInfo(client_no)->client_id);
}
} }
static void ClientList_SpeakToCompany(byte client_no) static void ClientList_SpeakToCompany(const NetworkClientInfo *ci)
{ {
if (NetworkFindClientInfo(client_no) != NULL) { ShowNetworkChatQueryWindow(DESTTYPE_TEAM, ci->client_playas);
ShowNetworkChatQueryWindow(DESTTYPE_TEAM, NetworkFindClientInfo(client_no)->client_playas);
}
} }
static void ClientList_SpeakToAll(byte client_no) static void ClientList_SpeakToAll(const NetworkClientInfo *ci)
{ {
ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0); ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
} }
@ -1774,7 +1750,7 @@ struct NetworkClientListPopupWindow : Window {
}; };
uint sel_index; uint sel_index;
int client_no; ClientID client_id;
Point desired_location; Point desired_location;
SmallVector<ClientListAction, 2> actions; ///< Actions to execute SmallVector<ClientListAction, 2> actions; ///< Actions to execute
@ -1790,14 +1766,14 @@ struct NetworkClientListPopupWindow : Window {
action->proc = proc; action->proc = proc;
} }
NetworkClientListPopupWindow(const WindowDesc *desc, int x, int y, int client_no) : NetworkClientListPopupWindow(const WindowDesc *desc, int x, int y, ClientID client_id) :
Window(), Window(),
sel_index(0), client_no(client_no) sel_index(0), client_id(client_id)
{ {
this->desired_location.x = x; this->desired_location.x = x;
this->desired_location.y = y; this->desired_location.y = y;
const NetworkClientInfo *ci = NetworkFindClientInfo(client_no); const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (_network_own_client_id != ci->client_id) { if (_network_own_client_id != ci->client_id) {
this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, &ClientList_SpeakToClient); this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, &ClientList_SpeakToClient);
@ -1822,7 +1798,7 @@ struct NetworkClientListPopupWindow : Window {
} }
this->flags4 &= ~WF_WHITE_BORDER_MASK; this->flags4 &= ~WF_WHITE_BORDER_MASK;
this->InitNested(desc, 0); this->InitNested(desc, client_id);
} }
virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number) virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
@ -1873,10 +1849,11 @@ struct NetworkClientListPopupWindow : Window {
this->SetDirty(); this->SetDirty();
} else { } else {
if (index < this->actions.Length() && _cursor.pos.y >= this->top) { if (index < this->actions.Length() && _cursor.pos.y >= this->top) {
this->actions[index].proc(this->client_no); const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(this->client_id);
if (ci != NULL) this->actions[index].proc(ci);
} }
DeleteWindowById(WC_TOOLBAR_MENU, 0); DeleteWindowByClass(WC_CLIENT_LIST_POPUP);
} }
} }
}; };
@ -1884,13 +1861,13 @@ struct NetworkClientListPopupWindow : Window {
/** /**
* Show the popup (action list) * Show the popup (action list)
*/ */
static void PopupClientList(int client_no, int x, int y) static void PopupClientList(ClientID client_id, int x, int y)
{ {
DeleteWindowById(WC_TOOLBAR_MENU, 0); DeleteWindowByClass(WC_CLIENT_LIST_POPUP);
if (NetworkFindClientInfo(client_no) == NULL) return; if (NetworkClientInfo::GetByClientID(client_id) == NULL) return;
new NetworkClientListPopupWindow(&_client_list_popup_desc, x, y, client_no); new NetworkClientListPopupWindow(&_client_list_popup_desc, x, y, client_id);
} }
@ -2027,7 +2004,15 @@ struct NetworkClientListWindow : Window {
{ {
/* Show the popup with option */ /* Show the popup with option */
if (this->selected_item != -1) { if (this->selected_item != -1) {
PopupClientList(this->selected_item, pt.x + this->left, pt.y + this->top); NetworkClientInfo *ci;
int client_no = this->selected_item;
FOR_ALL_CLIENT_INFOS(ci) {
if (client_no == 0) break;
client_no--;
}
if (ci != NULL) PopupClientList(ci->client_id, pt.x + this->left, pt.y + this->top);
} }
} }

View File

@ -164,7 +164,6 @@ void NetworkSyncCommandQueue(NetworkClientSocket *cs);
void NetworkError(StringID error_string); void NetworkError(StringID error_string);
void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0); void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0);
uint NetworkCalculateLag(const NetworkClientSocket *cs); uint NetworkCalculateLag(const NetworkClientSocket *cs);
NetworkClientSocket *NetworkFindClientStateFromClientID(ClientID client_id);
StringID GetNetworkErrorMsg(NetworkErrorCode err); StringID GetNetworkErrorMsg(NetworkErrorCode err);
bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]); bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed);

View File

@ -161,12 +161,6 @@ ServerNetworkGameSocketHandler::ServerNetworkGameSocketHandler(SOCKET s) : Netwo
* each Socket will be associated with at most one Info object. As * each Socket will be associated with at most one Info object. As
* such if the Socket was allocated the Info object can as well. */ * such if the Socket was allocated the Info object can as well. */
assert_compile(NetworkClientSocketPool::MAX_SIZE == NetworkClientInfoPool::MAX_SIZE); assert_compile(NetworkClientSocketPool::MAX_SIZE == NetworkClientInfoPool::MAX_SIZE);
assert(NetworkClientInfo::CanAllocateItem());
NetworkClientInfo *ci = new NetworkClientInfo(this->client_id);
this->SetInfo(ci);
ci->client_playas = COMPANY_INACTIVE_CLIENT;
ci->join_date = _date;
} }
/** /**
@ -253,6 +247,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvSta
extern byte _network_clients_connected; extern byte _network_clients_connected;
_network_clients_connected--; _network_clients_connected--;
DeleteWindowById(WC_CLIENT_LIST_POPUP, this->client_id);
SetWindowDirty(WC_CLIENT_LIST, 0); SetWindowDirty(WC_CLIENT_LIST, 0);
this->SendPackets(true); this->SendPackets(true);
@ -325,7 +320,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo()
memset(clients, 0, sizeof(clients)); memset(clients, 0, sizeof(clients));
/* Add the local player (if not dedicated) */ /* Add the local player (if not dedicated) */
const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER); const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
if (ci != NULL && Company::IsValidID(ci->client_playas)) { if (ci != NULL && Company::IsValidID(ci->client_playas)) {
strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas])); strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas]));
} }
@ -486,7 +481,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome()
} }
} }
/* Also send the info of the server */ /* Also send the info of the server */
return this->SendClientInfo(NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER)); return this->SendClientInfo(NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER));
} }
NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait() NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait()
@ -495,9 +490,10 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait()
NetworkClientSocket *new_cs; NetworkClientSocket *new_cs;
Packet *p; Packet *p;
/* Count how many clients are waiting in the queue */ /* Count how many clients are waiting in the queue, in front of you! */
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status == STATUS_MAP_WAIT) waiting++; if (new_cs->status != STATUS_MAP_WAIT) continue;
if (new_cs->GetInfo()->join_date < this->GetInfo()->join_date || (new_cs->GetInfo()->join_date == this->GetInfo()->join_date && new_cs->client_id < this->client_id)) waiting++;
} }
p = new Packet(PACKET_SERVER_WAIT); p = new Packet(PACKET_SERVER_WAIT);
@ -566,24 +562,28 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
* to send it is ready (maybe that happens like never ;)) */ * to send it is ready (maybe that happens like never ;)) */
this->status = STATUS_DONE_MAP; this->status = STATUS_DONE_MAP;
/* Find the best candidate for joining, i.e. the first joiner. */
NetworkClientSocket *new_cs; NetworkClientSocket *new_cs;
bool new_map_client = false; NetworkClientSocket *best = NULL;
/* Check if there is a client waiting for receiving the map
* and start sending him the map */
FOR_ALL_CLIENT_SOCKETS(new_cs) { FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status == STATUS_MAP_WAIT) { if (new_cs->status == STATUS_MAP_WAIT) {
/* Check if we already have a new client to send the map to */ if (best == NULL || best->GetInfo()->join_date > new_cs->GetInfo()->join_date || (best->GetInfo()->join_date == new_cs->GetInfo()->join_date && best->client_id > new_cs->client_id)) {
if (!new_map_client) { best = new_cs;
/* If not, this client will get the map */
new_cs->status = STATUS_AUTHORIZED;
new_map_client = true;
new_cs->SendMap();
} else {
/* Else, send the other clients how many clients are in front of them */
new_cs->SendWait();
} }
} }
} }
/* Is there someone else to join? */
if (best != NULL) {
/* Let the first start joining. */
best->status = STATUS_AUTHORIZED;
best->SendMap();
/* And update the rest. */
FOR_ALL_CLIENT_SOCKETS(new_cs) {
if (new_cs->status == STATUS_MAP_WAIT) new_cs->SendWait();
}
}
} }
switch (this->SendPackets()) { switch (this->SendPackets()) {
@ -793,7 +793,6 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_JOIN)
} }
char name[NETWORK_CLIENT_NAME_LENGTH]; char name[NETWORK_CLIENT_NAME_LENGTH];
NetworkClientInfo *ci;
CompanyID playas; CompanyID playas;
NetworkLanguage client_lang; NetworkLanguage client_lang;
char client_revision[NETWORK_REVISION_LENGTH]; char client_revision[NETWORK_REVISION_LENGTH];
@ -839,8 +838,10 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_JOIN)
return this->SendError(NETWORK_ERROR_NAME_IN_USE); return this->SendError(NETWORK_ERROR_NAME_IN_USE);
} }
ci = this->GetInfo(); assert(NetworkClientInfo::CanAllocateItem());
NetworkClientInfo *ci = new NetworkClientInfo(this->client_id);
this->SetInfo(ci);
ci->join_date = _date;
strecpy(ci->client_name, name, lastof(ci->client_name)); strecpy(ci->client_name, name, lastof(ci->client_name));
ci->client_playas = playas; ci->client_playas = playas;
ci->client_lang = client_lang; ci->client_lang = client_lang;
@ -978,7 +979,7 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_MAP_OK)
} }
} }
NetworkAdminClientInfo(this->GetInfo(), true); NetworkAdminClientInfo(this, true);
/* also update the new client with our max values */ /* also update the new client with our max values */
this->SendConfigUpdate(); this->SendConfigUpdate();
@ -1015,18 +1016,18 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMMAND)
NetworkClientInfo *ci = this->GetInfo(); NetworkClientInfo *ci = this->GetInfo();
if (err != NULL) { if (err != NULL) {
IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, GetClientIP(ci)); IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
return this->SendError(NETWORK_ERROR_NOT_EXPECTED); return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
} }
if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) { if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci)); IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
return this->SendError(NETWORK_ERROR_KICKED); return this->SendError(NETWORK_ERROR_KICKED);
} }
if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) { if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) {
IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci)); IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, this->GetClientIP());
return this->SendError(NETWORK_ERROR_KICKED); return this->SendError(NETWORK_ERROR_KICKED);
} }
@ -1037,7 +1038,7 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMMAND)
*/ */
if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) { if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...", IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
ci->client_playas + 1, GetClientIP(ci), cp.company + 1); ci->client_playas + 1, this->GetClientIP(), cp.company + 1);
return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH); return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
} }
@ -1176,7 +1177,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
case DESTTYPE_CLIENT: case DESTTYPE_CLIENT:
/* Are we sending to the server? */ /* Are we sending to the server? */
if ((ClientID)dest == CLIENT_ID_SERVER) { if ((ClientID)dest == CLIENT_ID_SERVER) {
ci = NetworkFindClientInfoFromClientID(from_id); ci = NetworkClientInfo::GetByClientID(from_id);
/* Display the text locally, and that is it */ /* Display the text locally, and that is it */
if (ci != NULL) { if (ci != NULL) {
NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data); NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
@ -1198,8 +1199,8 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
/* Display the message locally (so you know you have sent it) */ /* Display the message locally (so you know you have sent it) */
if (from_id != (ClientID)dest) { if (from_id != (ClientID)dest) {
if (from_id == CLIENT_ID_SERVER) { if (from_id == CLIENT_ID_SERVER) {
ci = NetworkFindClientInfoFromClientID(from_id); ci = NetworkClientInfo::GetByClientID(from_id);
ci_to = NetworkFindClientInfoFromClientID((ClientID)dest); ci_to = NetworkClientInfo::GetByClientID((ClientID)dest);
if (ci != NULL && ci_to != NULL) { if (ci != NULL && ci_to != NULL) {
NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data); NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
} }
@ -1220,7 +1221,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
ci_to = NULL; ci_to = NULL;
FOR_ALL_CLIENT_SOCKETS(cs) { FOR_ALL_CLIENT_SOCKETS(cs) {
ci = cs->GetInfo(); ci = cs->GetInfo();
if (ci->client_playas == (CompanyID)dest) { if (ci != NULL && ci->client_playas == (CompanyID)dest) {
cs->SendChat(action, from_id, false, msg, data); cs->SendChat(action, from_id, false, msg, data);
if (cs->client_id == from_id) show_local = false; if (cs->client_id == from_id) show_local = false;
ci_to = ci; // Remember a client that is in the company for company-name ci_to = ci; // Remember a client that is in the company for company-name
@ -1232,8 +1233,8 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
NetworkAdminChat(action, desttype, from_id, msg, data, from_admin); NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
} }
ci = NetworkFindClientInfoFromClientID(from_id); ci = NetworkClientInfo::GetByClientID(from_id);
ci_own = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER); ci_own = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) { if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data); NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
if (from_id == CLIENT_ID_SERVER) show_local = false; if (from_id == CLIENT_ID_SERVER) show_local = false;
@ -1271,7 +1272,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
NetworkAdminChat(action, desttype, from_id, msg, data, from_admin); NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
ci = NetworkFindClientInfoFromClientID(from_id); ci = NetworkClientInfo::GetByClientID(from_id);
if (ci != NULL) { if (ci != NULL) {
NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data); NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
} }
@ -1305,7 +1306,7 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_CHAT)
NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data); NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
break; break;
default: default:
IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, GetClientIP(ci)); IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, this->GetClientIP());
return this->SendError(NETWORK_ERROR_NOT_EXPECTED); return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
} }
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
@ -1501,7 +1502,7 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
void NetworkUpdateClientInfo(ClientID client_id) void NetworkUpdateClientInfo(ClientID client_id)
{ {
NetworkClientSocket *cs; NetworkClientSocket *cs;
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (ci == NULL) return; if (ci == NULL) return;
@ -1546,7 +1547,7 @@ static void NetworkAutoCleanCompanies()
} }
if (!_network_dedicated) { if (!_network_dedicated) {
ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER); ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true; if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
} }
@ -1621,7 +1622,7 @@ bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
} }
} }
/* Check if it is the same as the server-name */ /* Check if it is the same as the server-name */
ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER); ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
if (ci != NULL) { if (ci != NULL) {
if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
} }
@ -1652,7 +1653,7 @@ bool NetworkServerChangeClientName(ClientID client_id, const char *new_name)
if (strcmp(ci->client_name, new_name) == 0) return false; if (strcmp(ci->client_name, new_name) == 0) return false;
} }
ci = NetworkFindClientInfoFromClientID(client_id); ci = NetworkClientInfo::GetByClientID(client_id);
if (ci == NULL) return false; if (ci == NULL) return false;
NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name); NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
@ -1806,9 +1807,13 @@ void NetworkServerDailyLoop()
if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY); if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
} }
const char *GetClientIP(NetworkClientInfo *ci) /**
* Get the IP address/hostname of the connected client.
* @return The IP address.
*/
const char *ServerNetworkGameSocketHandler::GetClientIP()
{ {
return ci->client_address.GetHostname(); return this->client_address.GetHostname();
} }
void NetworkServerShowStatusToConsole() void NetworkServerShowStatusToConsole()
@ -1829,15 +1834,16 @@ void NetworkServerShowStatusToConsole()
NetworkClientSocket *cs; NetworkClientSocket *cs;
FOR_ALL_CLIENT_SOCKETS(cs) { FOR_ALL_CLIENT_SOCKETS(cs) {
uint lag = NetworkCalculateLag(cs);
NetworkClientInfo *ci = cs->GetInfo(); NetworkClientInfo *ci = cs->GetInfo();
if (ci == NULL) continue;
uint lag = NetworkCalculateLag(cs);
const char *status; const char *status;
status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown"); status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s", IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s",
cs->client_id, ci->client_name, status, lag, cs->client_id, ci->client_name, status, lag,
ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0), ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
GetClientIP(ci)); cs->GetClientIP());
} }
} }
@ -1879,7 +1885,7 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
/* Only allow non-dedicated servers and normal clients to be moved */ /* Only allow non-dedicated servers and normal clients to be moved */
if (client_id == CLIENT_ID_SERVER && _network_dedicated) return; if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
/* No need to waste network resources if the client is in the company already! */ /* No need to waste network resources if the client is in the company already! */
if (ci->client_playas == company_id) return; if (ci->client_playas == company_id) return;
@ -1889,7 +1895,7 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
if (client_id == CLIENT_ID_SERVER) { if (client_id == CLIENT_ID_SERVER) {
SetLocalCompany(company_id); SetLocalCompany(company_id);
} else { } else {
NetworkClientSocket *cs = NetworkFindClientStateFromClientID(client_id); NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id);
/* When the company isn't authorized we can't move them yet. */ /* When the company isn't authorized we can't move them yet. */
if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return; if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
cs->SendMove(client_id, company_id); cs->SendMove(client_id, company_id);
@ -1904,12 +1910,12 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string) void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
{ {
NetworkFindClientStateFromClientID(client_id)->SendRConResult(colour_code, string); NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string);
} }
static void NetworkServerSendError(ClientID client_id, NetworkErrorCode error) static void NetworkServerSendError(ClientID client_id, NetworkErrorCode error)
{ {
NetworkFindClientStateFromClientID(client_id)->SendError(error); NetworkClientSocket::GetByClientID(client_id)->SendError(error);
} }
void NetworkServerKickClient(ClientID client_id) void NetworkServerKickClient(ClientID client_id)
@ -1918,6 +1924,11 @@ void NetworkServerKickClient(ClientID client_id)
NetworkServerSendError(client_id, NETWORK_ERROR_KICKED); NetworkServerSendError(client_id, NETWORK_ERROR_KICKED);
} }
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
{
return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
}
uint NetworkServerKickOrBanIP(const char *ip, bool ban) uint NetworkServerKickOrBanIP(const char *ip, bool ban)
{ {
/* Add address to ban-list */ /* Add address to ban-list */
@ -1926,11 +1937,11 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban)
uint n = 0; uint n = 0;
/* There can be multiple clients with the same IP, kick them all */ /* There can be multiple clients with the same IP, kick them all */
NetworkClientInfo *ci; NetworkClientSocket *cs;
FOR_ALL_CLIENT_INFOS(ci) { FOR_ALL_CLIENT_SOCKETS(cs) {
if (ci->client_id == CLIENT_ID_SERVER) continue; if (cs->client_id == CLIENT_ID_SERVER) continue;
if (ci->client_address.IsInNetmask(const_cast<char *>(ip))) { if (cs->client_address.IsInNetmask(const_cast<char *>(ip))) {
NetworkServerKickClient(ci->client_id); NetworkServerKickClient(cs->client_id);
n++; n++;
} }
} }
@ -1957,11 +1968,26 @@ void ServerNetworkGameSocketHandler::GetClientName(char *client_name, size_t siz
{ {
const NetworkClientInfo *ci = this->GetInfo(); const NetworkClientInfo *ci = this->GetInfo();
if (StrEmpty(ci->client_name)) { if (ci == NULL || StrEmpty(ci->client_name)) {
snprintf(client_name, size, "Client #%4d", this->client_id); snprintf(client_name, size, "Client #%4d", this->client_id);
} else { } else {
ttd_strlcpy(client_name, ci->client_name, size); ttd_strlcpy(client_name, ci->client_name, size);
} }
} }
/**
* Print all the clients to the console
*/
void NetworkPrintClients()
{
NetworkClientInfo *ci;
FOR_ALL_CLIENT_INFOS(ci) {
IConsolePrintF(CC_INFO, _network_server ? "Client #%1d name: '%s' company: %1d IP: %s" : "Client #%1d name: '%s' company: %1d",
ci->client_id,
ci->client_name,
ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
_network_server ? (ci->client_id == CLIENT_ID_SERVER ? "server" : NetworkClientSocket::GetByClientID(ci->client_id)->GetClientIP()) : "");
}
}
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */

View File

@ -76,6 +76,7 @@ public:
Packet *savegame_packets; ///< Packet queue of the savegame; send these "slowly" to the client. Packet *savegame_packets; ///< Packet queue of the savegame; send these "slowly" to the client.
struct PacketWriter *savegame; ///< Writer used to write the savegame. struct PacketWriter *savegame; ///< Writer used to write the savegame.
ThreadMutex *savegame_mutex; ///< Mutex for making threaded saving safe. ThreadMutex *savegame_mutex; ///< Mutex for making threaded saving safe.
NetworkAddress client_address; ///< IP-address of the client (so he can be banned)
ServerNetworkGameSocketHandler(SOCKET s); ServerNetworkGameSocketHandler(SOCKET s);
~ServerNetworkGameSocketHandler(); ~ServerNetworkGameSocketHandler();
@ -115,6 +116,10 @@ public:
{ {
return "server"; return "server";
} }
const char *GetClientIP();
static ServerNetworkGameSocketHandler *GetByClientID(ClientID client_id);
}; };
void NetworkServer_Tick(bool send_frame); void NetworkServer_Tick(bool send_frame);

View File

@ -35,6 +35,17 @@ static inline uint32 GetRegister(uint i)
return _temp_store.Get(i); return _temp_store.Get(i);
} }
/**
* Clears the value of a so-called newgrf "register".
* @param i index of the register
* @pre i < 0x110
*/
static inline void ClearRegister(uint i)
{
extern TemporaryStorageArray<int32, 0x110> _temp_store;
_temp_store.Store(i, 0);
}
/* List of different sprite group types */ /* List of different sprite group types */
enum SpriteGroupType { enum SpriteGroupType {
SGT_REAL, SGT_REAL,

View File

@ -114,7 +114,7 @@ uint32 GetPlatformInfo(Axis axis, byte tile, int platforms, int length, int x, i
x -= platforms / 2; x -= platforms / 2;
y -= length / 2; y -= length / 2;
x = Clamp(x, -8, 7); x = Clamp(x, -8, 7);
y = Clamp(x, -8, 7); y = Clamp(y, -8, 7);
SB(retval, 0, 4, y & 0xF); SB(retval, 0, 4, y & 0xF);
SB(retval, 4, 4, x & 0xF); SB(retval, 4, 4, x & 0xF);
} else { } else {
@ -613,6 +613,7 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, const
NewStationResolver(&object, statspec, st, tile); NewStationResolver(&object, statspec, st, tile);
object.callback_param1 = 2; // Indicate we are resolving the foundation sprites object.callback_param1 = 2; // Indicate we are resolving the foundation sprites
ClearRegister(0x100);
group = ResolveStation(&object); group = ResolveStation(&object);
if (group == NULL || group->type != SGT_RESULT) return 0; if (group == NULL || group->type != SGT_RESULT) return 0;
return group->GetResult() + GetRegister(0x100); return group->GetResult() + GetRegister(0x100);

View File

@ -281,7 +281,7 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
char *p = buf; char *p = buf;
p += seprintf(p, lastof(buf), "Graphics set: %s (%u)\n", BaseGraphics::GetUsedSet()->name, BaseGraphics::GetUsedSet()->version); p += seprintf(p, lastof(buf), "Graphics set: %s (%u)\n", BaseGraphics::GetUsedSet()->name, BaseGraphics::GetUsedSet()->version);
p = strecpy(p, "NewGRFs:\n", lastof(buf)); p = strecpy(p, "NewGRFs:\n", lastof(buf));
for (const GRFConfig *c = _grfconfig; c != NULL; c = c->next) { for (const GRFConfig *c = _game_mode == GM_MENU ? NULL : _grfconfig; c != NULL; c = c->next) {
p += seprintf(p, lastof(buf), "%08X ", BSWAP32(c->ident.grfid)); p += seprintf(p, lastof(buf), "%08X ", BSWAP32(c->ident.grfid));
p = md5sumToString(p, lastof(buf), c->ident.md5sum); p = md5sumToString(p, lastof(buf), c->ident.md5sum);
p += seprintf(p, lastof(buf), " %s\n", c->filename); p += seprintf(p, lastof(buf), " %s\n", c->filename);

View File

@ -2565,7 +2565,6 @@ restart_search:
w->window_class != WC_SELECT_GAME && w->window_class != WC_SELECT_GAME &&
w->window_class != WC_MAIN_TOOLBAR && w->window_class != WC_MAIN_TOOLBAR &&
w->window_class != WC_STATUS_BAR && w->window_class != WC_STATUS_BAR &&
w->window_class != WC_TOOLBAR_MENU &&
w->window_class != WC_TOOLTIPS && w->window_class != WC_TOOLTIPS &&
(w->flags4 & WF_STICKY) == 0) { // do not delete windows which are 'pinned' (w->flags4 & WF_STICKY) == 0) { // do not delete windows which are 'pinned'
@ -2626,7 +2625,6 @@ restart_search:
/** Delete all always on-top windows to get an empty screen */ /** Delete all always on-top windows to get an empty screen */
void HideVitalWindows() void HideVitalWindows()
{ {
DeleteWindowById(WC_TOOLBAR_MENU, 0);
DeleteWindowById(WC_MAIN_TOOLBAR, 0); DeleteWindowById(WC_MAIN_TOOLBAR, 0);
DeleteWindowById(WC_STATUS_BAR, 0); DeleteWindowById(WC_STATUS_BAR, 0);
} }

View File

@ -51,7 +51,7 @@ enum WindowClass {
WC_QUERY_STRING, WC_QUERY_STRING,
WC_SAVELOAD, WC_SAVELOAD,
WC_SELECT_GAME, WC_SELECT_GAME,
WC_TOOLBAR_MENU, WC_CLIENT_LIST_POPUP,
WC_INCOME_GRAPH, WC_INCOME_GRAPH,
WC_OPERATING_PROFIT, WC_OPERATING_PROFIT,
WC_TOOLTIPS, WC_TOOLTIPS,