From 59a11e66263645c3ae30c0bdf572f02711576ca5 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sun, 15 May 2011 09:38:54 +0000 Subject: [PATCH] (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) --- src/company_cmd.cpp | 4 +- src/console_cmds.cpp | 17 ++-- src/main_gui.cpp | 4 +- src/network/core/tcp_game.h | 2 +- src/network/network.cpp | 11 +-- src/network/network_admin.cpp | 24 +++--- src/network/network_admin.h | 4 +- src/network/network_base.h | 3 +- src/network/network_chat_gui.cpp | 4 +- src/network/network_client.cpp | 33 ++------ src/network/network_func.h | 3 +- src/network/network_gui.cpp | 89 ++++++++------------ src/network/network_internal.h | 1 - src/network/network_server.cpp | 140 ++++++++++++++++++------------- src/network/network_server.h | 5 ++ src/newgrf_spritegroup.h | 11 +++ src/newgrf_station.cpp | 3 +- src/screenshot.cpp | 2 +- src/window.cpp | 2 - src/window_type.h | 2 +- 20 files changed, 187 insertions(+), 177 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index b2f42d5384..d8d52ecd6d 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -556,7 +556,7 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY) GeneratePresidentName(c); SetWindowDirty(WC_GRAPH_LEGEND, 0); - SetWindowDirty(WC_TOOLBAR_MENU, 0); + SetWindowClassesDirty(WC_CLIENT_LIST_POPUP); SetWindowDirty(WC_CLIENT_LIST, 0); BuildOwnerLegend(); InvalidateWindowData(WC_SMALLMAP, 0, 1); @@ -813,7 +813,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 #ifdef ENABLE_NETWORK /* Has the network client a correct ClientIndex? */ if (!(flags & DC_EXEC)) return CommandCost(); - NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); + NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci == NULL) return CommandCost(); /* Delete multiplayer progress bar */ diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index cacf9ada36..330bb46910 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -490,7 +490,7 @@ DEF_CONSOLE_CMD(ConClearBuffer) static bool ConKickOrBan(const char *argv, bool ban) { - const char *ip = argv; + uint n; if (strchr(argv, '.') == NULL && strchr(argv, ':') == NULL) { // banning with ID ClientID client_id = (ClientID)atoi(argv); @@ -504,7 +504,7 @@ static bool ConKickOrBan(const char *argv, bool ban) return true; } - NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); + NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci == NULL) { IConsoleError("Invalid client"); return true; @@ -517,10 +517,11 @@ static bool ConKickOrBan(const char *argv, bool ban) } /* 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) { IConsolePrint(CC_DEFAULT, ban ? "Client not online, address added to banlist" : "Client not found"); } else { @@ -699,7 +700,7 @@ DEF_CONSOLE_CMD(ConClientNickChange) return true; } - if (NetworkFindClientInfoFromClientID(client_id) == NULL) { + if (NetworkClientInfo::GetByClientID(client_id) == NULL) { IConsoleError("Invalid client"); return true; } @@ -727,7 +728,7 @@ DEF_CONSOLE_CMD(ConJoinCompany) 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!"); return true; } @@ -766,7 +767,7 @@ DEF_CONSOLE_CMD(ConMoveClient) 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])); /* check the client exists */ @@ -828,7 +829,7 @@ DEF_CONSOLE_CMD(ConResetCompany) IConsoleError("Cannot remove company: a client is connected to that company."); return false; } - const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER); + const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER); if (ci->client_playas == index) { IConsoleError("Cannot remove company: the server is connected to that company."); return true; diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 45f2d7ebb5..92e3e5f5dc 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -377,7 +377,7 @@ struct MainWindow : Window #ifdef ENABLE_NETWORK case GHK_CHAT: // smart chat; send to team if any, otherwise to all if (_networking) { - const NetworkClientInfo *cio = NetworkFindClientInfoFromClientID(_network_own_client_id); + const NetworkClientInfo *cio = NetworkClientInfo::GetByClientID(_network_own_client_id); if (cio == NULL) break; 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 if (_networking) { - const NetworkClientInfo *cio = NetworkFindClientInfoFromClientID(_network_own_client_id); + const NetworkClientInfo *cio = NetworkClientInfo::GetByClientID(_network_own_client_id); if (cio == NULL) break; ShowNetworkChatQueryWindow(DESTTYPE_TEAM, cio->client_playas); diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index fc15e7ba8b..decbe00c5c 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -266,7 +266,7 @@ protected: /** * 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); diff --git a/src/network/network.cpp b/src/network/network.cpp index 04268dbf6e..8b5245622c 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -108,7 +108,7 @@ NetworkClientInfo::~NetworkClientInfo() * @param client_id the ClientID to search for * @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; @@ -124,7 +124,7 @@ NetworkClientInfo *NetworkFindClientInfoFromClientID(ClientID client_id) * @param client_id the ClientID to search for * @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; @@ -484,7 +484,7 @@ void ParseConnectionString(const char **company, const char **port, char *connec SetWindowDirty(WC_CLIENT_LIST, 0); 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()); NetworkClientInfo *ci = new NetworkClientInfo(CLIENT_ID_SERVER); 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)); } diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 22c8332887..2abfa7cdb7 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -201,12 +201,16 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientJoin(ClientID clien 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); p->Send_uint32(ci->client_id); - p->Send_string(const_cast(ci->client_address).GetHostname()); + p->Send_string(const_cast(cs->client_address).GetHostname()); p->Send_string(ci->client_name); p->Send_uint8 (ci->client_lang); p->Send_uint32(ci->join_date); @@ -565,14 +569,14 @@ DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_POLL) case ADMIN_UPDATE_CLIENT_INFO: /* The admin is requesting client info. */ - const NetworkClientInfo *ci; + const NetworkClientSocket *cs; if (d1 == UINT32_MAX) { - FOR_ALL_CLIENT_INFOS(ci) { - this->SendClientInfo(ci); + FOR_ALL_CLIENT_SOCKETS(cs) { + this->SendClientInfo(cs); } } else { - ci = NetworkFindClientInfoFromClientID((ClientID)d1); - if (ci != NULL) this->SendClientInfo(ci); + cs = NetworkClientSocket::GetByClientID((ClientID)d1); + if (cs != NULL) this->SendClientInfo(cs); } break; @@ -649,14 +653,14 @@ DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_CHAT) * @param ci the client info. * @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; FOR_ALL_ADMIN_SOCKETS(as) { if (as->update_frequency[ADMIN_UPDATE_CLIENT_INFO] & ADMIN_FREQUENCY_AUTOMATIC) { - as->SendClientInfo(ci); + as->SendClientInfo(cs); if (new_client) { - as->SendClientJoin(ci->client_id); + as->SendClientJoin(cs->client_id); } } } diff --git a/src/network/network_admin.h b/src/network/network_admin.h index d9f64c73e7..c1407bc7c5 100644 --- a/src/network/network_admin.h +++ b/src/network/network_admin.h @@ -50,7 +50,7 @@ public: NetworkRecvStatus SendDate(); NetworkRecvStatus SendClientJoin(ClientID client_id); - NetworkRecvStatus SendClientInfo(const NetworkClientInfo *ci); + NetworkRecvStatus SendClientInfo(const NetworkClientSocket *cs); NetworkRecvStatus SendClientUpdate(const NetworkClientInfo *ci); NetworkRecvStatus SendClientQuit(ClientID client_id); 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(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 NetworkAdminClientQuit(ClientID client_id); void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code); diff --git a/src/network/network_base.h b/src/network/network_base.h index 219afe9270..625e769d26 100644 --- a/src/network/network_base.h +++ b/src/network/network_base.h @@ -27,11 +27,12 @@ struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_p char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the client byte client_lang; ///< The language of the client 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 NetworkClientInfo(ClientID client_id = INVALID_CLIENT_ID) : client_id(client_id) {} ~NetworkClientInfo(); + + static NetworkClientInfo *GetByClientID(ClientID client_id); }; #define FOR_ALL_CLIENT_INFOS_FROM(var, start) FOR_ALL_ITEMS_FROM(NetworkClientInfo, clientinfo_index, var, start) diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 6a2c768aaf..a53f451295 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -468,7 +468,7 @@ struct NetworkChatWindow : public QueryStringBaseWindow { if (widget != NWCW_DESTINATION) return; 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); d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; @@ -481,7 +481,7 @@ struct NetworkChatWindow : public QueryStringBaseWindow { if (widget != NWCW_DESTINATION) return; 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); } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 8380b47822..35741f09ae 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -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->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; - ci = NetworkFindClientInfoFromClientID(client_id); + ci = NetworkClientInfo::GetByClientID(client_id); if (ci != NULL) { if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) { /* 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); 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; /* Did we initiate the action locally? */ @@ -925,7 +925,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHAT) case NETWORK_ACTION_CHAT_CLIENT: /* For speaking to client we need the 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; /* 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); GetString(name, str, lastof(name)); - ci = NetworkFindClientInfoFromClientID(_network_own_client_id); + ci = NetworkClientInfo::GetByClientID(_network_own_client_id); break; } @@ -961,7 +961,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_ERROR_QUIT) ClientID client_id = (ClientID)p->Recv_uint32(); - NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); + NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci != NULL) { NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8())); delete ci; @@ -978,7 +978,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_QUIT) ClientID client_id = (ClientID)p->Recv_uint32(); - NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); + NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci != NULL) { NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING); delete ci; @@ -998,7 +998,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_JOIN) ClientID client_id = (ClientID)p->Recv_uint32(); - NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); + NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci != NULL) { 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; } - 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 */ if (ci == NULL) return NETWORK_RECV_STATUS_OKAY; @@ -1176,7 +1176,7 @@ void NetworkClientsToSpectators(CompanyID cid) void NetworkUpdateClientName() { - NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(_network_own_client_id); + NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(_network_own_client_id); if (ci == NULL) return; @@ -1244,19 +1244,4 @@ bool NetworkMaxSpectatorsReached() 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 */ diff --git a/src/network/network_func.h b/src/network/network_func.h index f504061405..af530d0684 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -68,14 +68,13 @@ bool NetworkServerStart(); void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded); 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 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 NetworkServerKickClient(ClientID client_id); +uint NetworkServerKickOrBanIP(ClientID client_id, bool ban); uint NetworkServerKickOrBanIP(const char *ip, bool ban); void NetworkInitChatMessage(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 0eb99ce7fb..3c4013e97d 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1693,8 +1693,11 @@ NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company) 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[] = { 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( WDP_AUTO, 0, 0, - WC_TOOLBAR_MENU, WC_CLIENT_LIST, + WC_CLIENT_LIST_POPUP, WC_CLIENT_LIST, 0, _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 */ -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); } -static void ClientList_Ban(byte client_no) +static void ClientList_Ban(const NetworkClientInfo *ci) { - NetworkClientInfo *ci = NetworkFindClientInfo(client_no); - - if (ci == NULL) return; - - NetworkServerKickOrBanIP(GetClientIP(ci), true); + NetworkServerKickOrBanIP(ci->client_id, true); } -static void ClientList_GiveMoney(byte client_no) +static void ClientList_GiveMoney(const NetworkClientInfo *ci) { - if (NetworkFindClientInfo(client_no) != NULL) { - ShowNetworkGiveMoneyWindow(NetworkFindClientInfo(client_no)->client_playas); - } + ShowNetworkGiveMoneyWindow(ci->client_playas); } -static void ClientList_SpeakToClient(byte client_no) +static void ClientList_SpeakToClient(const NetworkClientInfo *ci) { - if (NetworkFindClientInfo(client_no) != NULL) { - ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, NetworkFindClientInfo(client_no)->client_id); - } + ShowNetworkChatQueryWindow(DESTTYPE_CLIENT,ci->client_id); } -static void ClientList_SpeakToCompany(byte client_no) +static void ClientList_SpeakToCompany(const NetworkClientInfo *ci) { - if (NetworkFindClientInfo(client_no) != NULL) { - ShowNetworkChatQueryWindow(DESTTYPE_TEAM, NetworkFindClientInfo(client_no)->client_playas); - } + ShowNetworkChatQueryWindow(DESTTYPE_TEAM, ci->client_playas); } -static void ClientList_SpeakToAll(byte client_no) +static void ClientList_SpeakToAll(const NetworkClientInfo *ci) { ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0); } @@ -1774,7 +1750,7 @@ struct NetworkClientListPopupWindow : Window { }; uint sel_index; - int client_no; + ClientID client_id; Point desired_location; SmallVector actions; ///< Actions to execute @@ -1790,14 +1766,14 @@ struct NetworkClientListPopupWindow : Window { 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(), - sel_index(0), client_no(client_no) + sel_index(0), client_id(client_id) { this->desired_location.x = x; 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) { this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, &ClientList_SpeakToClient); @@ -1822,7 +1798,7 @@ struct NetworkClientListPopupWindow : Window { } 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) @@ -1873,10 +1849,11 @@ struct NetworkClientListPopupWindow : Window { this->SetDirty(); } else { 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) */ -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 */ 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); } } diff --git a/src/network/network_internal.h b/src/network/network_internal.h index cd87f1e319..818773256a 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -164,7 +164,6 @@ void NetworkSyncCommandQueue(NetworkClientSocket *cs); void NetworkError(StringID error_string); void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0); uint NetworkCalculateLag(const NetworkClientSocket *cs); -NetworkClientSocket *NetworkFindClientStateFromClientID(ClientID client_id); StringID GetNetworkErrorMsg(NetworkErrorCode err); bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]); const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index cd4008c628..ab10f8b223 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -161,12 +161,6 @@ ServerNetworkGameSocketHandler::ServerNetworkGameSocketHandler(SOCKET s) : Netwo * each Socket will be associated with at most one Info object. As * such if the Socket was allocated the Info object can as well. */ 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; _network_clients_connected--; + DeleteWindowById(WC_CLIENT_LIST_POPUP, this->client_id); SetWindowDirty(WC_CLIENT_LIST, 0); this->SendPackets(true); @@ -325,7 +320,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() memset(clients, 0, sizeof(clients)); /* 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)) { 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 */ - return this->SendClientInfo(NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER)); + return this->SendClientInfo(NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER)); } NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait() @@ -495,9 +490,10 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait() NetworkClientSocket *new_cs; 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) { - 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); @@ -563,27 +559,31 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() WaitTillSaved(); /* Set the status to DONE_MAP, no we will wait for the client - * 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; + /* Find the best candidate for joining, i.e. the first joiner. */ NetworkClientSocket *new_cs; - bool new_map_client = false; - /* Check if there is a client waiting for receiving the map - * and start sending him the map */ + NetworkClientSocket *best = NULL; FOR_ALL_CLIENT_SOCKETS(new_cs) { if (new_cs->status == STATUS_MAP_WAIT) { - /* Check if we already have a new client to send the map to */ - if (!new_map_client) { - /* 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(); + 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)) { + best = new_cs; } } } + + /* 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()) { @@ -793,7 +793,6 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_JOIN) } char name[NETWORK_CLIENT_NAME_LENGTH]; - NetworkClientInfo *ci; CompanyID playas; NetworkLanguage client_lang; 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); } - 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)); ci->client_playas = playas; 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 */ this->SendConfigUpdate(); @@ -1015,18 +1016,18 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMMAND) NetworkClientInfo *ci = this->GetInfo(); 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); } 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); } 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); } @@ -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) { 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); } @@ -1176,7 +1177,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co case DESTTYPE_CLIENT: /* Are we sending to the server? */ if ((ClientID)dest == CLIENT_ID_SERVER) { - ci = NetworkFindClientInfoFromClientID(from_id); + ci = NetworkClientInfo::GetByClientID(from_id); /* Display the text locally, and that is it */ if (ci != NULL) { 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) */ if (from_id != (ClientID)dest) { if (from_id == CLIENT_ID_SERVER) { - ci = NetworkFindClientInfoFromClientID(from_id); - ci_to = NetworkFindClientInfoFromClientID((ClientID)dest); + ci = NetworkClientInfo::GetByClientID(from_id); + ci_to = NetworkClientInfo::GetByClientID((ClientID)dest); if (ci != NULL && ci_to != NULL) { 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; FOR_ALL_CLIENT_SOCKETS(cs) { 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); if (cs->client_id == from_id) show_local = false; 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); } - ci = NetworkFindClientInfoFromClientID(from_id); - ci_own = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER); + ci = NetworkClientInfo::GetByClientID(from_id); + ci_own = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER); if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) { NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data); 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); - ci = NetworkFindClientInfoFromClientID(from_id); + ci = NetworkClientInfo::GetByClientID(from_id); if (ci != NULL) { 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); break; 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 NETWORK_RECV_STATUS_OKAY; @@ -1501,7 +1502,7 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats) void NetworkUpdateClientInfo(ClientID client_id) { NetworkClientSocket *cs; - NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id); + NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); if (ci == NULL) return; @@ -1546,7 +1547,7 @@ static void NetworkAutoCleanCompanies() } 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; } @@ -1621,7 +1622,7 @@ bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]) } } /* 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 (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; } - ci = NetworkFindClientInfoFromClientID(client_id); + ci = NetworkClientInfo::GetByClientID(client_id); if (ci == NULL) return false; 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); } -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() @@ -1829,15 +1834,16 @@ void NetworkServerShowStatusToConsole() NetworkClientSocket *cs; FOR_ALL_CLIENT_SOCKETS(cs) { - uint lag = NetworkCalculateLag(cs); NetworkClientInfo *ci = cs->GetInfo(); + if (ci == NULL) continue; + uint lag = NetworkCalculateLag(cs); const char *status; 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", cs->client_id, ci->client_name, status, lag, 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 */ 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! */ 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) { SetLocalCompany(company_id); } else { - NetworkClientSocket *cs = NetworkFindClientStateFromClientID(client_id); + NetworkClientSocket *cs = NetworkClientSocket::GetByClientID(client_id); /* When the company isn't authorized we can't move them yet. */ if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return; 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) { - NetworkFindClientStateFromClientID(client_id)->SendRConResult(colour_code, string); + NetworkClientSocket::GetByClientID(client_id)->SendRConResult(colour_code, string); } static void NetworkServerSendError(ClientID client_id, NetworkErrorCode error) { - NetworkFindClientStateFromClientID(client_id)->SendError(error); + NetworkClientSocket::GetByClientID(client_id)->SendError(error); } void NetworkServerKickClient(ClientID client_id) @@ -1918,6 +1924,11 @@ void NetworkServerKickClient(ClientID client_id) 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) { /* Add address to ban-list */ @@ -1926,11 +1937,11 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban) uint n = 0; /* There can be multiple clients with the same IP, kick them all */ - NetworkClientInfo *ci; - FOR_ALL_CLIENT_INFOS(ci) { - if (ci->client_id == CLIENT_ID_SERVER) continue; - if (ci->client_address.IsInNetmask(const_cast(ip))) { - NetworkServerKickClient(ci->client_id); + NetworkClientSocket *cs; + FOR_ALL_CLIENT_SOCKETS(cs) { + if (cs->client_id == CLIENT_ID_SERVER) continue; + if (cs->client_address.IsInNetmask(const_cast(ip))) { + NetworkServerKickClient(cs->client_id); n++; } } @@ -1957,11 +1968,26 @@ void ServerNetworkGameSocketHandler::GetClientName(char *client_name, size_t siz { 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); } else { 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 */ diff --git a/src/network/network_server.h b/src/network/network_server.h index 1ea273ffa8..cd62601116 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -76,6 +76,7 @@ public: Packet *savegame_packets; ///< Packet queue of the savegame; send these "slowly" to the client. struct PacketWriter *savegame; ///< Writer used to write the savegame. 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(); @@ -115,6 +116,10 @@ public: { return "server"; } + + const char *GetClientIP(); + + static ServerNetworkGameSocketHandler *GetByClientID(ClientID client_id); }; void NetworkServer_Tick(bool send_frame); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 232382cba7..af30c5ddfd 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -35,6 +35,17 @@ static inline uint32 GetRegister(uint 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 _temp_store; + _temp_store.Store(i, 0); +} + /* List of different sprite group types */ enum SpriteGroupType { SGT_REAL, diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 83f7b03eb8..b84fbf0a31 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -114,7 +114,7 @@ uint32 GetPlatformInfo(Axis axis, byte tile, int platforms, int length, int x, i x -= platforms / 2; y -= length / 2; x = Clamp(x, -8, 7); - y = Clamp(x, -8, 7); + y = Clamp(y, -8, 7); SB(retval, 0, 4, y & 0xF); SB(retval, 4, 4, x & 0xF); } else { @@ -613,6 +613,7 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, const NewStationResolver(&object, statspec, st, tile); object.callback_param1 = 2; // Indicate we are resolving the foundation sprites + ClearRegister(0x100); group = ResolveStation(&object); if (group == NULL || group->type != SGT_RESULT) return 0; return group->GetResult() + GetRegister(0x100); diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 46f54360d2..9c4fcd1aaa 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -281,7 +281,7 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user char *p = buf; p += seprintf(p, lastof(buf), "Graphics set: %s (%u)\n", BaseGraphics::GetUsedSet()->name, BaseGraphics::GetUsedSet()->version); 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 = md5sumToString(p, lastof(buf), c->ident.md5sum); p += seprintf(p, lastof(buf), " %s\n", c->filename); diff --git a/src/window.cpp b/src/window.cpp index b45e844435..b167cbb787 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2565,7 +2565,6 @@ restart_search: w->window_class != WC_SELECT_GAME && w->window_class != WC_MAIN_TOOLBAR && w->window_class != WC_STATUS_BAR && - w->window_class != WC_TOOLBAR_MENU && w->window_class != WC_TOOLTIPS && (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 */ void HideVitalWindows() { - DeleteWindowById(WC_TOOLBAR_MENU, 0); DeleteWindowById(WC_MAIN_TOOLBAR, 0); DeleteWindowById(WC_STATUS_BAR, 0); } diff --git a/src/window_type.h b/src/window_type.h index 458ba70ae4..b456b9f4bc 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -51,7 +51,7 @@ enum WindowClass { WC_QUERY_STRING, WC_SAVELOAD, WC_SELECT_GAME, - WC_TOOLBAR_MENU, + WC_CLIENT_LIST_POPUP, WC_INCOME_GRAPH, WC_OPERATING_PROFIT, WC_TOOLTIPS,