From e62ecbff16a1470aac2bb0dc830cdf129d1fb539 Mon Sep 17 00:00:00 2001 From: glx22 Date: Sat, 24 Apr 2021 17:49:41 +0200 Subject: [PATCH 01/22] Fix: [CMake] Incorrect dependency checks for GRF --- cmake/CreateGrfCommand.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/CreateGrfCommand.cmake b/cmake/CreateGrfCommand.cmake index 4ad9734198..107ec09b88 100644 --- a/cmake/CreateGrfCommand.cmake +++ b/cmake/CreateGrfCommand.cmake @@ -35,9 +35,9 @@ function(create_grf_command) -DNFORENUM_EXECUTABLE=${NFORENUM_EXECUTABLE} -DGRFCODEC_EXECUTABLE=${GRFCODEC_EXECUTABLE} -P ${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake - MAIN_DEPENDENCY ${GRF_NFO_SOURCE_FILES} + MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake DEPENDS ${GRF_PNG_BINARY_FILES} - ${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake + ${GRF_NFO_SOURCE_FILES} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating ${GRF_SOURCE_FOLDER_NAME}.grf" ) From aca20092aadd65a764f1ea493c36f0ca507b32ff Mon Sep 17 00:00:00 2001 From: glx22 Date: Sat, 24 Apr 2021 17:52:21 +0200 Subject: [PATCH 02/22] Fix: [CMake] Check nforenum and grfcodec return value --- cmake/scripts/CreateGRF.cmake | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cmake/scripts/CreateGRF.cmake b/cmake/scripts/CreateGRF.cmake index 8631284f33..d47e39aa0e 100644 --- a/cmake/scripts/CreateGRF.cmake +++ b/cmake/scripts/CreateGRF.cmake @@ -39,6 +39,20 @@ foreach(NFO_LINE IN LISTS NFO_LINES) endif() endforeach() -execute_process(COMMAND ${NFORENUM_EXECUTABLE} -s sprites/${GRF_SOURCE_FOLDER_NAME}.nfo) -execute_process(COMMAND ${GRFCODEC_EXECUTABLE} -n -s -e -p1 ${GRF_SOURCE_FOLDER_NAME}.grf) +execute_process(COMMAND ${NFORENUM_EXECUTABLE} -s sprites/${GRF_SOURCE_FOLDER_NAME}.nfo RESULT_VARIABLE RESULT) +if(RESULT) + if(NOT RESULT MATCHES "^[0-9]*$") + message(FATAL_ERROR "Failed to run NFORenum (${RESULT}), please check NFORENUM_EXECUTABLE variable") + endif() + message(FATAL_ERROR "NFORenum failed") +endif() + +execute_process(COMMAND ${GRFCODEC_EXECUTABLE} -n -s -e -p1 ${GRF_SOURCE_FOLDER_NAME}.grf RESULT_VARIABLE RESULT) +if(RESULT) + if(NOT RESULT MATCHES "^[0-9]*$") + message(FATAL_ERROR "Failed to run GRFCodec (${RESULT}), please check GRFCODEC_EXECUTABLE variable") + endif() + message(FATAL_ERROR "GRFCodec failed") +endif() + execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${GRF_SOURCE_FOLDER_NAME}.grf ${GRF_BINARY_FILE}) From 526635942451479bee66e9eb61c50f91ae48a7dd Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 18 Apr 2021 09:54:47 +0200 Subject: [PATCH 03/22] Feature: rework in-game Online Players GUI The GUI now more clearly shows some basic information about the server you joined, your client name (and the ability to change it), and what players are in which company. It also contains useful buttons to press to join companies, chat with other people, and for admins to kick/ban people. Additionally, renamed "advertised" to "visibility"; this has to do with future additions, but also because it is more clear in wording. --- media/baseset/openttd.grf | Bin 510358 -> 510525 bytes media/baseset/openttd/openttdgui.nfo | 5 +- media/baseset/openttd/openttdgui.png | Bin 43899 -> 44464 bytes src/company_cmd.cpp | 4 +- src/lang/english.txt | 41 +- src/network/network.cpp | 5 +- src/network/network_client.cpp | 10 +- src/network/network_gui.cpp | 645 +++++++++++++++++++++------ src/network/network_server.cpp | 7 +- src/table/sprites.h | 6 +- src/toolbar_gui.cpp | 14 +- src/widgets/network_widget.h | 11 +- 12 files changed, 573 insertions(+), 175 deletions(-) diff --git a/media/baseset/openttd.grf b/media/baseset/openttd.grf index a63bfc4e295e77a34ac22387778c534dcc1f2c3d..c4511f55ea9f87c7dd7e3e4f73e79e404801d053 100644 GIT binary patch delta 217 zcmbO>S$^*nc@`Fi|92Z%T3HxdS(sW`m|Iy`wz9AqlriqzZd%6LIH$gWfsu=c0R)(V z_yzL?wii6ijEsygfW!@MW`2HtAdCM6?*Z-yybE|b%7 diff --git a/media/baseset/openttd/openttdgui.nfo b/media/baseset/openttd/openttdgui.nfo index eb1313365e..9a13fa8000 100644 --- a/media/baseset/openttd/openttdgui.nfo +++ b/media/baseset/openttd/openttdgui.nfo @@ -4,7 +4,7 @@ // See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . // -1 * 0 0C "OpenTTD GUI graphics" - -1 * 3 05 15 \b 186 // OPENTTD_SPRITE_COUNT + -1 * 3 05 15 \b 189 // OPENTTD_SPRITE_COUNT -1 sprites/openttdgui.png 8bpp 66 8 64 31 -31 7 normal -1 sprites/openttdgui.png 8bpp 146 8 64 31 -31 7 normal -1 sprites/openttdgui.png 8bpp 226 8 64 31 -31 7 normal @@ -191,3 +191,6 @@ -1 sprites/openttdgui_convert_tram.png 8bpp 24 0 32 32 0 0 normal -1 sprites/openttdgui.png 8bpp 513 440 10 10 0 0 normal -1 sprites/openttdgui.png 8bpp 526 440 10 10 0 0 normal + -1 sprites/openttdgui.png 8bpp 539 440 12 10 0 0 normal + -1 sprites/openttdgui.png 8bpp 553 440 12 10 0 0 normal + -1 sprites/openttdgui.png 8bpp 567 440 12 10 0 0 normal diff --git a/media/baseset/openttd/openttdgui.png b/media/baseset/openttd/openttdgui.png index 1fc02aa61e30774b4e69fd08b21f51ef69a74a00..dc0976a971647fa6adad1ed1506030aaf2c60bf8 100644 GIT binary patch delta 41971 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 delta 41353 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 YWbVTEdU}UG1pHhyxnf*o?EnA( diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index ab9e7e12ef..c3483a9bfe 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -571,8 +571,8 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY) GeneratePresidentName(c); SetWindowDirty(WC_GRAPH_LEGEND, 0); - SetWindowClassesDirty(WC_CLIENT_LIST_POPUP); - SetWindowDirty(WC_CLIENT_LIST, 0); + InvalidateWindowClassesData(WC_CLIENT_LIST_POPUP); + InvalidateWindowData(WC_CLIENT_LIST, 0); InvalidateWindowData(WC_LINKGRAPH_LEGEND, 0); BuildOwnerLegend(); InvalidateWindowData(WC_SMALLMAP, 0, 1); diff --git a/src/lang/english.txt b/src/lang/english.txt index ff12f122af..13cde55d95 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1991,6 +1991,9 @@ STR_FACE_TIE :Tie: STR_FACE_EARRING :Earring: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Change tie or earring +STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Private +STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Public + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Player name: @@ -2053,10 +2056,8 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}The game STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Set password STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protect your game with a password if you don't want it to be publicly accessible -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Advertised -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Choose between an advertised (internet) and a not advertised (Local Area Network, LAN) game -STR_NETWORK_START_SERVER_UNADVERTISED :No -STR_NETWORK_START_SERVER_ADVERTISED :Yes +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Visibility +STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Whether other people can see your server in the public listing STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} client{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximum number of clients: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Choose the maximum number of clients. Not all slots need to be filled @@ -2118,19 +2119,37 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Disconne STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server is protected. Enter password STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Company is protected. Enter password -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Client list # Network company list added strings -STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Client list -STR_NETWORK_COMPANY_LIST_SPECTATE :Spectate +STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Online players STR_NETWORK_COMPANY_LIST_NEW_COMPANY :New company -# Network client list +# Network client list popup for clients STR_NETWORK_CLIENTLIST_KICK :Kick STR_NETWORK_CLIENTLIST_BAN :Ban -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Speak to all -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Speak to company -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Private message + +# Network client list +STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multiplayer +STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server +STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Name +STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Name of the server you are playing on +STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Edit the name of your server +STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Name of the server +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibility +STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Whether other people can see your server in the public listing +STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Player +STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Name +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Your player name +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Edit your player name +STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Your player name +STR_NETWORK_CLIENT_LIST_PLAYER_HOST :{WHITE}(host) {BLACK}{RAW_STRING} +STR_NETWORK_CLIENT_LIST_PLAYER_SELF :{WHITE}(you) {BLACK}{RAW_STRING} +STR_NETWORK_CLIENT_LIST_ADMIN_TOOLTIP :{BLACK}Administrative actions to perform for this client +STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Join this company +STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Send a message to this player +STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Send a message to all players of this company +STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Send a message to all spectators +STR_NETWORK_CLIENT_LIST_SPECTATORS :Spectators STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client diff --git a/src/network/network.cpp b/src/network/network.cpp index 97eadb9768..1e0838684e 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -522,9 +522,10 @@ void ParseGameConnectionString(const char **company, const char **port, char *co /* Register the login */ _network_clients_connected++; - SetWindowDirty(WC_CLIENT_LIST, 0); ServerNetworkGameSocketHandler *cs = new ServerNetworkGameSocketHandler(s); cs->client_address = address; // Save the IP of the client + + InvalidateWindowData(WC_CLIENT_LIST, 0); } /** @@ -713,7 +714,7 @@ void NetworkClientConnectGame(NetworkAddress address, CompanyID join_as, const c static void NetworkInitGameInfo() { if (StrEmpty(_settings_client.network.server_name)) { - seprintf(_settings_client.network.server_name, lastof(_settings_client.network.server_name), "Unnamed Server"); + strecpy(_settings_client.network.server_name, "Unnamed Server", lastof(_settings_client.network.server_name)); } /* The server is a client too */ diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 6156dc4863..d5fe64b11d 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -647,7 +647,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac ci->client_playas = playas; strecpy(ci->client_name, name, lastof(ci->client_name)); - SetWindowDirty(WC_CLIENT_LIST, 0); + InvalidateWindowData(WC_CLIENT_LIST, 0); return NETWORK_RECV_STATUS_OKAY; } @@ -666,7 +666,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac strecpy(ci->client_name, name, lastof(ci->client_name)); - SetWindowDirty(WC_CLIENT_LIST, 0); + InvalidateWindowData(WC_CLIENT_LIST, 0); return NETWORK_RECV_STATUS_OKAY; } @@ -1043,7 +1043,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR_QUIT(Pack delete ci; } - SetWindowDirty(WC_CLIENT_LIST, 0); + InvalidateWindowData(WC_CLIENT_LIST, 0); return NETWORK_RECV_STATUS_OKAY; } @@ -1062,7 +1062,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_QUIT(Packet *p) DEBUG(net, 0, "Unknown client (%d) is leaving the game", client_id); } - SetWindowDirty(WC_CLIENT_LIST, 0); + InvalidateWindowData(WC_CLIENT_LIST, 0); /* If we come here it means we could not locate the client.. strange :s */ return NETWORK_RECV_STATUS_OKAY; @@ -1079,7 +1079,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_JOIN(Packet *p) NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name); } - SetWindowDirty(WC_CLIENT_LIST, 0); + InvalidateWindowData(WC_CLIENT_LIST, 0); return NETWORK_RECV_STATUS_OKAY; } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index dd25ad5bc1..fcfeded5a5 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -21,6 +21,7 @@ #include "network_udp.h" #include "../window_func.h" #include "../gfx_func.h" +#include "../widgets/dropdown_type.h" #include "../widgets/dropdown_func.h" #include "../querystring_gui.h" #include "../sortlist_type.h" @@ -30,6 +31,8 @@ #include "../map_type.h" #include "../guitimer_func.h" #include "../zoom_func.h" +#include "../sprite.h" +#include "../settings_internal.h" #include "../widgets/network_widget.h" @@ -38,21 +41,24 @@ #include "../stringfilter_type.h" -#include "../safeguards.h" - #ifdef __EMSCRIPTEN__ # include #endif +#include + +#include "../safeguards.h" + static void ShowNetworkStartServerWindow(); static void ShowNetworkLobbyWindow(NetworkGameList *ngl); /** - * Advertisement options in the start server window + * Visibility of the server. Public servers advertise, where private servers + * do not. */ -static const StringID _connection_types_dropdown[] = { - STR_NETWORK_START_SERVER_UNADVERTISED, - STR_NETWORK_START_SERVER_ADVERTISED, +static const StringID _server_visibility_dropdown[] = { + STR_NETWORK_SERVER_VISIBILITY_PRIVATE, + STR_NETWORK_SERVER_VISIBILITY_PUBLIC, INVALID_STRING_ID }; @@ -985,7 +991,7 @@ struct NetworkStartServerWindow : public Window { { switch (widget) { case WID_NSS_CONNTYPE_BTN: - SetDParam(0, _connection_types_dropdown[_settings_client.network.server_advertise]); + SetDParam(0, _server_visibility_dropdown[_settings_client.network.server_advertise]); break; case WID_NSS_CLIENTS_TXT: @@ -1006,7 +1012,7 @@ struct NetworkStartServerWindow : public Window { { switch (widget) { case WID_NSS_CONNTYPE_BTN: - *size = maxdim(GetStringBoundingBox(_connection_types_dropdown[0]), GetStringBoundingBox(_connection_types_dropdown[1])); + *size = maxdim(GetStringBoundingBox(_server_visibility_dropdown[0]), GetStringBoundingBox(_server_visibility_dropdown[1])); size->width += padding.width; size->height += padding.height; break; @@ -1036,7 +1042,7 @@ struct NetworkStartServerWindow : public Window { break; case WID_NSS_CONNTYPE_BTN: // Connection type - ShowDropDownMenu(this, _connection_types_dropdown, _settings_client.network.server_advertise, WID_NSS_CONNTYPE_BTN, 0, 0); // do it for widget WID_NSS_CONNTYPE_BTN + ShowDropDownMenu(this, _server_visibility_dropdown, _settings_client.network.server_advertise, WID_NSS_CONNTYPE_BTN, 0, 0); // do it for widget WID_NSS_CONNTYPE_BTN break; case WID_NSS_CLIENTS_BTND: case WID_NSS_CLIENTS_BTNU: // Click on up/down button for number of clients @@ -1175,8 +1181,8 @@ static const NWidgetPart _nested_network_start_server_window_widgets[] = { NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 6, 10), NWidget(NWID_VERTICAL), SetPIP(0, 1, 0), - NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_ADVERTISED_LABEL, STR_NULL), - NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP), + NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_VISIBILITY_LABEL, STR_NULL), + NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP), EndContainer(), NWidget(NWID_VERTICAL), SetPIP(0, 1, 0), NWidget(NWID_SPACER), SetFill(1, 1), @@ -1592,21 +1598,6 @@ static void ClientList_Ban(const NetworkClientInfo *ci) NetworkServerKickOrBanIP(ci->client_id, true, nullptr); } -static void ClientList_SpeakToClient(const NetworkClientInfo *ci) -{ - ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, ci->client_id); -} - -static void ClientList_SpeakToCompany(const NetworkClientInfo *ci) -{ - ShowNetworkChatQueryWindow(DESTTYPE_TEAM, ci->client_playas); -} - -static void ClientList_SpeakToAll(const NetworkClientInfo *ci) -{ - ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0); -} - /** Popup selection window to chose an action to perform */ struct NetworkClientListPopupWindow : Window { /** Container for actions that can be executed. */ @@ -1639,15 +1630,6 @@ struct NetworkClientListPopupWindow : Window { 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); - } - - if (Company::IsValidID(ci->client_playas) || ci->client_playas == COMPANY_SPECTATOR) { - this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, &ClientList_SpeakToCompany); - } - this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, &ClientList_SpeakToAll); - /* A server can kick clients (but not himself). */ if (_network_server && _network_own_client_id != ci->client_id) { this->AddAction(STR_NETWORK_CLIENTLIST_KICK, &ClientList_Kick); @@ -1671,7 +1653,7 @@ struct NetworkClientListPopupWindow : Window { } d.height *= (uint)this->actions.size(); - d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; + d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + 4 + 4; // Give the list a bit of padding on both sides. d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; *size = d; } @@ -1690,7 +1672,7 @@ struct NetworkClientListPopupWindow : Window { colour = TC_BLACK; } - DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, action.name, colour); + DrawString(r.left + WD_FRAMERECT_LEFT + 4, r.right - WD_FRAMERECT_RIGHT - 4, y, action.name, colour); y += FONT_HEIGHT_NORMAL; } } @@ -1731,167 +1713,554 @@ static void PopupClientList(ClientID client_id, int x, int y) static const NWidgetPart _nested_client_list_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), - NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_CLIENT_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_CL_PANEL), SetMinimalSize(250, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM), SetResize(1, 1), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CL_SERVER_SELECTOR), + NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_NETWORK_CLIENT_LIST_SERVER, STR_NULL), SetPadding(4, 4, 0, 4), SetPIP(0, 2, 0), + NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalTextLines(1, 0), SetDataTip(STR_NETWORK_CLIENT_LIST_SERVER_NAME, STR_NULL), + NWidget(NWID_SPACER), SetMinimalSize(20, 0), + NWidget(WWT_TEXT, COLOUR_GREY, WID_CL_SERVER_NAME), SetFill(1, 0), SetMinimalTextLines(1, 0), SetResize(1, 0), SetDataTip(STR_BLACK_RAW_STRING, STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP), SetAlignment(SA_VERT_CENTER | SA_RIGHT), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_CL_SERVER_NAME_EDIT), SetMinimalSize(12, 14), SetDataTip(SPR_RENAME, STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalTextLines(1, 0), SetDataTip(STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY, STR_NULL), + NWidget(NWID_SPACER), SetMinimalSize(20, 0), SetFill(1, 0), SetResize(1, 0), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_CL_SERVER_VISIBILITY), SetDataTip(STR_BLACK_STRING, STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP), + EndContainer(), + EndContainer(), + EndContainer(), + NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_NETWORK_CLIENT_LIST_PLAYER, STR_NULL), SetPadding(4, 4, 4, 4), SetPIP(0, 2, 0), + NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalTextLines(1, 0), SetDataTip(STR_NETWORK_CLIENT_LIST_PLAYER_NAME, STR_NULL), + NWidget(NWID_SPACER), SetMinimalSize(20, 0), + NWidget(WWT_TEXT, COLOUR_GREY, WID_CL_CLIENT_NAME), SetFill(1, 0), SetMinimalTextLines(1, 0), SetResize(1, 0), SetDataTip(STR_BLACK_RAW_STRING, STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP), SetAlignment(SA_VERT_CENTER | SA_RIGHT), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_CL_CLIENT_NAME_EDIT), SetMinimalSize(12, 14), SetDataTip(SPR_RENAME, STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP), + EndContainer(), + EndContainer(), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_CL_MATRIX), SetMinimalSize(180, 0), SetResize(1, 1), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_CL_SCROLLBAR), + NWidget(NWID_VERTICAL), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_CL_SCROLLBAR), + NWidget(WWT_RESIZEBOX, COLOUR_GREY), + EndContainer(), + EndContainer(), + EndContainer(), }; static WindowDesc _client_list_desc( - WDP_AUTO, "list_clients", 0, 0, + WDP_AUTO, "list_clients", 220, 300, WC_CLIENT_LIST, WC_NONE, 0, _nested_client_list_widgets, lengthof(_nested_client_list_widgets) ); +/** + * Button shown for either a company or client in the client-list. + * + * These buttons are dynamic and strongly depends on which company/client + * what buttons are available. This class allows dynamically creating them + * as the current Widget system does not. + */ +class ButtonCommon { +public: + SpriteID sprite; ///< The sprite to use on the button. + StringID tooltip; ///< The tooltip of the button. + Colours colour; ///< The colour of the button. + bool disabled; ///< Is the button disabled? + uint height; ///< Calculated height of the button. + uint width; ///< Calculated width of the button. + + ButtonCommon(SpriteID sprite, StringID tooltip, Colours colour) : + sprite(sprite), + tooltip(tooltip), + colour(colour), + disabled(false) + { + Dimension d = GetSpriteSize(sprite); + this->height = d.height + ScaleGUITrad(WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM); + this->width = d.width + ScaleGUITrad(WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT); + } + virtual ~ButtonCommon() {} + + /** + * OnClick handler for when the button is pressed. + */ + virtual void OnClick(struct NetworkClientListWindow *w, Point pt) = 0; +}; + +/** + * Template version of Button, with callback support. + */ +template +class Button : public ButtonCommon { +private: + typedef void (*ButtonCallback)(struct NetworkClientListWindow *w, Point pt, T id); ///< Callback function to call on click. + T id; ///< ID this button belongs to. + ButtonCallback proc; ///< Callback proc to call when button is pressed. + +public: + Button(SpriteID sprite, StringID tooltip, Colours colour, T id, ButtonCallback proc) : + ButtonCommon(sprite, tooltip, colour), + id(id), + proc(proc) + { + assert(proc != nullptr); + } + + void OnClick(struct NetworkClientListWindow *w, Point pt) override + { + if (this->disabled) return; + + this->proc(w, pt, this->id); + } +}; + +using CompanyButton = Button; +using ClientButton = Button; + /** * Main handle for clientlist */ struct NetworkClientListWindow : Window { - int selected_item; +private: + ClientListWidgets query_widget; ///< During a query this tracks what widget caused the query. + CompanyID join_company; ///< During query for company password, this stores what company we wanted to join. - uint server_client_width; - uint line_height; + Scrollbar *vscroll; ///< Vertical scrollbar of this window. + uint line_height; ///< Current lineheight of each entry in the matrix. + uint line_count; ///< Amount of lines in the matrix. - Dimension icon_size; + std::map>> buttons; ///< Per line which buttons are available. - NetworkClientListWindow(WindowDesc *desc, WindowNumber window_number) : - Window(desc), - selected_item(-1) + static const int CLIENT_OFFSET_LEFT = 12; ///< Offset of client entries compared to company entries. + + /** + * Chat button on a Company is clicked. + * @param w The instance of this window. + * @param pt The point where this button was clicked. + * @param company_id The company this button was assigned to. + */ + static void OnClickCompanyChat(NetworkClientListWindow *w, Point pt, CompanyID company_id) { - this->InitNested(window_number); + ShowNetworkChatQueryWindow(DESTTYPE_TEAM, company_id); } /** - * Finds the amount of clients and set the height correct + * Join button on a Company is clicked. + * @param w The instance of this window. + * @param pt The point where this button was clicked. + * @param company_id The company this button was assigned to. */ - bool CheckClientListHeight() + static void OnClickCompanyJoin(NetworkClientListWindow *w, Point pt, CompanyID company_id) { - int num = 0; + if (_network_server) { + NetworkServerDoMove(CLIENT_ID_SERVER, company_id); + MarkWholeScreenDirty(); + } else if (NetworkCompanyIsPassworded(company_id)) { + w->query_widget = WID_CL_COMPANY_JOIN; + w->join_company = company_id; + ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_PASSWORD); + } else { + NetworkClientRequestMove(company_id); + } + } - /* Should be replaced with a loop through all clients */ + /** + * Admin button on a Client is clicked. + * @param w The instance of this window. + * @param pt The point where this button was clicked. + * @param client_id The client this button was assigned to. + */ + static void OnClickClientAdmin(NetworkClientListWindow *w, Point pt, ClientID client_id) + { + PopupClientList(client_id, pt.x + w->left, pt.y + w->top); + } + + /** + * Chat button on a Client is clicked. + * @param w The instance of this window. + * @param pt The point where this button was clicked. + * @param client_id The client this button was assigned to. + */ + static void OnClickClientChat(NetworkClientListWindow *w, Point pt, ClientID client_id) + { + ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, client_id); + } + + /** + * Part of RebuildList() to create the information for a single company. + * @param company_id The company to build the list for. + * @param own_ci The NetworkClientInfo of the client itself. + */ + void RebuildListCompany(CompanyID company_id, const NetworkClientInfo *own_ci) + { + ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat); + + this->buttons[line_count].emplace_back(chat_button); + if (own_ci->client_playas != company_id) this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin)); + + this->line_count += 1; + + bool has_players = false; for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (ci->client_playas != COMPANY_INACTIVE_CLIENT) num++; + if (ci->client_playas != company_id) continue; + has_players = true; + + if (_network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat)); + if (_network_server && _network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin)); + + this->line_count += 1; } - num *= this->line_height; + chat_button->disabled = !has_players; + } - int diff = (num + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM) - (this->GetWidget(WID_CL_PANEL)->current_y); - /* If height is changed */ - if (diff != 0) { - ResizeWindow(this, 0, diff, false); - return false; + /** + * Rebuild the list, meaning: calculate the lines needed and what buttons go on which line. + */ + void RebuildList() + { + const NetworkClientInfo *own_ci = NetworkClientInfo::GetByClientID(_network_own_client_id); + + this->buttons.clear(); + this->line_count = 0; + + /* Companies */ + for (const Company *c : Company::Iterate()) { + this->RebuildListCompany(c->index, own_ci); } - return true; + + /* Spectators */ + this->RebuildListCompany(COMPANY_SPECTATOR, own_ci); + + this->vscroll->SetCount(this->line_count); + } + + /** + * Get the button at a specific point on the WID_CL_MATRIX. + * @param pt The point to look for a button. + * @return The button or a nullptr if there was none. + */ + ButtonCommon *GetButtonAtPoint(Point pt) + { + uint index = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_CL_MATRIX); + NWidgetBase *widget_matrix = this->GetWidget(WID_CL_MATRIX); + + bool rtl = _current_text_dir == TD_RTL; + uint x = rtl ? (uint)widget_matrix->pos_x + WD_FRAMERECT_LEFT : widget_matrix->current_x - WD_FRAMERECT_RIGHT; + + /* Find the buttons for this row. */ + auto button_find = this->buttons.find(index); + if (button_find == this->buttons.end()) return nullptr; + + /* Check if we want to display a tooltip for any of the buttons. */ + for (auto &button : button_find->second) { + uint left = rtl ? x : x - button->width; + uint right = rtl ? x + button->width : x; + + if (IsInsideMM(pt.x, left, right)) { + return button.get(); + } + + int width = button->width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; + x += rtl ? width : -width; + } + + return nullptr; + } + +public: + NetworkClientListWindow(WindowDesc *desc, WindowNumber window_number) : + Window(desc) + { + this->CreateNestedTree(); + this->vscroll = this->GetScrollbar(WID_CL_SCROLLBAR); + this->OnInvalidateData(); + this->FinishInitNested(window_number); + } + + void OnInvalidateData(int data = 0, bool gui_scope = true) override + { + this->RebuildList(); + + /* Currently server information is not sync'd to clients, so we cannot show it on clients. */ + this->GetWidget(WID_CL_SERVER_SELECTOR)->SetDisplayedPlane(_network_server ? 0 : SZSP_HORIZONTAL); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override { - if (widget != WID_CL_PANEL) return; + switch (widget) { + case WID_CL_SERVER_VISIBILITY: + *size = maxdim(GetStringBoundingBox(_server_visibility_dropdown[0]), GetStringBoundingBox(_server_visibility_dropdown[1])); + size->width += padding.width; + size->height += padding.height; + break; - this->server_client_width = std::max(GetStringBoundingBox(STR_NETWORK_SERVER).width, GetStringBoundingBox(STR_NETWORK_CLIENT).width) + WD_FRAMERECT_RIGHT; - this->icon_size = GetSpriteSize(SPR_COMPANY_ICON); - this->line_height = std::max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL); + case WID_CL_MATRIX: { + uint height = std::max({GetSpriteSize(SPR_COMPANY_ICON).height, GetSpriteSize(SPR_JOIN).height, GetSpriteSize(SPR_ADMIN).height, GetSpriteSize(SPR_CHAT).height}); + height += ScaleGUITrad(WD_FRAMERECT_TOP) + ScaleGUITrad(WD_FRAMERECT_BOTTOM); + this->line_height = std::max(height, (uint)FONT_HEIGHT_NORMAL) + ScaleGUITrad(WD_MATRIX_TOP + WD_MATRIX_BOTTOM); - uint width = 100; // Default width - for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - width = std::max(width, GetStringBoundingBox(ci->client_name).width); + resize->width = 1; + resize->height = this->line_height; + fill->height = this->line_height; + size->height = std::max(size->height, 5 * this->line_height); + break; + } } - - size->width = WD_FRAMERECT_LEFT + this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT + width + WD_FRAMERECT_RIGHT; } - void OnPaint() override + void OnResize() override { - /* Check if we need to reset the height */ - if (!this->CheckClientListHeight()) return; - - this->DrawWidgets(); + this->vscroll->SetCapacityFromWidget(this, WID_CL_MATRIX); } - void DrawWidget(const Rect &r, int widget) const override + void SetStringParameters(int widget) const override { - if (widget != WID_CL_PANEL) return; + switch (widget) { + case WID_CL_SERVER_NAME: + SetDParamStr(0, _settings_client.network.server_name); + break; - bool rtl = _current_text_dir == TD_RTL; - int icon_offset = (this->line_height - icon_size.height) / 2; - int text_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2; + case WID_CL_SERVER_VISIBILITY: + SetDParam(0, _server_visibility_dropdown[_settings_client.network.server_advertise]); + break; - uint y = r.top + WD_FRAMERECT_TOP; - uint left = r.left + WD_FRAMERECT_LEFT; - uint right = r.right - WD_FRAMERECT_RIGHT; - uint type_icon_width = this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT; - - - uint type_left = rtl ? right - this->server_client_width : left; - uint type_right = rtl ? right : left + this->server_client_width - 1; - uint icon_left = rtl ? right - type_icon_width + WD_FRAMERECT_LEFT : left + this->server_client_width; - uint name_left = rtl ? left : left + type_icon_width; - uint name_right = rtl ? right - type_icon_width : right; - - int i = 0; - for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - TextColour colour; - if (this->selected_item == i++) { // Selected item, highlight it - GfxFillRect(r.left + 1, y, r.right - 1, y + this->line_height - 1, PC_BLACK); - colour = TC_WHITE; - } else { - colour = TC_BLACK; - } - - if (ci->client_id == CLIENT_ID_SERVER) { - DrawString(type_left, type_right, y + text_offset, STR_NETWORK_SERVER, colour); - } else { - DrawString(type_left, type_right, y + text_offset, STR_NETWORK_CLIENT, colour); - } - - /* Filter out spectators */ - if (Company::IsValidID(ci->client_playas)) DrawCompanyIcon(ci->client_playas, icon_left, y + icon_offset); - - DrawString(name_left, name_right, y + text_offset, ci->client_name, colour); - - y += line_height; + case WID_CL_CLIENT_NAME: + SetDParamStr(0, _settings_client.network.client_name); + break; } } void OnClick(Point pt, int widget, int click_count) override { - /* Show the popup with option */ - if (this->selected_item != -1) { - int client_no = this->selected_item; - for (NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (client_no == 0) { - PopupClientList(ci->client_id, pt.x + this->left, pt.y + this->top); - break; - } - client_no--; + switch (widget) { + case WID_CL_SERVER_NAME_EDIT: + if (!_network_server) break; + + this->query_widget = WID_CL_SERVER_NAME_EDIT; + SetDParamStr(0, _settings_client.network.server_name); + ShowQueryString(STR_JUST_RAW_STRING, STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION, NETWORK_NAME_LENGTH, this, CS_ALPHANUMERAL, QSF_LEN_IN_CHARS); + break; + + case WID_CL_CLIENT_NAME_EDIT: + this->query_widget = WID_CL_CLIENT_NAME_EDIT; + SetDParamStr(0, _settings_client.network.client_name); + ShowQueryString(STR_JUST_RAW_STRING, STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION, NETWORK_CLIENT_NAME_LENGTH, this, CS_ALPHANUMERAL, QSF_LEN_IN_CHARS); + break; + + case WID_CL_SERVER_VISIBILITY: + if (!_network_server) break; + + ShowDropDownMenu(this, _server_visibility_dropdown, _settings_client.network.server_advertise, WID_CL_SERVER_VISIBILITY, 0, 0); + break; + + case WID_CL_MATRIX: { + ButtonCommon *button = this->GetButtonAtPoint(pt); + if (button == nullptr) break; + + button->OnClick(this, pt); + break; } } } - void OnMouseOver(Point pt, int widget) override + bool OnTooltip(Point pt, int widget, TooltipCloseCondition close_cond) override { - /* -1 means we left the current window */ - if (pt.y == -1) { - this->selected_item = -1; - this->SetDirty(); - return; + switch (widget) { + case WID_CL_MATRIX: { + ButtonCommon *button = this->GetButtonAtPoint(pt); + if (button == nullptr) return false; + + GuiShowTooltips(this, button->tooltip, 0, nullptr, close_cond); + return true; + }; } - /* Find the new selected item (if any) */ - pt.y -= this->GetWidget(WID_CL_PANEL)->pos_y; - int item = -1; - if (IsInsideMM(pt.y, WD_FRAMERECT_TOP, this->GetWidget(WID_CL_PANEL)->current_y - WD_FRAMERECT_BOTTOM)) { - item = (pt.y - WD_FRAMERECT_TOP) / this->line_height; + return false; + } + + void OnDropdownSelect(int widget, int index) override + { + switch (widget) { + case WID_CL_SERVER_VISIBILITY: + if (!_network_server) break; + + _settings_client.network.server_advertise = (index != 0); + break; + + default: + NOT_REACHED(); } - /* It did not change.. no update! */ - if (item == this->selected_item) return; - this->selected_item = item; - - /* Repaint */ this->SetDirty(); } + + void OnQueryTextFinished(char *str) override + { + if (str == nullptr) return; + + switch (this->query_widget) { + default: NOT_REACHED(); + + case WID_CL_SERVER_NAME_EDIT: { + if (!_network_server) break; + + uint index; + GetSettingFromName("network.server_name", &index); + SetSettingValue(index, StrEmpty(str) ? "Unnamed Server" : str); + this->InvalidateData(); + break; + } + + case WID_CL_CLIENT_NAME_EDIT: { + if (!NetworkValidateClientName(str)) break; + + uint index; + GetSettingFromName("network.client_name", &index); + SetSettingValue(index, str); + this->InvalidateData(); + break; + } + + case WID_CL_COMPANY_JOIN: + NetworkClientRequestMove(this->join_company, str); + break; + } + } + + /** + * Draw the buttons for a single line in the matrix. + * + * The x-position in RTL is the most left or otherwise the most right pixel + * we can draw the buttons from. + * + * @param x The x-position to start with the buttons. Updated during this function. + * @param y The y-position to start with the buttons. + * @param buttons The buttons to draw. + */ + void DrawButtons(uint &x, uint y, const std::vector> &buttons) const + { + for (auto &button : buttons) { + bool rtl = _current_text_dir == TD_RTL; + + uint left = rtl ? x : x - button->width; + uint right = rtl ? x + button->width : x; + + int offset = std::max(0, ((int)(this->line_height + 1) - (int)button->height) / 2); + + DrawFrameRect(left, y + offset, right, y + offset + button->height, button->colour, FR_NONE); + DrawSprite(button->sprite, PAL_NONE, left + ScaleGUITrad(WD_FRAMERECT_LEFT), y + offset + ScaleGUITrad(WD_FRAMERECT_TOP)); + if (button->disabled) { + GfxFillRect(left + 1, y + offset + 1, right - 1, y + offset + button->height - 1, _colour_gradient[button->colour & 0xF][2], FILLRECT_CHECKER); + } + + int width = button->width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; + x += rtl ? width : -width; + } + } + + /** + * Draw a company and its clients on the matrix. + * @param c The company to draw. + * @param left The most left pixel of the line. + * @param right The most right pixel of the line. + * @param top The top of the first line. + * @param line The Nth line we are drawing. Updated during this function. + */ + void DrawCompany(const Company *c, uint left, uint right, uint top, uint &line) const + { + bool rtl = _current_text_dir == TD_RTL; + int text_y_offset = std::max(0, ((int)(this->line_height + 1) - (int)FONT_HEIGHT_NORMAL) / 2) + WD_MATRIX_BOTTOM; + + Dimension d = GetSpriteSize(SPR_COMPANY_ICON); + int offset = std::max(0, ((int)(this->line_height + 1) - (int)d.height) / 2); + + uint text_left = left + (rtl ? (uint)WD_FRAMERECT_LEFT : d.width + 8); + uint text_right = right - (rtl ? d.width + 8 : (uint)WD_FRAMERECT_RIGHT); + + uint line_start = this->vscroll->GetPosition(); + uint line_end = line_start + this->vscroll->GetCapacity(); + + uint y = top + (this->line_height * (line - line_start)); + + /* Draw the company line (if in range of scrollbar). */ + if (IsInsideMM(line, line_start, line_end)) { + uint x = rtl ? text_left : text_right; + + /* If there are buttons for this company, draw them. */ + auto button_find = this->buttons.find(line); + if (button_find != this->buttons.end()) { + this->DrawButtons(x, y, button_find->second); + } + + if (c == nullptr) { + DrawSprite(SPR_COMPANY_ICON, PALETTE_TO_GREY, rtl ? right - d.width - 4 : left + 4, y + offset); + DrawString(rtl ? x : text_left, rtl ? text_right : x, y + text_y_offset, STR_NETWORK_CLIENT_LIST_SPECTATORS, TC_SILVER); + } else { + DrawCompanyIcon(c->index, rtl ? right - d.width - 4 : left + 4, y + offset); + + SetDParam(0, c->index); + SetDParam(1, c->index); + DrawString(rtl ? x : text_left, rtl ? text_right : x, y + text_y_offset, STR_COMPANY_NAME, TC_SILVER); + } + } + + y += this->line_height; + line++; + + for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { + if (c != nullptr && ci->client_playas != c->index) continue; + if (c == nullptr && ci->client_playas != COMPANY_SPECTATOR) continue; + + /* Draw the player line (if in range of scrollbar). */ + if (IsInsideMM(line, line_start, line_end)) { + uint x = rtl ? text_left : text_right; + + /* If there are buttons for this client, draw them. */ + auto button_find = this->buttons.find(line); + if (button_find != this->buttons.end()) { + this->DrawButtons(x, y, button_find->second); + } + + StringID client_string = STR_JUST_RAW_STRING; + + if (ci->client_id == CLIENT_ID_SERVER) { + client_string = STR_NETWORK_CLIENT_LIST_PLAYER_HOST; + } + if (ci->client_id == _network_own_client_id) { + client_string = STR_NETWORK_CLIENT_LIST_PLAYER_SELF; + } + + SetDParamStr(0, ci->client_name); + DrawString(rtl ? x : text_left + CLIENT_OFFSET_LEFT, rtl ? text_right - CLIENT_OFFSET_LEFT : x, y + text_y_offset, client_string, TC_BLACK); + } + + y += this->line_height; + line++; + } + } + + void DrawWidget(const Rect &r, int widget) const override + { + switch (widget) { + case WID_CL_MATRIX: { + uint line = 0; + + for (const Company *c : Company::Iterate()) { + this->DrawCompany(c, r.left, r.right, r.top, line); + } + /* Specators */ + this->DrawCompany(nullptr, r.left, r.right, r.top, line); + + break; + } + } + } }; void ShowClientList() diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index a0d1a00666..746077abdb 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -288,13 +288,14 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvSta _network_clients_connected--; DeleteWindowById(WC_CLIENT_LIST_POPUP, this->client_id); - SetWindowDirty(WC_CLIENT_LIST, 0); this->SendPackets(true); delete this->GetInfo(); delete this; + InvalidateWindowData(WC_CLIENT_LIST, 0); + return status; } @@ -1043,6 +1044,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet * this->GetClientName(client_name, lastof(client_name)); NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, nullptr, this->client_id); + InvalidateWindowData(WC_CLIENT_LIST, 0); /* Mark the client as pre-active, and wait for an ACK * so we know he is done loading and in sync with us */ @@ -2061,6 +2063,9 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id) NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN; NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1); + + InvalidateWindowClassesData(WC_CLIENT_LIST_POPUP); + InvalidateWindowData(WC_CLIENT_LIST, 0); } /** diff --git a/src/table/sprites.h b/src/table/sprites.h index 9071e61dc6..039d50b9de 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -54,7 +54,7 @@ static const SpriteID SPR_LARGE_SMALL_WINDOW = 682; /** Extra graphic spritenumbers */ static const SpriteID SPR_OPENTTD_BASE = 4896; -static const uint16 OPENTTD_SPRITE_COUNT = 186; +static const uint16 OPENTTD_SPRITE_COUNT = 189; /* Halftile-selection sprites */ static const SpriteID SPR_HALFTILE_SELECTION_FLAT = SPR_OPENTTD_BASE; @@ -166,6 +166,10 @@ static const SpriteID SPR_WINDOW_DEFSIZE = SPR_OPENTTD_BASE + 168; static const SpriteID SPR_RENAME = SPR_OPENTTD_BASE + 184; static const SpriteID SPR_GOTO_LOCATION = SPR_OPENTTD_BASE + 185; +static const SpriteID SPR_CHAT = SPR_OPENTTD_BASE + 186; +static const SpriteID SPR_ADMIN = SPR_OPENTTD_BASE + 187; +static const SpriteID SPR_JOIN = SPR_OPENTTD_BASE + 188; + static const SpriteID SPR_IMG_CARGOFLOW = SPR_OPENTTD_BASE + 174; static const SpriteID SPR_SIGNALS_BASE = SPR_OPENTTD_BASE + OPENTTD_SPRITE_COUNT; diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index ea50661e4c..6a65382b44 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -205,8 +205,7 @@ static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count /** Enum for the Company Toolbar's network related buttons */ static const int CTMN_CLIENT_LIST = -1; ///< Show the client list static const int CTMN_NEW_COMPANY = -2; ///< Create a new company -static const int CTMN_SPECTATE = -3; ///< Become spectator -static const int CTMN_SPECTATOR = -4; ///< Show a company window as spectator +static const int CTMN_SPECTATOR = -3; ///< Show a company window as spectator /** * Pop up a generic company list menu. @@ -227,8 +226,6 @@ static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0) if (_local_company == COMPANY_SPECTATOR) { list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached())); - } else { - list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached())); } break; @@ -619,15 +616,6 @@ static CallBackFunction MenuClickCompany(int index) NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company); } return CBF_NONE; - - case CTMN_SPECTATE: - if (_network_server) { - NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR); - MarkWholeScreenDirty(); - } else { - NetworkClientRequestMove(COMPANY_SPECTATOR); - } - return CBF_NONE; } } ShowCompany((CompanyID)index); diff --git a/src/widgets/network_widget.h b/src/widgets/network_widget.h index 79d33fb067..a453b085cf 100644 --- a/src/widgets/network_widget.h +++ b/src/widgets/network_widget.h @@ -96,7 +96,16 @@ enum NetworkLobbyWidgets { /** Widgets of the #NetworkClientListWindow class. */ enum ClientListWidgets { - WID_CL_PANEL, ///< Panel of the window. + WID_CL_PANEL, ///< Panel of the window. + WID_CL_SERVER_SELECTOR, ///< Selector to hide the server frame. + WID_CL_SERVER_NAME, ///< Server name. + WID_CL_SERVER_NAME_EDIT, ///< Edit button for server name. + WID_CL_SERVER_VISIBILITY, ///< Server visibility. + WID_CL_CLIENT_NAME, ///< Client name. + WID_CL_CLIENT_NAME_EDIT, ///< Edit button for client name. + WID_CL_MATRIX, ///< Company/client list. + WID_CL_SCROLLBAR, ///< Scrollbar for company/client list. + WID_CL_COMPANY_JOIN, ///< Used for QueryWindow when a company has a password. }; /** Widgets of the #NetworkClientListPopupWindow class. */ From ff708c2c659477da04fab108ca8e46a60c0d60b0 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 23 Apr 2021 01:52:57 +0200 Subject: [PATCH 04/22] Add: admin menu for companies in multiplayer games You can now easily do: - a password reset (unlock) - remove an empty company (reset company) --- src/company_cmd.cpp | 3 +- src/lang/english.txt | 12 +- src/network/network_gui.cpp | 234 +++++++++++++-------------------- src/network/network_server.cpp | 3 - src/widgets/network_widget.h | 5 - src/window_type.h | 6 - 6 files changed, 97 insertions(+), 166 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index c3483a9bfe..063d32d3f3 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -571,7 +571,6 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY) GeneratePresidentName(c); SetWindowDirty(WC_GRAPH_LEGEND, 0); - InvalidateWindowClassesData(WC_CLIENT_LIST_POPUP); InvalidateWindowData(WC_CLIENT_LIST, 0); InvalidateWindowData(WC_LINKGRAPH_LEGEND, 0); BuildOwnerLegend(); @@ -909,6 +908,8 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 CompanyAdminRemove(c_index, (CompanyRemoveReason)reason); if (StoryPage::GetNumItems() == 0 || Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0); + InvalidateWindowData(WC_CLIENT_LIST, 0); + break; } diff --git a/src/lang/english.txt b/src/lang/english.txt index 13cde55d95..a6d70e26d6 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2124,10 +2124,6 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Company STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Online players STR_NETWORK_COMPANY_LIST_NEW_COMPANY :New company -# Network client list popup for clients -STR_NETWORK_CLIENTLIST_KICK :Kick -STR_NETWORK_CLIENTLIST_BAN :Ban - # Network client list STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server @@ -2144,13 +2140,19 @@ STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Edit you STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Your player name STR_NETWORK_CLIENT_LIST_PLAYER_HOST :{WHITE}(host) {BLACK}{RAW_STRING} STR_NETWORK_CLIENT_LIST_PLAYER_SELF :{WHITE}(you) {BLACK}{RAW_STRING} -STR_NETWORK_CLIENT_LIST_ADMIN_TOOLTIP :{BLACK}Administrative actions to perform for this client +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Administrative actions to perform for this client +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Administrative actions to perform for this company STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Join this company STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Send a message to this player STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Send a message to all players of this company STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Send a message to all spectators STR_NETWORK_CLIENT_LIST_SPECTATORS :Spectators +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kick +STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Ban +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Delete +STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Password unlock + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client STR_NETWORK_SPECTATORS :Spectators diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index fcfeded5a5..ceeca633e4 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -17,6 +17,7 @@ #include "network.h" #include "network_base.h" #include "network_content.h" +#include "network_server.h" #include "../gui.h" #include "network_udp.h" #include "../window_func.h" @@ -26,6 +27,7 @@ #include "../querystring_gui.h" #include "../sortlist_type.h" #include "../company_func.h" +#include "../command_func.h" #include "../core/geometry_func.hpp" #include "../genworld.h" #include "../map_type.h" @@ -1570,146 +1572,6 @@ NetworkCompanyInfo *GetLobbyCompanyInfo(CompanyID company) extern void DrawCompanyIcon(CompanyID cid, int x, int y); -/** - * 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, WID_CLP_PANEL), EndContainer(), -}; - -static WindowDesc _client_list_popup_desc( - WDP_AUTO, nullptr, 0, 0, - WC_CLIENT_LIST_POPUP, WC_CLIENT_LIST, - 0, - _nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets) -); - -/* Here we start to define the options out of the menu */ -static void ClientList_Kick(const NetworkClientInfo *ci) -{ - NetworkServerKickClient(ci->client_id, nullptr); -} - -static void ClientList_Ban(const NetworkClientInfo *ci) -{ - NetworkServerKickOrBanIP(ci->client_id, true, nullptr); -} - -/** Popup selection window to chose an action to perform */ -struct NetworkClientListPopupWindow : Window { - /** Container for actions that can be executed. */ - struct ClientListAction { - StringID name; ///< Name of the action to execute - ClientList_Action_Proc *proc; ///< Action to execute - }; - - uint sel_index; - ClientID client_id; - Point desired_location; - std::vector actions; ///< Actions to execute - - /** - * Add an action to the list of actions to execute. - * @param name the name of the action - * @param proc the procedure to execute for the action - */ - inline void AddAction(StringID name, ClientList_Action_Proc *proc) - { - this->actions.push_back({name, proc}); - } - - NetworkClientListPopupWindow(WindowDesc *desc, int x, int y, ClientID client_id) : - Window(desc), - sel_index(0), client_id(client_id) - { - this->desired_location.x = x; - this->desired_location.y = y; - - const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); - - /* A server can kick clients (but not himself). */ - if (_network_server && _network_own_client_id != ci->client_id) { - this->AddAction(STR_NETWORK_CLIENTLIST_KICK, &ClientList_Kick); - this->AddAction(STR_NETWORK_CLIENTLIST_BAN, &ClientList_Ban); - } - - this->InitNested(client_id); - CLRBITS(this->flags, WF_WHITE_BORDER); - } - - Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override - { - return this->desired_location; - } - - void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override - { - Dimension d = *size; - for (const ClientListAction &action : this->actions) { - d = maxdim(GetStringBoundingBox(action.name), d); - } - - d.height *= (uint)this->actions.size(); - d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + 4 + 4; // Give the list a bit of padding on both sides. - d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; - *size = d; - } - - void DrawWidget(const Rect &r, int widget) const override - { - /* Draw the actions */ - int sel = this->sel_index; - int y = r.top + WD_FRAMERECT_TOP; - for (const ClientListAction &action : this->actions) { - TextColour colour; - if (sel-- == 0) { // Selected item, highlight it - GfxFillRect(r.left + 1, y, r.right - 1, y + FONT_HEIGHT_NORMAL - 1, PC_BLACK); - colour = TC_WHITE; - } else { - colour = TC_BLACK; - } - - DrawString(r.left + WD_FRAMERECT_LEFT + 4, r.right - WD_FRAMERECT_RIGHT - 4, y, action.name, colour); - y += FONT_HEIGHT_NORMAL; - } - } - - void OnMouseLoop() override - { - /* We selected an action */ - uint index = (_cursor.pos.y - this->top - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL; - - if (_left_button_down) { - if (index == this->sel_index || index >= this->actions.size()) return; - - this->sel_index = index; - this->SetDirty(); - } else { - if (index < this->actions.size() && _cursor.pos.y >= this->top) { - const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(this->client_id); - if (ci != nullptr) this->actions[index].proc(ci); - } - - DeleteWindowByClass(WC_CLIENT_LIST_POPUP); - } - } -}; - -/** - * Show the popup (action list) - */ -static void PopupClientList(ClientID client_id, int x, int y) -{ - DeleteWindowByClass(WC_CLIENT_LIST_POPUP); - - if (NetworkClientInfo::GetByClientID(client_id) == nullptr) return; - - new NetworkClientListPopupWindow(&_client_list_popup_desc, x, y, client_id); -} - static const NWidgetPart _nested_client_list_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), @@ -1758,6 +1620,17 @@ static WindowDesc _client_list_desc( _nested_client_list_widgets, lengthof(_nested_client_list_widgets) ); +/** + * The possibly entries in a DropDown for an admin. + * Client and companies are mixed; they just have to be unique. + */ +enum DropDownAdmin { + DD_CLIENT_ADMIN_KICK, + DD_CLIENT_ADMIN_BAN, + DD_COMPANY_ADMIN_RESET, + DD_COMPANY_ADMIN_UNLOCK, +}; + /** * Button shown for either a company or client in the client-list. * @@ -1774,11 +1647,11 @@ public: uint height; ///< Calculated height of the button. uint width; ///< Calculated width of the button. - ButtonCommon(SpriteID sprite, StringID tooltip, Colours colour) : + ButtonCommon(SpriteID sprite, StringID tooltip, Colours colour, bool disabled = false) : sprite(sprite), tooltip(tooltip), colour(colour), - disabled(false) + disabled(disabled) { Dimension d = GetSpriteSize(sprite); this->height = d.height + ScaleGUITrad(WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM); @@ -1803,8 +1676,8 @@ private: ButtonCallback proc; ///< Callback proc to call when button is pressed. public: - Button(SpriteID sprite, StringID tooltip, Colours colour, T id, ButtonCallback proc) : - ButtonCommon(sprite, tooltip, colour), + Button(SpriteID sprite, StringID tooltip, Colours colour, T id, ButtonCallback proc, bool disabled = false) : + ButtonCommon(sprite, tooltip, colour, disabled), id(id), proc(proc) { @@ -1830,6 +1703,9 @@ private: ClientListWidgets query_widget; ///< During a query this tracks what widget caused the query. CompanyID join_company; ///< During query for company password, this stores what company we wanted to join. + ClientID dd_client_id; ///< During admin dropdown, track which client this was for. + CompanyID dd_company_id; ///< During admin dropdown, track which company this was for. + Scrollbar *vscroll; ///< Vertical scrollbar of this window. uint line_height; ///< Current lineheight of each entry in the matrix. uint line_count; ///< Amount of lines in the matrix. @@ -1877,9 +1753,41 @@ private: */ static void OnClickClientAdmin(NetworkClientListWindow *w, Point pt, ClientID client_id) { - PopupClientList(client_id, pt.x + w->left, pt.y + w->top); + DropDownList list; + list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK, DD_CLIENT_ADMIN_KICK, false)); + list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN, DD_CLIENT_ADMIN_BAN, false)); + + Rect wi_rect; + wi_rect.left = pt.x; + wi_rect.right = pt.x; + wi_rect.top = pt.y; + wi_rect.bottom = pt.y; + + w->dd_client_id = client_id; + ShowDropDownListAt(w, std::move(list), -1, WID_CL_MATRIX, wi_rect, COLOUR_GREY, true, true); } + /** + * Admin button on a Company is clicked. + * @param w The instance of this window. + * @param pt The point where this button was clicked. + * @param company_id The company this button was assigned to. + */ + static void OnClickCompanyAdmin(NetworkClientListWindow *w, Point pt, CompanyID company_id) + { + DropDownList list; + list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET, DD_COMPANY_ADMIN_RESET, NetworkCompanyHasClients(company_id))); + list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK, DD_COMPANY_ADMIN_UNLOCK, !NetworkCompanyIsPassworded(company_id))); + + Rect wi_rect; + wi_rect.left = pt.x; + wi_rect.right = pt.x; + wi_rect.top = pt.y; + wi_rect.bottom = pt.y; + + w->dd_company_id = company_id; + ShowDropDownListAt(w, std::move(list), -1, WID_CL_MATRIX, wi_rect, COLOUR_GREY, true, true); + } /** * Chat button on a Client is clicked. * @param w The instance of this window. @@ -1900,6 +1808,7 @@ private: { ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat); + if (_network_server) this->buttons[line_count].emplace_back(new CompanyButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin)); this->buttons[line_count].emplace_back(chat_button); if (own_ci->client_playas != company_id) this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin)); @@ -1910,12 +1819,13 @@ private: if (ci->client_playas != company_id) continue; has_players = true; + if (_network_server) this->buttons[line_count].emplace_back(new ClientButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id)); if (_network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat)); - if (_network_server && _network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin)); this->line_count += 1; } + /* Disable the chat button when there are players in this company. */ chat_button->disabled = !has_players; } @@ -2084,6 +1994,14 @@ public: return false; } + void OnDropdownClose(Point pt, int widget, int index, bool instant_close) override + { + /* If you close the dropdown outside the list, don't take any action. */ + if (widget == WID_CL_MATRIX) return; + + Window::OnDropdownClose(pt, widget, index, instant_close); + } + void OnDropdownSelect(int widget, int index) override { switch (widget) { @@ -2093,6 +2011,30 @@ public: _settings_client.network.server_advertise = (index != 0); break; + case WID_CL_MATRIX: + switch (index) { + case DD_CLIENT_ADMIN_KICK: + NetworkServerKickClient(this->dd_client_id, nullptr); + break; + + case DD_CLIENT_ADMIN_BAN: + NetworkServerKickOrBanIP(this->dd_client_id, true, nullptr); + break; + + case DD_COMPANY_ADMIN_RESET: + if (NetworkCompanyHasClients(this->dd_company_id)) break; + DoCommandP(0, CCA_DELETE | this->dd_company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL); + break; + + case DD_COMPANY_ADMIN_UNLOCK: + NetworkServerSetCompanyPassword(this->dd_company_id, "", false); + break; + + default: + NOT_REACHED(); + } + break; + default: NOT_REACHED(); } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 746077abdb..f6b3e1192e 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -287,8 +287,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvSta extern byte _network_clients_connected; _network_clients_connected--; - DeleteWindowById(WC_CLIENT_LIST_POPUP, this->client_id); - this->SendPackets(true); delete this->GetInfo(); @@ -2064,7 +2062,6 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id) NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN; NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1); - InvalidateWindowClassesData(WC_CLIENT_LIST_POPUP); InvalidateWindowData(WC_CLIENT_LIST, 0); } diff --git a/src/widgets/network_widget.h b/src/widgets/network_widget.h index a453b085cf..2ed94d2849 100644 --- a/src/widgets/network_widget.h +++ b/src/widgets/network_widget.h @@ -108,11 +108,6 @@ enum ClientListWidgets { WID_CL_COMPANY_JOIN, ///< Used for QueryWindow when a company has a password. }; -/** Widgets of the #NetworkClientListPopupWindow class. */ -enum ClientListPopupWidgets { - WID_CLP_PANEL, ///< Panel of the window. -}; - /** Widgets of the #NetworkJoinStatusWindow class. */ enum NetworkJoinStatusWidgets { WID_NJS_BACKGROUND, ///< Background of the window. diff --git a/src/window_type.h b/src/window_type.h index e4b08e6e5d..2b486fbdf6 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -471,12 +471,6 @@ enum WindowClass { */ WC_CLIENT_LIST, - /** - * Popup for the client list; %Window numbers: - * - #ClientID = #ClientListPopupWidgets - */ - WC_CLIENT_LIST_POPUP, - /** * Network status window; %Window numbers: * - #WN_NETWORK_STATUS_WINDOW_JOIN = #NetworkJoinStatusWidgets From 54f69deb0c627b602da949e8c3fb5ed40daaeaa0 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 23 Apr 2021 12:55:09 +0200 Subject: [PATCH 05/22] Add: ask for confirmation on admin actions in network games --- src/lang/english.txt | 6 +++ src/network/network_gui.cpp | 80 ++++++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index a6d70e26d6..f22e9f7de4 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2153,6 +2153,12 @@ STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Ban STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Delete STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Password unlock +STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Admin action +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Are you sure you want to kick player '{RAW_STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Are you sure you want to ban player '{RAW_STRING}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Are you sure you want to delete company '{COMPANY}'? +STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Are you sure you want to reset the password of company '{COMPANY}'? + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client STR_NETWORK_SPECTATORS :Spectators diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index ceeca633e4..7aaabb3c06 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -54,6 +54,9 @@ static void ShowNetworkStartServerWindow(); static void ShowNetworkLobbyWindow(NetworkGameList *ngl); +static ClientID _admin_client_id = INVALID_CLIENT_ID; ///< For what client a confirmation window is open. +static CompanyID _admin_company_id = INVALID_COMPANY; ///< For what company a confirmation window is open. + /** * Visibility of the server. Public servers advertise, where private servers * do not. @@ -1631,6 +1634,49 @@ enum DropDownAdmin { DD_COMPANY_ADMIN_UNLOCK, }; +/** + * Callback function for admin command to kick client. + * @param w The window which initiated the confirmation dialog. + * @param confirmed Iff the user pressed Yes. + */ +static void AdminClientKickCallback(Window *w, bool confirmed) +{ + if (confirmed) NetworkServerKickClient(_admin_client_id, nullptr); +} + +/** + * Callback function for admin command to ban client. + * @param w The window which initiated the confirmation dialog. + * @param confirmed Iff the user pressed Yes. + */ +static void AdminClientBanCallback(Window *w, bool confirmed) +{ + if (confirmed) NetworkServerKickOrBanIP(_admin_client_id, true, nullptr); +} + +/** + * Callback function for admin command to reset company. + * @param w The window which initiated the confirmation dialog. + * @param confirmed Iff the user pressed Yes. + */ +static void AdminCompanyResetCallback(Window *w, bool confirmed) +{ + if (confirmed) { + if (NetworkCompanyHasClients(_admin_company_id)) return; + DoCommandP(0, CCA_DELETE | _admin_company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL); + } +} + +/** + * Callback function for admin command to unlock company. + * @param w The window which initiated the confirmation dialog. + * @param confirmed Iff the user pressed Yes. + */ +static void AdminCompanyUnlockCallback(Window *w, bool confirmed) +{ + if (confirmed) NetworkServerSetCompanyPassword(_admin_company_id, "", false); +} + /** * Button shown for either a company or client in the client-list. * @@ -2011,29 +2057,51 @@ public: _settings_client.network.server_advertise = (index != 0); break; - case WID_CL_MATRIX: + case WID_CL_MATRIX: { + StringID text = STR_NULL; + QueryCallbackProc *callback = nullptr; + switch (index) { case DD_CLIENT_ADMIN_KICK: - NetworkServerKickClient(this->dd_client_id, nullptr); + _admin_client_id = this->dd_client_id; + text = STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK; + callback = AdminClientKickCallback; + SetDParamStr(0, NetworkClientInfo::GetByClientID(_admin_client_id)->client_name); break; case DD_CLIENT_ADMIN_BAN: - NetworkServerKickOrBanIP(this->dd_client_id, true, nullptr); + _admin_client_id = this->dd_client_id; + text = STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN; + callback = AdminClientBanCallback; + SetDParamStr(0, NetworkClientInfo::GetByClientID(_admin_client_id)->client_name); break; case DD_COMPANY_ADMIN_RESET: - if (NetworkCompanyHasClients(this->dd_company_id)) break; - DoCommandP(0, CCA_DELETE | this->dd_company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL); + _admin_company_id = this->dd_company_id; + text = STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET; + callback = AdminCompanyResetCallback; + SetDParam(0, _admin_company_id); break; case DD_COMPANY_ADMIN_UNLOCK: - NetworkServerSetCompanyPassword(this->dd_company_id, "", false); + _admin_company_id = this->dd_company_id; + text = STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK; + callback = AdminCompanyUnlockCallback; + SetDParam(0, _admin_company_id); break; default: NOT_REACHED(); } + + assert(text != STR_NULL); + assert(callback != nullptr); + + /* Always ask confirmation for all admin actions. */ + ShowQuery(STR_NETWORK_CLIENT_LIST_ASK_CAPTION, text, this, callback); + break; + } default: NOT_REACHED(); From c2e116a3d3240daf6f1f27a0847efe10a0489adc Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 23 Apr 2021 15:01:02 +0200 Subject: [PATCH 06/22] Change: track hover position on Online Players GUI Especially if there are many players online, trying to chat with the right one can be a visual challenge. This can be solved by highlighting the row you are on. This visual cue is often enough for humans to find the right row. --- src/network/network_gui.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 7aaabb3c06..6eac3e8d7e 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1755,6 +1755,7 @@ private: Scrollbar *vscroll; ///< Vertical scrollbar of this window. uint line_height; ///< Current lineheight of each entry in the matrix. uint line_count; ///< Amount of lines in the matrix. + int hover_index; ///< Index of the current line we are hovering over, or -1 if none. std::map>> buttons; ///< Per line which buttons are available. @@ -2261,6 +2262,11 @@ public: case WID_CL_MATRIX: { uint line = 0; + if (this->hover_index >= 0) { + uint offset = this->hover_index * this->line_height; + GfxFillRect(r.left + 2, r.top + offset, r.right - 1, r.top + offset + this->line_height - 1, GREY_SCALE(9)); + } + for (const Company *c : Company::Iterate()) { this->DrawCompany(c, r.left, r.right, r.top, line); } @@ -2271,6 +2277,24 @@ public: } } } + + virtual void OnMouseLoop() override + { + if (GetWidgetFromPos(this, _cursor.pos.x - this->left, _cursor.pos.y - this->top) != WID_CL_MATRIX) { + this->hover_index = -1; + this->SetDirty(); + return; + } + + NWidgetBase *nwi = this->GetWidget(WID_CL_MATRIX); + int y = _cursor.pos.y - this->top - nwi->pos_y - 2; + int index = y / this->line_height; + + if (index != this->hover_index) { + this->hover_index = index; + this->SetDirty(); + } + } }; void ShowClientList() From a924b2ff81844c8d43ad1eaa25dea9642815738c Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 23 Apr 2021 16:22:01 +0200 Subject: [PATCH 07/22] Add: move "New Company" inside the Online Players GUI --- src/lang/english.txt | 3 +- src/network/network_gui.cpp | 62 ++++++++++++++++++++++++++++++------- src/toolbar_gui.cpp | 15 +-------- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index f22e9f7de4..33ccca2a41 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2122,7 +2122,6 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Company # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Online players -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :New company # Network client list STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multiplayer @@ -2147,6 +2146,8 @@ STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Send a m STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Send a message to all players of this company STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Send a message to all spectators STR_NETWORK_CLIENT_LIST_SPECTATORS :Spectators +STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(New company) +STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Create a new company and join it STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kick STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Ban diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 6eac3e8d7e..e76500f091 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1792,6 +1792,21 @@ private: } } + /** + * Crete new company button is clicked. + * @param w The instance of this window. + * @param pt The point where this button was clicked. + * @param company_id The company this button was assigned to. + */ + static void OnClickCompanyNew(NetworkClientListWindow *w, Point pt, CompanyID company_id) + { + if (_network_server) { + DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL); + } else { + NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company); + } + } + /** * Admin button on a Client is clicked. * @param w The instance of this window. @@ -1886,8 +1901,20 @@ private: this->buttons.clear(); this->line_count = 0; + /* As spectator, show a line to create a new company. */ + if (own_ci->client_playas == COMPANY_SPECTATOR && !NetworkMaxCompaniesReached()) { + this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP, COLOUR_ORANGE, COMPANY_SPECTATOR, &NetworkClientListWindow::OnClickCompanyNew)); + this->line_count += 1; + } + + if (own_ci->client_playas != COMPANY_SPECTATOR) { + this->RebuildListCompany(own_ci->client_playas, own_ci); + } + /* Companies */ for (const Company *c : Company::Iterate()) { + if (c->index == own_ci->client_playas) continue; + this->RebuildListCompany(c->index, own_ci); } @@ -2177,13 +2204,13 @@ public: /** * Draw a company and its clients on the matrix. - * @param c The company to draw. + * @param company_id The company to draw. * @param left The most left pixel of the line. * @param right The most right pixel of the line. * @param top The top of the first line. * @param line The Nth line we are drawing. Updated during this function. */ - void DrawCompany(const Company *c, uint left, uint right, uint top, uint &line) const + void DrawCompany(CompanyID company_id, uint left, uint right, uint top, uint &line) const { bool rtl = _current_text_dir == TD_RTL; int text_y_offset = std::max(0, ((int)(this->line_height + 1) - (int)FONT_HEIGHT_NORMAL) / 2) + WD_MATRIX_BOTTOM; @@ -2209,14 +2236,17 @@ public: this->DrawButtons(x, y, button_find->second); } - if (c == nullptr) { + if (company_id == COMPANY_SPECTATOR) { DrawSprite(SPR_COMPANY_ICON, PALETTE_TO_GREY, rtl ? right - d.width - 4 : left + 4, y + offset); DrawString(rtl ? x : text_left, rtl ? text_right : x, y + text_y_offset, STR_NETWORK_CLIENT_LIST_SPECTATORS, TC_SILVER); + } else if (company_id == COMPANY_NEW_COMPANY) { + DrawSprite(SPR_COMPANY_ICON, PALETTE_TO_GREY, rtl ? right - d.width - 4 : left + 4, y + offset); + DrawString(rtl ? x : text_left, rtl ? text_right : x, y + text_y_offset, STR_NETWORK_CLIENT_LIST_NEW_COMPANY, TC_WHITE); } else { - DrawCompanyIcon(c->index, rtl ? right - d.width - 4 : left + 4, y + offset); + DrawCompanyIcon(company_id, rtl ? right - d.width - 4 : left + 4, y + offset); - SetDParam(0, c->index); - SetDParam(1, c->index); + SetDParam(0, company_id); + SetDParam(1, company_id); DrawString(rtl ? x : text_left, rtl ? text_right : x, y + text_y_offset, STR_COMPANY_NAME, TC_SILVER); } } @@ -2225,8 +2255,7 @@ public: line++; for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (c != nullptr && ci->client_playas != c->index) continue; - if (c == nullptr && ci->client_playas != COMPANY_SPECTATOR) continue; + if (ci->client_playas != company_id) continue; /* Draw the player line (if in range of scrollbar). */ if (IsInsideMM(line, line_start, line_end)) { @@ -2267,11 +2296,22 @@ public: GfxFillRect(r.left + 2, r.top + offset, r.right - 1, r.top + offset + this->line_height - 1, GREY_SCALE(9)); } - for (const Company *c : Company::Iterate()) { - this->DrawCompany(c, r.left, r.right, r.top, line); + NetworkClientInfo *own_ci = NetworkClientInfo::GetByClientID(_network_own_client_id); + if (own_ci->client_playas == COMPANY_SPECTATOR && !NetworkMaxCompaniesReached()) { + this->DrawCompany(COMPANY_NEW_COMPANY, r.left, r.right, r.top, line); } + + if (own_ci->client_playas != COMPANY_SPECTATOR) { + this->DrawCompany(own_ci->client_playas, r.left, r.right, r.top, line); + } + + for (const Company *c : Company::Iterate()) { + if (own_ci->client_playas == c->index) continue; + this->DrawCompany(c->index, r.left, r.right, r.top, line); + } + /* Specators */ - this->DrawCompany(nullptr, r.left, r.right, r.top, line); + this->DrawCompany(COMPANY_SPECTATOR, r.left, r.right, r.top, line); break; } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 6a65382b44..fc8b183470 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -204,8 +204,7 @@ static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count /** Enum for the Company Toolbar's network related buttons */ static const int CTMN_CLIENT_LIST = -1; ///< Show the client list -static const int CTMN_NEW_COMPANY = -2; ///< Create a new company -static const int CTMN_SPECTATOR = -3; ///< Show a company window as spectator +static const int CTMN_SPECTATOR = -2; ///< Show a company window as spectator /** * Pop up a generic company list menu. @@ -223,10 +222,6 @@ static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0) /* Add the client list button for the companies menu */ list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false)); - - if (_local_company == COMPANY_SPECTATOR) { - list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached())); - } break; case WID_TN_STORY: @@ -608,14 +603,6 @@ static CallBackFunction MenuClickCompany(int index) case CTMN_CLIENT_LIST: ShowClientList(); return CBF_NONE; - - case CTMN_NEW_COMPANY: - if (_network_server) { - DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL); - } else { - NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, nullptr, _local_company); - } - return CBF_NONE; } } ShowCompany((CompanyID)index); From fda1a590f6978f906ed21b6732f80c9aefa02b47 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 24 Apr 2021 13:06:59 +0200 Subject: [PATCH 08/22] Change: use icons to indicate you/host in Online Players GUI --- media/baseset/openttd.grf | Bin 510525 -> 510635 bytes media/baseset/openttd/openttdgui.nfo | 4 +- media/baseset/openttd/openttdgui.png | Bin 44464 -> 44530 bytes src/lang/english.txt | 4 +- src/network/network_gui.cpp | 60 +++++++++++++++++++++++---- src/table/sprites.h | 4 +- 6 files changed, 59 insertions(+), 13 deletions(-) diff --git a/media/baseset/openttd.grf b/media/baseset/openttd.grf index c4511f55ea9f87c7dd7e3e4f73e79e404801d053..837e4b12d2553699331ad6ba878d38afda6aa109 100644 GIT binary patch delta 176 zcmdlxMSk^Ec@`Fi|MweNT3HxdS(sW`m|Iy`wz9Aqlriq#Zd%5wF}FU4fsu=g0R)(V z_yzL?HdY1(Mn=XHoXq_E{1>=4aBUFj&^Tat!FU7L0TE2q3wTaQFfu-1xxvB6_<|Wo zvokUBKVW5Kc)`xZ&;Nqu0oM!82Rs|NZfHEvVPq6!_|M~*SyYf;RH9H&lv. // -1 * 0 0C "OpenTTD GUI graphics" - -1 * 3 05 15 \b 189 // OPENTTD_SPRITE_COUNT + -1 * 3 05 15 \b 191 // OPENTTD_SPRITE_COUNT -1 sprites/openttdgui.png 8bpp 66 8 64 31 -31 7 normal -1 sprites/openttdgui.png 8bpp 146 8 64 31 -31 7 normal -1 sprites/openttdgui.png 8bpp 226 8 64 31 -31 7 normal @@ -194,3 +194,5 @@ -1 sprites/openttdgui.png 8bpp 539 440 12 10 0 0 normal -1 sprites/openttdgui.png 8bpp 553 440 12 10 0 0 normal -1 sprites/openttdgui.png 8bpp 567 440 12 10 0 0 normal + -1 sprites/openttdgui.png 8bpp 581 440 10 10 0 0 normal + -1 sprites/openttdgui.png 8bpp 593 440 10 10 0 0 normal diff --git a/media/baseset/openttd/openttdgui.png b/media/baseset/openttd/openttdgui.png index dc0976a971647fa6adad1ed1506030aaf2c60bf8..5b80c3326047f00565f11a27cc8cad879228a9f1 100644 GIT binary patch delta 19226 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 y^XIE!y#d4kV#J66#E20Ch!G>> buttons; ///< Per line which buttons are available. @@ -1870,7 +1872,7 @@ private: { ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat); - if (_network_server) this->buttons[line_count].emplace_back(new CompanyButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin)); + if (_network_server) this->buttons[line_count].emplace_back(new CompanyButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin, company_id == COMPANY_SPECTATOR)); this->buttons[line_count].emplace_back(chat_button); if (own_ci->client_playas != company_id) this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin)); @@ -1884,6 +1886,12 @@ private: if (_network_server) this->buttons[line_count].emplace_back(new ClientButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id)); if (_network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat)); + if (ci->client_id == _network_own_client_id) { + this->player_self_index = this->line_count; + } else if (ci->client_id == CLIENT_ID_SERVER) { + this->player_host_index = this->line_count; + } + this->line_count += 1; } @@ -1900,6 +1908,8 @@ private: this->buttons.clear(); this->line_count = 0; + this->player_host_index = -1; + this->player_self_index = -1; /* As spectator, show a line to create a new company. */ if (own_ci->client_playas == COMPANY_SPECTATOR && !NetworkMaxCompaniesReached()) { @@ -1959,7 +1969,10 @@ private: public: NetworkClientListWindow(WindowDesc *desc, WindowNumber window_number) : - Window(desc) + Window(desc), + hover_index(-1), + player_self_index(-1), + player_host_index(-1) { this->CreateNestedTree(); this->vscroll = this->GetScrollbar(WID_CL_SCROLLBAR); @@ -2057,6 +2070,30 @@ public: { switch (widget) { case WID_CL_MATRIX: { + int index = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_CL_MATRIX); + + bool rtl = _current_text_dir == TD_RTL; + NWidgetBase *widget_matrix = this->GetWidget(WID_CL_MATRIX); + + Dimension d = GetSpriteSize(SPR_COMPANY_ICON); + uint text_left = widget_matrix->pos_x + (rtl ? (uint)WD_FRAMERECT_LEFT : d.width + 8); + uint text_right = widget_matrix->pos_x + widget_matrix->current_x - (rtl ? d.width + 8 : (uint)WD_FRAMERECT_RIGHT); + + Dimension d2 = GetSpriteSize(SPR_PLAYER_SELF); + uint offset_x = CLIENT_OFFSET_LEFT - d2.width - 3; + + uint player_icon_x = rtl ? text_right - offset_x - d2.width : text_left + offset_x; + + if (IsInsideMM(pt.x, player_icon_x, player_icon_x + d2.width)) { + if (index == this->player_self_index) { + GuiShowTooltips(this, STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP, 0, nullptr, close_cond); + return true; + } else if (index == this->player_host_index) { + GuiShowTooltips(this, STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP, 0, nullptr, close_cond); + return true; + } + } + ButtonCommon *button = this->GetButtonAtPoint(pt); if (button == nullptr) return false; @@ -2267,17 +2304,22 @@ public: this->DrawButtons(x, y, button_find->second); } - StringID client_string = STR_JUST_RAW_STRING; - - if (ci->client_id == CLIENT_ID_SERVER) { - client_string = STR_NETWORK_CLIENT_LIST_PLAYER_HOST; - } + SpriteID player_icon = 0; if (ci->client_id == _network_own_client_id) { - client_string = STR_NETWORK_CLIENT_LIST_PLAYER_SELF; + player_icon = SPR_PLAYER_SELF; + } else if (ci->client_id == CLIENT_ID_SERVER) { + player_icon = SPR_PLAYER_HOST; + } + + if (player_icon != 0) { + Dimension d2 = GetSpriteSize(player_icon); + uint offset_x = CLIENT_OFFSET_LEFT - 3; + int offset_y = std::max(0, ((int)(this->line_height + 1) - (int)d2.height) / 2); + DrawSprite(player_icon, PALETTE_TO_GREY, rtl ? text_right - offset_x : text_left + offset_x - d2.width, y + offset_y); } SetDParamStr(0, ci->client_name); - DrawString(rtl ? x : text_left + CLIENT_OFFSET_LEFT, rtl ? text_right - CLIENT_OFFSET_LEFT : x, y + text_y_offset, client_string, TC_BLACK); + DrawString(rtl ? x : text_left + CLIENT_OFFSET_LEFT, rtl ? text_right - CLIENT_OFFSET_LEFT : x, y + text_y_offset, STR_JUST_RAW_STRING, TC_BLACK); } y += this->line_height; diff --git a/src/table/sprites.h b/src/table/sprites.h index 039d50b9de..b7bb910203 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -54,7 +54,7 @@ static const SpriteID SPR_LARGE_SMALL_WINDOW = 682; /** Extra graphic spritenumbers */ static const SpriteID SPR_OPENTTD_BASE = 4896; -static const uint16 OPENTTD_SPRITE_COUNT = 189; +static const uint16 OPENTTD_SPRITE_COUNT = 191; /* Halftile-selection sprites */ static const SpriteID SPR_HALFTILE_SELECTION_FLAT = SPR_OPENTTD_BASE; @@ -169,6 +169,8 @@ static const SpriteID SPR_GOTO_LOCATION = SPR_OPENTTD_BASE + 185; static const SpriteID SPR_CHAT = SPR_OPENTTD_BASE + 186; static const SpriteID SPR_ADMIN = SPR_OPENTTD_BASE + 187; static const SpriteID SPR_JOIN = SPR_OPENTTD_BASE + 188; +static const SpriteID SPR_PLAYER_SELF = SPR_OPENTTD_BASE + 189; +static const SpriteID SPR_PLAYER_HOST = SPR_OPENTTD_BASE + 190; static const SpriteID SPR_IMG_CARGOFLOW = SPR_OPENTTD_BASE + 174; From fbc232569c149518911ca66fa8d71e2ef2183439 Mon Sep 17 00:00:00 2001 From: PeterN Date: Sat, 24 Apr 2021 22:27:47 +0100 Subject: [PATCH 09/22] Fix #9097: Upper 16 bits of cargo base payment rate were discarded. (#9098) NewGRF spec says that base payment rate is 32 bits, but it was loaded into a 16 bit variable. This value is loaded into Money variable after inflation is applied. --- src/cargotype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cargotype.h b/src/cargotype.h index 9645bf7c59..f6b3eaead5 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -59,7 +59,7 @@ struct CargoSpec { uint8 rating_colour; uint8 weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg). uint16 multiplier; ///< Capacity multiplier for vehicles. (8 fractional bits) - uint16 initial_payment; + uint32 initial_payment; ///< Initial payment rate before inflation is applied. uint8 transit_days[2]; bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier). From f4d5c8d99e9071efc54483f44b74a6d3c2a05214 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 25 Apr 2021 00:43:38 +0200 Subject: [PATCH 10/22] Fix: [OpenGL] Main loop expects to start with the video buffer unmapped. (#9100) --- src/video/opengl.cpp | 1 + src/video/sdl2_opengl_v.cpp | 2 ++ src/video/win32_v.cpp | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 1eab9b10e3..ecafeb6138 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -1154,6 +1154,7 @@ void *OpenGLBackend::GetVideoBuffer() #endif if (!this->persistent_mapping_supported) { + assert(this->vid_buffer == nullptr); _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo); this->vid_buffer = _glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE); } else if (this->vid_buffer == nullptr) { diff --git a/src/video/sdl2_opengl_v.cpp b/src/video/sdl2_opengl_v.cpp index 9c84c36b1c..003e194380 100644 --- a/src/video/sdl2_opengl_v.cpp +++ b/src/video/sdl2_opengl_v.cpp @@ -74,6 +74,8 @@ const char *VideoDriver_SDL_OpenGL::Start(const StringList ¶m) this->Stop(); return "Can't get pointer to screen buffer"; } + /* Main loop expects to start with the buffer unmapped. */ + this->ReleaseVideoPointer(); return nullptr; } diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 1dc1db8cef..f0291db714 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -1311,6 +1311,8 @@ const char *VideoDriver_Win32OpenGL::Start(const StringList ¶m) _cur_resolution = old_res; return "Can't get pointer to screen buffer"; } + /* Main loop expects to start with the buffer unmapped. */ + this->ReleaseVideoPointer(); MarkWholeScreenDirty(); From 9d6ff1c780462bed9b1441571919c262f40df3a4 Mon Sep 17 00:00:00 2001 From: 2TallTyler Date: Fri, 9 Apr 2021 21:45:44 -0400 Subject: [PATCH 11/22] Fix: Missing 'Town names:' colon in map gen GUI --- src/lang/english.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index dbf0a82d0f..46a8492c9f 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -953,7 +953,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malaysian Ringg STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Drive on left STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Drive on right -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Town names +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Town names: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Select style of town names ############ start of townname region From f158957a4e9d7fab39e35b5dc3b5e31882d4da52 Mon Sep 17 00:00:00 2001 From: PeterN Date: Sun, 25 Apr 2021 17:51:03 +0100 Subject: [PATCH 12/22] Fix: Use width of tiny arrow string instead of scaled pixels in ship/aircraft list. (#9102) --- src/vehicle_gui.cpp | 21 +++++++++++++-------- src/vehicle_gui_base.h | 3 +++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index aa28938248..f4b5185865 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -240,6 +240,11 @@ Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bo return d; } +void BaseVehicleListWindow::OnInit() +{ + this->order_arrow_width = GetStringBoundingBox(STR_TINY_RIGHT_ARROW).width; +} + /** * Display the Action dropdown window. * @param show_autoreplace If true include the autoreplace item. @@ -1406,14 +1411,14 @@ static const NWidgetPart _nested_vehicle_list[] = { EndContainer(), }; -static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, VehicleOrderID start = 0) +static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, uint order_arrow_width, VehicleOrderID start) { const Order *order = v->GetOrder(start); if (order == nullptr) return; bool rtl = _current_text_dir == TD_RTL; - int l_offset = rtl ? 0 : ScaleGUITrad(6); - int r_offset = rtl ? ScaleGUITrad(6) : 0; + int l_offset = rtl ? 0 : order_arrow_width; + int r_offset = rtl ? order_arrow_width : 0; int i = 0; VehicleOrderID oid = start; @@ -1438,11 +1443,11 @@ static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, Veh } /** Draw small order list in the vehicle GUI, but without the little black arrow. This is used for shared order groups. */ -static void DrawSmallOrderList(const Order *order, int left, int right, int y) +static void DrawSmallOrderList(const Order *order, int left, int right, int y, uint order_arrow_width) { bool rtl = _current_text_dir == TD_RTL; - int l_offset = rtl ? 0 : ScaleGUITrad(6); - int r_offset = rtl ? ScaleGUITrad(6) : 0; + int l_offset = rtl ? 0 : order_arrow_width; + int r_offset = rtl ? order_arrow_width : 0; int i = 0; while (order != nullptr) { if (order->IsType(OT_GOTO_STATION)) { @@ -1550,7 +1555,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int DrawString(text_left, text_right, y, STR_TINY_GROUP, TC_BLACK); } - if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, v->cur_real_order_index); + if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, this->order_arrow_width, v->cur_real_order_index); StringID str; if (v->IsChainInDepot()) { @@ -1572,7 +1577,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int DrawVehicleImage(vehgroup.vehicles_begin[i], image_left + 8 * i, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0); } - if (show_orderlist) DrawSmallOrderList((vehgroup.vehicles_begin[0])->GetFirstOrder(), orderlist_left, orderlist_right, y); + if (show_orderlist) DrawSmallOrderList((vehgroup.vehicles_begin[0])->GetFirstOrder(), orderlist_left, orderlist_right, y, this->order_arrow_width); SetDParam(0, vehgroup.NumVehicles()); DrawString(left, right, y + 2, STR_BLACK_COMMA); diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h index 4bbfbf2a80..d724bc3433 100644 --- a/src/vehicle_gui_base.h +++ b/src/vehicle_gui_base.h @@ -83,6 +83,7 @@ struct BaseVehicleListWindow : public Window { byte unitnumber_digits; ///< The number of digits of the highest unit number. Scrollbar *vscroll; VehicleListIdentifier vli; ///< Identifier of the vehicle list we want to currently show. + uint order_arrow_width; ///< Width of the arrow in the small order list. typedef GUIVehicleGroupList::SortFunction VehicleGroupSortFunction; typedef GUIVehicleList::SortFunction VehicleIndividualSortFunction; @@ -104,6 +105,8 @@ struct BaseVehicleListWindow : public Window { BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno); + void OnInit() override; + void UpdateSortingFromGrouping(); void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const; From 65818db1f4332fecb9395df2e41f2068bb86feeb Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 25 Apr 2021 17:53:24 +0200 Subject: [PATCH 13/22] Fix: [Network] Prevent stalling save game transfer when compression is slow --- src/network/network_server.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index f6b3e1192e..5489db8480 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -592,7 +592,7 @@ void ServerNetworkGameSocketHandler::CheckNextClientToSendMap(NetworkClientSocke /** This sends the map to the client */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() { - static uint sent_packets; // How many packets we did send successfully last time + static uint16 sent_packets; // How many packets we did send successfully last time if (this->status < STATUS_AUTHORIZED) { /* Illegal call, return error and ignore the packet */ @@ -652,8 +652,10 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() return NETWORK_RECV_STATUS_CONN_LOST; case SPS_ALL_SENT: - /* All are sent, increase the sent_packets */ - if (has_packets) sent_packets *= 2; + /* All are sent, increase the sent_packets but do not overflow! */ + if (has_packets && sent_packets < std::numeric_limits::max() / 2) { + sent_packets *= 2; + } break; case SPS_PARTLY_SENT: From b721787c7fafbff040fbcaa188a9d5dd7557e26f Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 25 Apr 2021 18:04:52 +0000 Subject: [PATCH 14/22] Update: Translations from eints norwegian (bokmal): 4 changes by Anolitt spanish (mexican): 3 changes by absay japanese: 60 changes by scabtert, 38 changes by Azusa257 english (us): 3 changes by 2TallTyler korean: 3 changes by telk5093 russian: 4 changes by Ln-Wolf finnish: 3 changes by hpiirai slovak: 20 changes by FuryPapaya --- src/lang/afrikaans.txt | 15 +--- src/lang/arabic_egypt.txt | 10 +-- src/lang/basque.txt | 12 +--- src/lang/belarusian.txt | 15 +--- src/lang/brazilian_portuguese.txt | 15 +--- src/lang/bulgarian.txt | 14 +--- src/lang/catalan.txt | 15 +--- src/lang/chuvash.txt | 3 + src/lang/croatian.txt | 15 +--- src/lang/czech.txt | 15 +--- src/lang/danish.txt | 15 +--- src/lang/dutch.txt | 15 +--- src/lang/english_AU.txt | 14 +--- src/lang/english_US.txt | 18 ++--- src/lang/esperanto.txt | 10 +-- src/lang/estonian.txt | 15 +--- src/lang/faroese.txt | 12 +--- src/lang/finnish.txt | 18 ++--- src/lang/french.txt | 15 +--- src/lang/frisian.txt | 13 +--- src/lang/gaelic.txt | 14 +--- src/lang/galician.txt | 15 +--- src/lang/german.txt | 15 +--- src/lang/greek.txt | 15 +--- src/lang/hebrew.txt | 14 +--- src/lang/hindi.txt | 4 +- src/lang/hungarian.txt | 15 +--- src/lang/icelandic.txt | 10 +-- src/lang/ido.txt | 3 + src/lang/indonesian.txt | 15 +--- src/lang/irish.txt | 14 +--- src/lang/italian.txt | 15 +--- src/lang/japanese.txt | 115 ++++++++++++++++++++++++++---- src/lang/korean.txt | 18 ++--- src/lang/latin.txt | 15 +--- src/lang/latvian.txt | 15 +--- src/lang/lithuanian.txt | 15 +--- src/lang/luxembourgish.txt | 15 +--- src/lang/macedonian.txt | 3 + src/lang/malay.txt | 11 +-- src/lang/maltese.txt | 3 + src/lang/marathi.txt | 3 + src/lang/norwegian_bokmal.txt | 19 ++--- src/lang/norwegian_nynorsk.txt | 14 +--- src/lang/persian.txt | 13 +--- src/lang/polish.txt | 15 +--- src/lang/portuguese.txt | 15 +--- src/lang/romanian.txt | 14 +--- src/lang/russian.txt | 20 ++---- src/lang/serbian.txt | 15 +--- src/lang/simplified_chinese.txt | 15 +--- src/lang/slovak.txt | 55 ++++++-------- src/lang/slovenian.txt | 14 +--- src/lang/spanish.txt | 15 +--- src/lang/spanish_MX.txt | 18 ++--- src/lang/swedish.txt | 15 +--- src/lang/tamil.txt | 14 +--- src/lang/thai.txt | 14 +--- src/lang/traditional_chinese.txt | 14 +--- src/lang/turkish.txt | 15 +--- src/lang/ukrainian.txt | 15 +--- src/lang/urdu.txt | 10 +-- src/lang/vietnamese.txt | 15 +--- src/lang/welsh.txt | 14 +--- 64 files changed, 330 insertions(+), 674 deletions(-) diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt index cf3d05321e..4390a75a0d 100644 --- a/src/lang/afrikaans.txt +++ b/src/lang/afrikaans.txt @@ -1915,6 +1915,7 @@ STR_FACE_TIE :Das: STR_FACE_EARRING :Oorbel: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Verander das of oorbel + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multispeler STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Speler naam: @@ -1973,10 +1974,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Die spel STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Stel wagwoord STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beskerm jou spel met 'n wagwoord as jy wil dit nie publieke toepassing laat wees nie -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Openbaar -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Kies tussen 'n openbare (internet) of 'n plaaslike (LAN) spel -STR_NETWORK_START_SERVER_UNADVERTISED :Nee -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} Klient{P "" e} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maksimum aantal kliënte: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Kies die maksimum aantal kliënte. Alle posisies hoef nie vol te wees nie @@ -2038,19 +2035,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Loskoppe STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Verskaffer is beskerm. Voer wagwoord in STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Maatskappy is beskerm. Voer wagwoord in -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Kliëntelys # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Klient Lys -STR_NETWORK_COMPANY_LIST_SPECTATE :Toeskou -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nuwe maatskapy # Network client list -STR_NETWORK_CLIENTLIST_KICK :Skop -STR_NETWORK_CLIENTLIST_BAN :Verbod -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Praat met almal -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Praat met maatskappy -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privaate boodskap + + STR_NETWORK_SERVER :Verskaffer STR_NETWORK_CLIENT :Klient diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt index 61bb91a186..eb9abb14ea 100644 --- a/src/lang/arabic_egypt.txt +++ b/src/lang/arabic_egypt.txt @@ -1611,6 +1611,7 @@ STR_FACE_TIE :الربطة: STR_FACE_EARRING :أقراط الأذان: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}غير الربطة أو أقراط الأذن + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}تعدد اللاعبين STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}أسم اللاعب @@ -1733,15 +1734,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}الشر # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :قائمة العملاء -STR_NETWORK_COMPANY_LIST_SPECTATE :شاهد -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :شركة جديدة # Network client list -STR_NETWORK_CLIENTLIST_KICK :اطرد -STR_NETWORK_CLIENTLIST_BAN :بان -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :تحدث مع الكل -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :تحدث لشركة -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :رسالة خاصة + + STR_NETWORK_SERVER :خادم STR_NETWORK_CLIENT :عميل diff --git a/src/lang/basque.txt b/src/lang/basque.txt index 66b4a38eff..4223e9f9cc 100644 --- a/src/lang/basque.txt +++ b/src/lang/basque.txt @@ -1790,6 +1790,7 @@ STR_FACE_TIE :Korbata: STR_FACE_EARRING :Belarritakoak: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Aldatu korbata eta belarritakoak + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijokalaria STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Jokalariaren izena: @@ -1848,8 +1849,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Jokoaren STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Pasahitza ezarri STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Babestu zure jokoa pasahitz batekin ez baduzu nahi publikoa izatea -STR_NETWORK_START_SERVER_UNADVERTISED :Ez -STR_NETWORK_START_SERVER_ADVERTISED :Bai STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} Bezero STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Gehienezko bezeroak: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Gehienezko bezero kopurua aukeratu. Ez da beharrezkoa guztia betetzea @@ -1914,15 +1913,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Konpaini # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Bezero zerrenda -STR_NETWORK_COMPANY_LIST_SPECTATE :Ikusle -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Konpainia berria # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kanporatu -STR_NETWORK_CLIENTLIST_BAN :Debekatu -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Guztiei hitz egin -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Konpainiari hitz egin -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Mezu pribatua + + STR_NETWORK_SERVER :Zerbitzaria STR_NETWORK_CLIENT :Bezeroa diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt index 21f4e795c2..519a4bf547 100644 --- a/src/lang/belarusian.txt +++ b/src/lang/belarusian.txt @@ -2225,6 +2225,7 @@ STR_FACE_TIE :Гальшту STR_FACE_EARRING :Завушніца: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Зьмяніць гальштук або завушніцу + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Сеткавая гульня STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Імя гульца: @@ -2283,10 +2284,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Назв STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Усталяваць пароль STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Абараніце вашу гульню паролем, калі ня хочаце рабіць яе публічна даступнай -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Інтэрнэт -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Выберыце паміж гульнёй праз Інтэрнэт або ў лакальнай сетцы -STR_NETWORK_START_SERVER_UNADVERTISED :Не -STR_NETWORK_START_SERVER_ADVERTISED :Так STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клiент{P "" ы аў} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. колькасьць клiентаў: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбар максымальнай колькасьці кліентаў. Ня ўсе месцы павінны быць занятыя @@ -2348,19 +2345,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Адлу STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Сэрвэр абаронены. Увядзіце пароль STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Кампанія абароненая. Увядзіце пароль -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Сьпіс кліентаў # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Сьпіс кліентаў -STR_NETWORK_COMPANY_LIST_SPECTATE :Назіраць -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Новая кампанія # Network client list -STR_NETWORK_CLIENTLIST_KICK :Выкінуць гульца -STR_NETWORK_CLIENTLIST_BAN :Бан -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Пагутарыць з усімі -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Пагутарыць з кампаніяй -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Прыватнае паведамленьне + + STR_NETWORK_SERVER :Сэрвэр STR_NETWORK_CLIENT :Кліент diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 6ea84d97b2..92c6929b82 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -1991,6 +1991,7 @@ STR_FACE_TIE :Gravata: STR_FACE_EARRING :Brinco: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Alterar gravata ou brinco + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multi-jogador STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nome: @@ -2053,10 +2054,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}O nome d STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Definir senha STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Proteja o jogo com uma senha se não desejar que seja publicamente acessível -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :[BLACK}Publicado -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Selecione entre um jogo publicado (internet) ou não publicado (Rede de Área Local, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Não -STR_NETWORK_START_SERVER_ADVERTISED :Sim STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Num máx de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Escolha o número máximo de clientes. Não é necessário estarem todos preenchidos @@ -2118,19 +2115,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Desconec STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor está protegido. Digite a senha STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa está protegida. Digite a senha -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Lista de clientes # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes -STR_NETWORK_COMPANY_LIST_SPECTATE :Assistir -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nova Companhia # Network client list -STR_NETWORK_CLIENTLIST_KICK :Banir -STR_NETWORK_CLIENTLIST_BAN :Banir -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Falar com todos -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Falar com a empresa -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Mensagem privada + + STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt index aa11c5df73..9ddda2dc28 100644 --- a/src/lang/bulgarian.txt +++ b/src/lang/bulgarian.txt @@ -1836,6 +1836,7 @@ STR_FACE_TIE :Вратовр STR_FACE_EARRING :Oбица: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cмени вратовръзкатa или oбицатa + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Онлайн играчи STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Име на играч: @@ -1894,10 +1895,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Имет STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Поставяне на парола STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Защитаване на вашата игра с парола за да не е публично достъпна -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Рекламирана -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Избери игра измежду рекламирана през интернет или нерекламирана през Локален интернет хост или ЛАН -STR_NETWORK_START_SERVER_UNADVERTISED :Не -STR_NETWORK_START_SERVER_ADVERTISED :Да STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клиент{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. брой играчи: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Избор на максималния брой клиенти. Не всички слотове трябва да се попълнят @@ -1962,15 +1959,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Комп # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Списък с играчите -STR_NETWORK_COMPANY_LIST_SPECTATE :Наблюдавай -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Нова фирма # Network client list -STR_NETWORK_CLIENTLIST_KICK :Изгони -STR_NETWORK_CLIENTLIST_BAN :Бан -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Кажи на всички -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Кажи на компания -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Лично съобщение + + STR_NETWORK_SERVER :Сървър STR_NETWORK_CLIENT :Клиент diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 6df8a5e4b7..5ad9f92378 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -1991,6 +1991,7 @@ STR_FACE_TIE :Corbata: STR_FACE_EARRING :Arracades: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Canvia la corbata o les arracades + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijugador STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nom del jugador: @@ -2053,10 +2054,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}El nom d STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Posa una contrasenya STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protegeix la teva partida amb una contrasenya si no vols que sigui accessible a desconeguts -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Anunciat -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Escull entre una partida anunciada (internet) i una partida no anunciada (xarxa d'àrea local, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :No -STR_NETWORK_START_SERVER_ADVERTISED :Sí STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} client{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Màxim nombre de clients: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Tria el nombre màxim de clients. No és necessari omplir tots els llocs. @@ -2118,19 +2115,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Desconne STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor protegit: escriviu-ne la contrasenya STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Companyia protegida: escriviu-ne la contrasenya -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Llista de clients # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Llista de clients -STR_NETWORK_COMPANY_LIST_SPECTATE :Espectador -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nova companyia # Network client list -STR_NETWORK_CLIENTLIST_KICK :Breu -STR_NETWORK_CLIENTLIST_BAN :Prohibit -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Parla a tothom -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Parla amb la companyia -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Missatge Privat + + STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Client diff --git a/src/lang/chuvash.txt b/src/lang/chuvash.txt index c5e617e841..37567cefc0 100644 --- a/src/lang/chuvash.txt +++ b/src/lang/chuvash.txt @@ -726,6 +726,7 @@ STR_FACE_COLLAR :Ҫуха: STR_FACE_TIE :Галстук: STR_FACE_EARRING :Алка: + # Network server list STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Вӑйӑҫӑ ят: @@ -788,6 +789,8 @@ STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Вырн # Network client list + + # Network set password # Network company info join/password diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index b28690c848..ab7f63301a 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -2020,6 +2020,7 @@ STR_FACE_TIE :Kravata: STR_FACE_EARRING :Naušnica: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Promijeni kravatu ili naušnicu + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Više igrača STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Ime igrača: @@ -2078,10 +2079,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Ime igre STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Postavi zaporku STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Zaštiti svoju igru pomoću zaporke ukoliko ne želiš da bude javno dostupna -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Sa oglasima -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Odaberi između igre s oglasima (internet) i bez oglasa (Local Area Network, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Ne -STR_NETWORK_START_SERVER_ADVERTISED :Da STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klijen{P t ta ata} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Najveći broj klijenata: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Odaberi najveći broj klijenata. Ne moraju sva mjesta biti popunjena. @@ -2143,19 +2140,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Odspoji STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Poslužitelj je zaštićen. Unesite zaporku STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Tvrtka je zaštićena. Unesite zaporku -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Popis klijenata # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Popis klijenata -STR_NETWORK_COMPANY_LIST_SPECTATE :Promatraj -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nova tvrtka # Network client list -STR_NETWORK_CLIENTLIST_KICK :Izbaci -STR_NETWORK_CLIENTLIST_BAN :Zabrana -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Razgovaraj sa svima -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Razgovaraj s tvrtkom -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privatna poruka + + STR_NETWORK_SERVER :Poslužitelj STR_NETWORK_CLIENT :Klijent diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 444bdc7dfa..8650bf7f3c 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -2072,6 +2072,7 @@ STR_FACE_TIE :Kravata: STR_FACE_EARRING :Náušnice: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Změnit kravatu nebo náušnice + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Jméno hráče: @@ -2134,10 +2135,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Jméno h STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Nastavit heslo STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Svoji hru si můžeš ochránit heslem, když nechceš, aby se ti do ni hlásili jiní lidé -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Vypsané -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Vyber mezi propagovanou (internet) a nepropagovanou (Místní síť, LAN) hrou -STR_NETWORK_START_SERVER_UNADVERTISED :Ne -STR_NETWORK_START_SERVER_ADVERTISED :Ano STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" i ů} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Nejvyšší počet hráčů: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Zvol nejvyšší počet hráčů. Může se jich připojit i méně @@ -2199,19 +2196,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Odpojit STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server je chráněný. Napiš heslo STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Společnost je chráněná. Napiš heslo -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :Seznam klientů # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Seznam hráčů -STR_NETWORK_COMPANY_LIST_SPECTATE :Pozorovat -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nová společnost # Network client list -STR_NETWORK_CLIENTLIST_KICK :Vyhodit -STR_NETWORK_CLIENTLIST_BAN :Ban -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Napsat všem -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Napsat společnosti -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Soukromá zpráva + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient diff --git a/src/lang/danish.txt b/src/lang/danish.txt index cff944dd92..8a34c16c57 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -1929,6 +1929,7 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Ørering: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Ændre slips eller ørering + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Netværksspil STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spiller navn: @@ -1987,10 +1988,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Navnet v STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Sæt kodeord STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beskyt dit spil med et kodeord hvis du ikke vil have fremmede med -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Offentlig -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Vælg mellem et offentligt (internet) og et ikke offentligt (lokalnetværk, LAN) spil -STR_NETWORK_START_SERVER_UNADVERTISED :Nej -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" er} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maksimalt antal tilladte klienter: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Vælg det maksimale antal klienter. Det er ikke nødvendigt at fylde dem alle @@ -2052,19 +2049,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Afbryd f STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Serveren er beskyttet. Indtast kodeord STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Selskabet er beskyttet. Indtast kodeord -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Klientliste # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Klient liste -STR_NETWORK_COMPANY_LIST_SPECTATE :Tilslut som tilskuer -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nyt firma # Network client list -STR_NETWORK_CLIENTLIST_KICK :Smid ud -STR_NETWORK_CLIENTLIST_BAN :Ban (Forvis spiller) -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Tal til alle -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Tal til selskab -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privat besked + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 63ed51c351..ae1af9673a 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -1990,6 +1990,7 @@ STR_FACE_TIE :Stropdas: STR_FACE_EARRING :Oorbel: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Verander das of oorbel + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Netwerkspel STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spelersnaam: @@ -2052,10 +2053,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}De speln STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Wachtwoord instellen STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beveilig je spel met een wachtwoord als je niet wilt dat dit algemeen toegankelijk is -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Openbaar -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Kies tussen een openbaar (internet) en een niet-openbaar (Local Area Network, LAN) spel -STR_NETWORK_START_SERVER_UNADVERTISED :Nee -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} speler{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximumaantal spelers: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Kies het maximaal aantal toegestane spelers. Niet alle posities hoeven gebruikt te worden. @@ -2117,19 +2114,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Verbindi STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server is beveiligd. Voer wachtwoord in STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Bedrijf is beveiligd. Voer wachtwoord in -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Spelerslijst # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spelerslijst -STR_NETWORK_COMPANY_LIST_SPECTATE :Toekijken -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nieuw bedrijf # Network client list -STR_NETWORK_CLIENTLIST_KICK :Uit het spel schoppen -STR_NETWORK_CLIENTLIST_BAN :Verbannen -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Met iedereen praten -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Met bedrijf praten -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privébericht + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Speler diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index 1fd94cbd87..085e982fa3 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -1846,6 +1846,7 @@ STR_FACE_TIE :Tie: STR_FACE_EARRING :Earring: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Change tie or earring + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Player name: @@ -1904,10 +1905,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}The game STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Set password STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protect your game with a password if you don't want it to be publicly accessible -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Advertised -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Choose between an advertised (internet) and a not advertised (Local Area Network, LAN) game -STR_NETWORK_START_SERVER_UNADVERTISED :No -STR_NETWORK_START_SERVER_ADVERTISED :Yes STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} client{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximum number of clients: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Choose the maximum number of clients. Not all slots need to be filled @@ -1972,15 +1969,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Company # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Client list -STR_NETWORK_COMPANY_LIST_SPECTATE :Spectate -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :New company # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kick -STR_NETWORK_CLIENTLIST_BAN :Ban -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Speak to all -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Speak to company -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Private message + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 9573e2f9dd..6b8b77bacb 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -1991,6 +1991,7 @@ STR_FACE_TIE :Tie: STR_FACE_EARRING :Earring: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Change tie or earring + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Player name: @@ -2053,10 +2054,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}The game STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Set password STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protect your game with a password if you don't want it to be publicly accessible -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Advertised -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Choose between an advertised (internet) and a not advertised (Local Area Network, LAN) game -STR_NETWORK_START_SERVER_UNADVERTISED :No -STR_NETWORK_START_SERVER_ADVERTISED :Yes STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} client{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximum number of clients: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Choose the maximum number of clients. Not all slots need to be filled @@ -2118,19 +2115,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Disconne STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server is protected. Enter password STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Company is protected. Enter password -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Client list # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Client list -STR_NETWORK_COMPANY_LIST_SPECTATE :Spectate -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :New company # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kick -STR_NETWORK_CLIENTLIST_BAN :Ban -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Speak to all -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Speak to company -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Private message + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client @@ -2175,6 +2166,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Could no STR_NETWORK_ERROR_CLIENT_START :{WHITE}Could not connect STR_NETWORK_ERROR_TIMEOUT :{WHITE}Connection #{NUM} timed out STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}A protocol error was detected and the connection was closed +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Your player name has not been set. The name can be set at the top of the Multiplayer window STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}The revision of this client does not match the server's revision STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Wrong password STR_NETWORK_ERROR_SERVER_FULL :{WHITE}The server is full @@ -2187,6 +2179,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}You took STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Your computer is too slow to keep up with the server STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Your computer took too long to download the map STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Your computer took too long to join the server +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Your player name is not valid ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :general error @@ -2209,6 +2202,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :received no pas STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :general timeout STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :downloading map took too long STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :processing map took too long +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :invalid client name ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possible connection loss diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt index 97f1e625f4..99473e3e4e 100644 --- a/src/lang/esperanto.txt +++ b/src/lang/esperanto.txt @@ -1530,6 +1530,7 @@ STR_FACE_TIE :Kravato: STR_FACE_EARRING :Orelringo: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Ŝanĝi kravaton aŭ orelringon. + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Pluraj ludantoj STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Ludantnomo: @@ -1652,15 +1653,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Kompanio # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Klientlisto -STR_NETWORK_COMPANY_LIST_SPECTATE :Spekti -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nova kompanio # Network client list -STR_NETWORK_CLIENTLIST_KICK :Forbatu -STR_NETWORK_CLIENTLIST_BAN :Bari -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Parolu al ĉiuj -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Parolu al kompanio -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privata mesaĝo + + STR_NETWORK_SERVER :Servilo STR_NETWORK_CLIENT :Kliento diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index fdf2958841..d4b7d94dbe 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -2042,6 +2042,7 @@ STR_FACE_TIE :Lips: STR_FACE_EARRING :Kõrvarõngas: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Vaheta kraed või kõrvarõngast + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Mitmikmäng STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Mängija nimi: @@ -2104,10 +2105,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Serveril STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Määra salasõna STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Et server ei oleks avalik, kaitse oma mäng salasõnaga -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Reklaami -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Valib reklaamitava (internet) või mittereklaamitava (kohtvõrk, LAN) mängu -STR_NETWORK_START_SERVER_UNADVERTISED :Ei -STR_NETWORK_START_SERVER_ADVERTISED :Jah STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" i} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Kliente kuni: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS.in :sees @@ -2170,19 +2167,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Katkesta STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server on kaitstud. Sisesta salasõna STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Ettevõte on kaitstud. Sisesta salasõna -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Klientide nimekiri # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Klientide nimekiri -STR_NETWORK_COMPANY_LIST_SPECTATE :Jälgi -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Uus ettevõte # Network client list -STR_NETWORK_CLIENTLIST_KICK :Viska välja -STR_NETWORK_CLIENTLIST_BAN :Bänn -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Räägi kõigiga -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Räägi ettevõttega -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privaatne sõnum + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt index a0c6ed76bb..5820f62ead 100644 --- a/src/lang/faroese.txt +++ b/src/lang/faroese.txt @@ -1696,6 +1696,7 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Oyraringur: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Broyt slips ella oyraring + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Hópspæl STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spælara navn: @@ -1754,8 +1755,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Aðrir s STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Áset loyniorð STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Verj títt spæl við einum loyniorðið um tú ikki vil at ta skal verða opi fyri almenninginum -STR_NETWORK_START_SERVER_UNADVERTISED :Nei -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" ar} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Mest loyvdir klientar: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Vel mest loyvda tali av klientum. Ta er ikki neyðugt at fylla øll plássini @@ -1820,15 +1819,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Fyritøk # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Listi yvir klientar -STR_NETWORK_COMPANY_LIST_SPECTATE :Eygleið -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nýggja fyritøku # Network client list -STR_NETWORK_CLIENTLIST_KICK :Sparka -STR_NETWORK_CLIENTLIST_BAN :Bannað -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Tosa við øll -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Tosa við fyritøku -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Persónligt boð + + STR_NETWORK_SERVER :Servari STR_NETWORK_CLIENT :Klient diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 820a83b065..e4896cd45e 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -1991,6 +1991,7 @@ STR_FACE_TIE :Solmio: STR_FACE_EARRING :Korvakoru: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Vaihda solmio tai korvakoru + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Moninpeli STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Pelaajan nimi @@ -2053,10 +2054,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nimi nä STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Aseta salasana STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Jos peliin ei halua ulkopuolisia, voi sen suojata salasanalla -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Mainostettu -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Valitse mainostettu (internet) tai ei-mainostettu (paikallisverkko, LAN) peli -STR_NETWORK_START_SERVER_UNADVERTISED :Ei -STR_NETWORK_START_SERVER_ADVERTISED :Kyllä STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} asiakas{P "" ta} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Pelaajien enimmäismäärä: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Pelaajien enimmäismäärä. Pelissä voi olla myös vähemmän pelaajia @@ -2118,19 +2115,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Pura yht STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Palvelin on suojattu. Anna salasana STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Yhtiö on suojattu. Anna salasana -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Asiakaslista # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Asiakaslista -STR_NETWORK_COMPANY_LIST_SPECTATE :Katsele -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Uusi yhtiö # Network client list -STR_NETWORK_CLIENTLIST_KICK :Potkaise -STR_NETWORK_CLIENTLIST_BAN :Kiellä -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Puhu kaikille -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Puhu yhtiölle -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Yksityinen viesti + + STR_NETWORK_SERVER :Palvelin STR_NETWORK_CLIENT :Pelaaja @@ -2175,6 +2166,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Palvelin STR_NETWORK_ERROR_CLIENT_START :{WHITE}Yhdistäminen ei onnistunut STR_NETWORK_ERROR_TIMEOUT :{WHITE}Yhteys nro {NUM} aikakatkaistiin STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Protokollavirhe tapahtui ja yhteys suljettiin +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Et ole asettanut pelaajanimeäsi. Nimen voi asettaa moninpeli-ikkunan ylälaidassa. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Tämän asiakkaan versio ei vastaa palvelimen versiota STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Väärä salasana STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Palvelin on täynnä @@ -2187,6 +2179,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Käytit STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Tietokoneesi on liian hidas pysyäkseen palvelimen tahdissa STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Kartan lataus kesti liian kauan STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Palvelimelle liittyminen kesti liian kauan +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Pelaajanimesi ei kelpaa ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :yleinen virhe @@ -2209,6 +2202,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :salasanaa ei va STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :yleinen aikakatkaisu STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :kartan lataaminen kesti liian kauan STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :kartan käsittely kesti liian kauan +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :Epäkelpo asiakasnimi ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Mahdollinen yhteyden menetys diff --git a/src/lang/french.txt b/src/lang/french.txt index bfad801ea5..a578ea2739 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -1991,6 +1991,7 @@ STR_FACE_TIE :Cravate{NBSP}: STR_FACE_EARRING :Boucle d'oreille{NBSP}: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Modifier la cravate ou la boucle d'oreille + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijoueurs STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nom du joueur{NBSP}: @@ -2053,10 +2054,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Les autr STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Choisir le mot de passe STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protégez votre partie avec un mot de passe si vous ne souhaitez pas que d'autres l'utilisent -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Publiée -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Choisir entre une partie publiée (internet) et une partie non publiée (Réseau local, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Non -STR_NETWORK_START_SERVER_ADVERTISED :Oui STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} client{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Nombre de clients maximum{NBSP}: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Choisir un nombre maximum de clients. Tous les emplacements n'auront pas besoin d'être remplis @@ -2118,19 +2115,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Déconne STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Le serveur est protégé. Entrez le mot de passe STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}La compagnie est protégée. Entrez le mot de passe -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Liste des clients # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste des clients -STR_NETWORK_COMPANY_LIST_SPECTATE :Spectateur -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nouvelle compagnie # Network client list -STR_NETWORK_CLIENTLIST_KICK :Exclure -STR_NETWORK_CLIENTLIST_BAN :Bannir -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Parler à tous -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Parler à la compagnie -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Message privé + + STR_NETWORK_SERVER :Serveur STR_NETWORK_CLIENT :Client diff --git a/src/lang/frisian.txt b/src/lang/frisian.txt index 4a7178629e..6bceed5a1a 100644 --- a/src/lang/frisian.txt +++ b/src/lang/frisian.txt @@ -1795,6 +1795,7 @@ STR_FACE_TIE :Strik: STR_FACE_EARRING :Earbel: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Feroarje strik of earbel + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Namme fan spieler: @@ -1841,10 +1842,6 @@ STR_NETWORK_START_SERVER_CAPTION :{WHITE}Start in STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}Spulnamme: STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Wachtwurd ynstelle -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Advertearre -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Kies tusken in advertearre (ynternet) of in net-advertearre (LAN) spul -STR_NETWORK_START_SERVER_UNADVERTISED :Nee -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} kliïnt{P "" en} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maksimaal oantal kliïnten: STR_NETWORK_START_SERVER_COMPANIES_SELECT :{BLACK}{NUM} bedriuw{P "" en} @@ -1898,14 +1895,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Bedriuw # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :{WHITE}Client lyst -STR_NETWORK_COMPANY_LIST_SPECTATE :{WHITE}Taskôgje -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :{WHITE}Nei Bedriuw # Network client list -STR_NETWORK_CLIENTLIST_KICK :Skoppe -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Tsjin elkenien prate -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Praat mei bedriuw -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Priveeberjocht + + STR_NETWORK_SERVER :Tsjinner STR_NETWORK_CLIENT :Kliïnt diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt index c38ac7e026..d6609eb0d6 100644 --- a/src/lang/gaelic.txt +++ b/src/lang/gaelic.txt @@ -2081,6 +2081,7 @@ STR_FACE_TIE :Tàidh: STR_FACE_EARRING :Fàinne-chluaise: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Atharraich an tàidh no an fhàinne-chluaise + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Ioma-chluicheadair STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Ainm cluicheadair: @@ -2139,10 +2140,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Thèid a STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Suidhich facal-faire STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Dìon an geama agad le facal-faire ach nach eil e ri fhaighinn gu poblach -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Sanasaichte -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Dèan taghadh eadar geama sanasaichte (eadar-lìon) no gun sanasachadh (lìonra ionadail, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Chan eil -STR_NETWORK_START_SERVER_ADVERTISED :Tha STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} {P chliant chliant cliantan cliant} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Cliantan air a char as motha: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Tagh an àireamh as motha dhe chliantan. Cha leig thu leas a h-uile slot a lìonadh @@ -2207,15 +2204,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Tha a' c # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liosta nan cliant -STR_NETWORK_COMPANY_LIST_SPECTATE :Coimhead air -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Companaidh ùr # Network client list -STR_NETWORK_CLIENTLIST_KICK :Thoir a bhròg dha -STR_NETWORK_CLIENTLIST_BAN :Toirmisg -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Bruidhinn ris a h-uile duine -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Bruidhinn ris a' chompanaidh -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Teachdaireachd phrìobhaideach + + STR_NETWORK_SERVER :Frithealaiche STR_NETWORK_CLIENT :Cliant diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 255d5e8838..864bcdb043 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -1917,6 +1917,7 @@ STR_FACE_TIE :Garavata: STR_FACE_EARRING :Pendentes: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambia-la garavata ou os pendentes + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multixogador STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nome do xogador: @@ -1975,10 +1976,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}O nome d STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Establecer contrasinal STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protexe a túa partida cun contrasinal se non queres ser accesible públicamente -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Anunciado -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Escolle entre unha partida con anuncios (internet) ou sen eles (LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Non -STR_NETWORK_START_SERVER_ADVERTISED :Si STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Máximo de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Escolle o máximo número de clientes. Non tódolos ocos teñen que estar cubertos @@ -2040,19 +2037,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Desconec STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}O servidor está protexido. Introduce o contrasinal STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}A compañía está protexida. Introduce o contrasinal -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Lista de clientes # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes -STR_NETWORK_COMPANY_LIST_SPECTATE :Observar -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nova compañía # Network client list -STR_NETWORK_CLIENTLIST_KICK :Chimpar -STR_NETWORK_CLIENTLIST_BAN :Bloquear -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Falar a todos -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Falar con compañía -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Mensaxe privada + + STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente diff --git a/src/lang/german.txt b/src/lang/german.txt index d0f89a9265..3ac9293998 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -1991,6 +1991,7 @@ STR_FACE_TIE :Krawatte: STR_FACE_EARRING :Ohrring: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Krawatte oder Ohrring ändern + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Mehrspieler STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spielername: @@ -2053,10 +2054,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Der Name STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Passwort setzen STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Ein Passwort verhindert, dass unbefugte Leute beitreten -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Angekündigt -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Zwischen öffentlich angekündigtem (Internet) und nicht angekündigtem (Local Area Network, LAN) Spiel wählen -STR_NETWORK_START_SERVER_UNADVERTISED :Nein -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} Teilnehmer STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximale Teilnehmeranzahl: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Auswahl der maximal erlaubten Anzahl von Teilnehmern. Nicht alle Slots müssen belegt werden @@ -2118,19 +2115,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Trennen STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server ist geschützt. Passwort eingeben: STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firma ist geschützt. Passwort eingeben: -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Teilnehmerliste # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Teilnehmerliste -STR_NETWORK_COMPANY_LIST_SPECTATE :Zuschauen -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Neue Firma # Network client list -STR_NETWORK_CLIENTLIST_KICK :Hinauswerfen -STR_NETWORK_CLIENTLIST_BAN :Sperren -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Mit allen sprechen -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Mit Firma sprechen -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Private Nachricht + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Teilnehmer diff --git a/src/lang/greek.txt b/src/lang/greek.txt index fc55858dc8..15c9734628 100644 --- a/src/lang/greek.txt +++ b/src/lang/greek.txt @@ -2037,6 +2037,7 @@ STR_FACE_TIE :Γραβάτα: STR_FACE_EARRING :Σκουλαρίκι: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Αλλαγή γραβάτας ή σκουλαρικιού + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Παιχνίδι πολλών παικτών STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Όνομα παίκτη: @@ -2096,10 +2097,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Το ό STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Θέση κωδικού STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Προστατέψτε το παιχνίδι με έναν κωδικό εάν δε θέλετε να είναι δημοσίως προσβάσιμο -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Διαφημιζόμενο -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Επιλογή ανάμεσα σε ένα διαφημιζόμενο (διαδίκτυο) ή μη διαφημιζόμενο (Τοπικό Δίκτυο/LAN) παιχνίδι -STR_NETWORK_START_SERVER_UNADVERTISED :Όχι -STR_NETWORK_START_SERVER_ADVERTISED :Ναι STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} συμπαίκτ{P ης ες} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Μέγιστος αριθμός συμμετεχόντων: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Επιλέξτε τον μέγιστο αριθμό συμμετεχόντων. Δεν είναι ανάγκη να γεμίσουν όλες οι θέσεις @@ -2161,19 +2158,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Αποσ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Η πρόσβαση στον διακομιστή προστατεύεται. Εισάγετε τον κωδικό STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Η εταιρεία προστατεύεται από κωδικό. Εισάγετε κωδικό -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Λίστα συμμετεχόντων # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Λίστα συμμετεχόντων -STR_NETWORK_COMPANY_LIST_SPECTATE :Παρακολούθηση -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Νέα εταιρεία # Network client list -STR_NETWORK_CLIENTLIST_KICK :Εκδίωξη -STR_NETWORK_CLIENTLIST_BAN :Απαγόρευση -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Μιλήστε σε όλους -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Μιλήστε στην εταιρεία -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Προσωπικό μήνυμα + + STR_NETWORK_SERVER :Διακομιστής STR_NETWORK_CLIENT :Πελάτης diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index c36119dd48..eee6f1e00f 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -1895,6 +1895,7 @@ STR_FACE_TIE ::עניבה STR_FACE_EARRING ::עגילים STR_FACE_TIE_EARRING_TOOLTIP :{BLACK} שנה עניבה/עגילים + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}משחק רשת STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK} :שם השחקן @@ -1953,10 +1954,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}השם STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}קבע סיסמה STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}הגן על המשחק שלך עם סיסמה אם אתה לא רוצה שהוא יהיה זמין לכולם -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}מפורסם -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}בחר בין משחק מפורסם (אינטרנטי) ומשחק לא מפורסם (רשת מקומית, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :לא -STR_NETWORK_START_SERVER_ADVERTISED :כן STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} לקוח{P "" "ות"} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}מספר מקסימלי של לקוחות: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK} :מספר משתתפים מירבי @@ -2021,15 +2018,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}חברה # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :רשימת משתתפים -STR_NETWORK_COMPANY_LIST_SPECTATE :צפה -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :חברה חדשה # Network client list -STR_NETWORK_CLIENTLIST_KICK :בעט -STR_NETWORK_CLIENTLIST_BAN :חסימה -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :דבר לכולם -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :דבר לחברה -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :הודעה פרטית + + STR_NETWORK_SERVER :שרת STR_NETWORK_CLIENT :לקוח diff --git a/src/lang/hindi.txt b/src/lang/hindi.txt index d8e185057f..220e584b4c 100644 --- a/src/lang/hindi.txt +++ b/src/lang/hindi.txt @@ -336,6 +336,7 @@ STR_QUIT_YES :{BLACK}हा # Face selection window + # Network server list STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT :{BLACK}{COMMA}x{COMMA} @@ -348,7 +349,6 @@ STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT :{BLACK}{COMMA}x # Start new multiplayer server -STR_NETWORK_START_SERVER_ADVERTISED :हाँ # Network game lobby @@ -371,6 +371,8 @@ STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR :{SILVER}उद # Network client list + + # Network set password # Network company info join/password diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index cba2a6aef0..5aa64101a3 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -2054,6 +2054,7 @@ STR_FACE_TIE :Nyakkendő: STR_FACE_EARRING :Fülbevaló: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Nyakkendő vagy fülbevaló cseréje + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Hálózati játék STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Játékos neve: @@ -2116,10 +2117,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}A játé STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Jelszó beállítása STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Védd le a játékodat jelszóval, ha nem akarod hogy illetéktelenek csatlakozzanak -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Hírdetett -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Válassz hírdetett (internet) és nem hírdetett (helyi hálózat, LAN) játék közül. -STR_NETWORK_START_SERVER_UNADVERTISED :Nem -STR_NETWORK_START_SERVER_ADVERTISED :Igen STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} kliens STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Játékosok max. száma: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}A maximálisan felcsatlakozható kliensek számának kiválasztása. Nem szükséges pont ennyi embernek éppen kapcsolódva lennie @@ -2181,19 +2178,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Megszak STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}A szerver jelszóval van védve. Írd be STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}A vállalat jelszóval van védve. Írd be -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Kliens lista # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Kliens lista -STR_NETWORK_COMPANY_LIST_SPECTATE :Megfigyelés -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Új vállalat # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kirúgás -STR_NETWORK_CLIENTLIST_BAN :Kitiltás -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Üzenet mindenkinek -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Üzenet a vállalatnak -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privát üzenet + + STR_NETWORK_SERVER :Szerver STR_NETWORK_CLIENT :Kliens diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt index 47a4d268bc..f22328c20f 100644 --- a/src/lang/icelandic.txt +++ b/src/lang/icelandic.txt @@ -1734,6 +1734,7 @@ STR_FACE_TIE :Bindi: STR_FACE_EARRING :Eyrnalokkur: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Breyta bindi eða eyrnalokk + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Fjölspilun STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nafn leikmanns: @@ -1856,15 +1857,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Fyrirtæ # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Listi yfir leikmenn -STR_NETWORK_COMPANY_LIST_SPECTATE :Fylgjast með -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nýtt fyrirtæki # Network client list -STR_NETWORK_CLIENTLIST_KICK :Sparka -STR_NETWORK_CLIENTLIST_BAN :Banna -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Tala við alla -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Tala við fyrirtæki -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Einkaskilaboð + + STR_NETWORK_SERVER :Þjónn STR_NETWORK_CLIENT :Notandi diff --git a/src/lang/ido.txt b/src/lang/ido.txt index ba04de0dee..aad91f8978 100644 --- a/src/lang/ido.txt +++ b/src/lang/ido.txt @@ -602,6 +602,7 @@ STR_QUIT_NO :{BLACK}Ne # Face selection window + # Network server list STR_NETWORK_SERVER_LIST_GENERAL_ONLINE :{BLACK}{COMMA}/{COMMA} - {COMMA}/{COMMA} @@ -636,6 +637,8 @@ STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT :{BLACK}{COMMA}x # Network client list + + # Network set password # Network company info join/password diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index a6401981a2..878cb24d8e 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -1967,6 +1967,7 @@ STR_FACE_TIE :Dasi: STR_FACE_EARRING :Anting-anting: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Ubah dasi atau anting-anting + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Bermain bersama STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nama pemain: @@ -2029,10 +2030,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nama per STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Atur kata sandi STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Lindungi permainan ini dengan kata kunci jika anda tidak ingin membiarkannya terbuka untuk umum -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Diiklankan -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Pilih antara permainan diiklankan (internet) dan tidak diiklankan (Jaringan wilayah lokal, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Tidak -STR_NETWORK_START_SERVER_ADVERTISED :Ya STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klien STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maksimum jumlah klien: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Pilih jumlah klien maksimal. Tidak semua slot harus diisi @@ -2094,19 +2091,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Putuskan STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server terkunci, masukkan kata kunci STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Perusahaan terkunci, masukkan kata kunci -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Daftar klien # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Daftar klien -STR_NETWORK_COMPANY_LIST_SPECTATE :Menonton -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Buat Perusahaan # Network client list -STR_NETWORK_CLIENTLIST_KICK :Usir -STR_NETWORK_CLIENTLIST_BAN :Larangan -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Bicara ke semua -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Bicara ke perusahaan -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Pesan pribadi + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klien diff --git a/src/lang/irish.txt b/src/lang/irish.txt index 18e4bc2df2..da17c26811 100644 --- a/src/lang/irish.txt +++ b/src/lang/irish.txt @@ -1869,6 +1869,7 @@ STR_FACE_TIE :Carbhat: STR_FACE_EARRING :Fáinne cluaise: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Athraigh carbhat nó fáinne cluaise + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Ilimreoirí STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Ainm imreora: @@ -1927,10 +1928,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Taispeá STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Socraigh pasfhocal STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Cosain do chluiche le pasfhocal más mian leat nach mbeidh rochtain phoiblí air -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Fógartha -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Roghnaigh idir cluiche fógartha (idirlín) agus cluiche neamhfhógartha (Líonra Achair Logánta, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Níl -STR_NETWORK_START_SERVER_ADVERTISED :Tá STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} {P ch ch ch gc c}lia{P "" "" "" "" i}nt STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Cliaint uasta: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Roghnaigh uaslíon na gcliant. Ní gá gach áit a líonadh @@ -1995,15 +1992,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Tá an c # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liosta na gcliant -STR_NETWORK_COMPANY_LIST_SPECTATE :Féach air -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Cuideachta nua # Network client list -STR_NETWORK_CLIENTLIST_KICK :Ciceáil -STR_NETWORK_CLIENTLIST_BAN :Toirmisc -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Labhair le cách -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Labhair le cuideachta -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Teacht. phríobháideach + + STR_NETWORK_SERVER :Freastalaí STR_NETWORK_CLIENT :Cliant diff --git a/src/lang/italian.txt b/src/lang/italian.txt index 9cad946207..8841f3e711 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -2005,6 +2005,7 @@ STR_FACE_TIE :Cravatta: STR_FACE_EARRING :Orecchino: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambia la cravatta o l'orecchino + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multigiocatore STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nome giocatore: @@ -2067,10 +2068,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Il nome STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Imposta password STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protegge la partita con una password in modo che non sia accessibile pubblicamente -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Pubblico -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Sceglie fra partita pubblica (su Internet) o privata (su rete locale, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :No -STR_NETWORK_START_SERVER_ADVERTISED :Sì STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} client STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Limite client: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Imposta il numero massimo di client. Non tutti i posti dovranno essere occupati @@ -2132,19 +2129,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Disconne STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server protetto. Inserire la password STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Compagnia protetta. Inserire la password -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Elenco dei client # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Elenco dei client -STR_NETWORK_COMPANY_LIST_SPECTATE :Diventa spettatore -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nuova compagnia # Network client list -STR_NETWORK_CLIENTLIST_KICK :Espelli -STR_NETWORK_CLIENTLIST_BAN :Bandisci -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Parla a tutti -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Parla alla compagnia -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Messaggio privato + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index d9c676f1e2..f4cc22bf0a 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -32,7 +32,7 @@ STR_CARGO_PLURAL_OIL :石油 STR_CARGO_PLURAL_LIVESTOCK :家畜 STR_CARGO_PLURAL_GOODS :商品 STR_CARGO_PLURAL_GRAIN :穀物 -STR_CARGO_PLURAL_WOOD :木材 +STR_CARGO_PLURAL_WOOD :原木 STR_CARGO_PLURAL_IRON_ORE :鉄鉱石 STR_CARGO_PLURAL_STEEL :鋼鉄 STR_CARGO_PLURAL_VALUABLES :貴重品 @@ -66,7 +66,7 @@ STR_CARGO_SINGULAR_OIL :石油 STR_CARGO_SINGULAR_LIVESTOCK :家畜 STR_CARGO_SINGULAR_GOODS :商品 STR_CARGO_SINGULAR_GRAIN :穀物 -STR_CARGO_SINGULAR_WOOD :木材 +STR_CARGO_SINGULAR_WOOD :原木 STR_CARGO_SINGULAR_IRON_ORE :鉄鉱石 STR_CARGO_SINGULAR_STEEL :鋼鉄 STR_CARGO_SINGULAR_VALUABLES :貴重品 @@ -100,7 +100,7 @@ STR_QUANTITY_OIL :石油{VOLUME_L STR_QUANTITY_LIVESTOCK :家畜{COMMA}頭 STR_QUANTITY_GOODS :商品{COMMA}箱 STR_QUANTITY_GRAIN :穀物{WEIGHT_LONG} -STR_QUANTITY_WOOD :木材{WEIGHT_LONG} +STR_QUANTITY_WOOD :原木{WEIGHT_LONG} STR_QUANTITY_IRON_ORE :鉄鉱石{WEIGHT_LONG} STR_QUANTITY_STEEL :鋼鉄{WEIGHT_LONG} STR_QUANTITY_VALUABLES :貴重品{COMMA}袋 @@ -187,6 +187,7 @@ STR_COLOUR_ORANGE :橙 STR_COLOUR_BROWN :茶 STR_COLOUR_GREY :灰 STR_COLOUR_WHITE :白 +STR_COLOUR_RANDOM :ランダム # Units used in OpenTTD STR_UNITS_VELOCITY_IMPERIAL :{COMMA}mph @@ -312,6 +313,7 @@ STR_SORT_BY_RATING :レーティン STR_SORT_BY_NUM_VEHICLES :車両数 STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :昨年の総利益 STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :今年の総利益 +STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :前年度の平均利益 # Group by options for vehicle list STR_GROUP_BY_SHARED_ORDERS :共有注文 @@ -360,6 +362,7 @@ STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION :{BLACK}地形 STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}町を生成します STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}産業を生成します STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}道路を建設します +STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}路面電車建設 STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}木を植えます。Shiftキーを押しながら決定すると費用を見積もります STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}標識を設置します STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}オブジェクトを設置します。Shiftを押しながら決定すると費用を見積もります @@ -648,6 +651,7 @@ STR_MUSIC_EFFECTS_VOLUME :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}音楽がありません STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}トラック STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}タイトル @@ -673,7 +677,9 @@ STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTB STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}楽曲索引 STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}プレイリスト - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}消去 +STR_PLAYLIST_CHANGE_SET :{BLACK}セットの変更 STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}選択したプレイリストの内容を消去します。(カスタム1/2 のみ) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}音楽の選択を別のインストール済みセットに変更する STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストに追加します。(カスタム1/2 のみ) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストから削除します。(カスタム1/2 のみ) @@ -733,6 +739,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}荒地 STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}草地 STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}露地 +STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT} {BLACK}熱帯雨林 STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}耕作地 STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}樹林 STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}岩石 @@ -764,6 +771,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}全貨 STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}最新のメッセージ/ニュースを表示します STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_PAUSED :{YELLOW}* * ポーズ中 * * +STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * 一時停止中 (リンクグラフの更新を待っています) * * STR_STATUSBAR_AUTOSAVE :{RED}オートセーブ STR_STATUSBAR_SAVING_GAME :{RED}* * ゲームセーブ中 * * @@ -923,8 +931,12 @@ STR_GAME_OPTIONS_CURRENCY_ZAR :南アフリカ STR_GAME_OPTIONS_CURRENCY_CUSTOM :カスタム… STR_GAME_OPTIONS_CURRENCY_GEL :グルジア ラリー(GEL) STR_GAME_OPTIONS_CURRENCY_IRR :イラン リアル(IRR) +STR_GAME_OPTIONS_CURRENCY_RUB :新ロシアルーブル(RUB) STR_GAME_OPTIONS_CURRENCY_MXN :メキシコペソ(MXN) STR_GAME_OPTIONS_CURRENCY_NTD :新台湾ドル(ntd) +STR_GAME_OPTIONS_CURRENCY_CNY :人民元(CNY) +STR_GAME_OPTIONS_CURRENCY_HKD :香港ドル(HKD) +STR_GAME_OPTIONS_CURRENCY_INR :インドルピー(INR) STR_GAME_OPTIONS_CURRENCY_IDR :インドネシアルピア(IDR) ############ end of currency region @@ -982,6 +994,7 @@ STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM} STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}ハードウェアアクセラレーション +STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK} 垂直同期 STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}インターフェイスのサイズ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}インターフェイス上の単位サイズを指定します @@ -992,15 +1005,19 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :2倍 STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :4倍 STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}フォントサイズ +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}使用するインターフェースのフォントサイズを選択します STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(自動検出) STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :ノーマル +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :ダブルサイズ +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :4倍 STR_GAME_OPTIONS_GRAPHICS :{BLACK}グラフィクス STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}画面リフレッシュレート STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}使用する画面のリフレッシュレートを選択します STR_GAME_OPTIONS_REFRESH_RATE_OTHER :その他 +STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}60Hzを超えるリフレッシュレートはパフォーマンスに影響を与える可能性があります。 STR_GAME_OPTIONS_BASE_GRF :{BLACK}基本グラフィックセット STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}使用するグラフィックセットを選択します @@ -1096,6 +1113,7 @@ STR_TERRAIN_TYPE_FLAT :平地 STR_TERRAIN_TYPE_HILLY :丘陵地 STR_TERRAIN_TYPE_MOUNTAINOUS :山岳地 STR_TERRAIN_TYPE_ALPINIST :山脈地帯 +STR_TERRAIN_TYPE_CUSTOM :カスタム高度 STR_CITY_APPROVAL_PERMISSIVE :寛大 STR_CITY_APPROVAL_TOLERANT :寛容 @@ -1116,6 +1134,7 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :ゲーム設定 STR_CONFIG_SETTING_TYPE_GAME_INGAME :ゲーム設定(現在のゲームにのみ影響) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :会社設定(新規ゲームにのみ影響) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :会社設定(現在の会社のみに影響) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}注意! STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}カテゴリ: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}種類: @@ -1177,11 +1196,13 @@ STR_CONFIG_SETTING_DISASTERS_HELPTEXT :設定を有効 STR_CONFIG_SETTING_CITY_APPROVAL :地域の再編に対する町の姿勢: {STRING} STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :会社が街域で引き起こした騒音(主に空港)や環境破壊がどの程度、街での評価や同じ地域での更なる建設行為に影響するかを設定します +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :マップ高さ限界: {STRING} STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}マップの最高高さをこの値には設定出来ません。少なくとも1箇所以上この値より高い山があります。 STR_CONFIG_SETTING_AUTOSLOPE :建物/路線の自動地形追従: {STRING} STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :撤去を行わないで建物や路線がある土地の地形を変更することを可能にします。建物/路線は変更された地形に自動で追従します。 STR_CONFIG_SETTING_CATCHMENT :現実的な受入範囲: {STRING} STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :駅や空港の種類の違いによって受入範囲が変動するようになります +STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :有効にすると、駅が接続されている産業(石油掘削装置など)にも、近くに建設された会社が所有している駅がサービスを提供する場合があります。無効になっている場合、これらの産業は、接続されているステーションによってのみサービスを受けることができます。近くの会社のステーションはそれらにサービスを提供できず、接続されたステーションは業界以外のものにサービスを提供しません STR_CONFIG_SETTING_EXTRADYNAMITE :街有道路・橋・トンネルの撤去容認: {STRING} STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :街有の交通インフラや建物の撤去をより容易にします STR_CONFIG_SETTING_TRAIN_LENGTH :列車の最大長: {STRING} @@ -1319,6 +1340,7 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :石油精製所 STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :石油精製所はマップの外周付近にのみ建設されます。つまり、外周が海のマップでは海岸沿いに建設されるということです STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪線の位置: {STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :亜寒帯気候での雪線の高さを設定します。雪は産業と街の成長に影響があります +STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :地形の起伏: {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesisのみ) 地形の起伏度を設定します。なだらかな地形では丘陵の数は減り、裾野が長くなります。起伏が多い地形では丘陵が多くなりますが、似たり寄ったりな地形の繰り返しに見えることがあります STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :特になだらか @@ -1357,6 +1379,7 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :青紫 STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :スクロール時の動き STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :右クリックでビューポートを移動し、マウスの位置をロックします STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :右クリックで地図を移動し、マウスの位置をロックします +STR_CONFIG_SETTING_SCROLLMODE_RMB :マップを右マウスボタンで動かす STR_CONFIG_SETTING_SMOOTH_SCROLLING :画面のスムーズスクロール: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :ミニマップでの移動や「現在位置に移動」などのコマンドを使用した際にメイン画面がどのように移動するかを設定します。有効にした場合はスムーズにスクロールして移動します。無効の場合は目的地に直接ジャンプします STR_CONFIG_SETTING_MEASURE_TOOLTIP :測定ツールチップ表示: {STRING} @@ -1428,6 +1451,7 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :橋やトンネ STR_CONFIG_SETTING_EXPENSES_LAYOUT :財政ウィンドウのグループ分け: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :財政ウィンドウのレイアウトを収入部門・支出部門でグループ分けするかどうかを設定します STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}%通常のゲーム速度 +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :制限なし(コンピューターが許す限り高速) STR_CONFIG_SETTING_SOUND_TICKER :ニュース表示: {STRING} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :ステータスバーにニュースが流れたとき効果音を鳴らすかどうかを設定します @@ -1476,6 +1500,7 @@ STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :マルチプレ STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :マルチプレイヤーゲームでもAIのライバル企業が登場するかを設定します STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :命令コード処理上限: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :AIやゲームスクリプトが一つの「詰め込み指令」を処理する際に、一度に演算できる命令コード数を設定します。一般に値を小さくした場合、ゲームへの負荷が軽減されます +STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_VALUE :{COMMA} MiB STR_CONFIG_SETTING_SERVINT_ISPERCENT :最大信頼度を点検要件化: {STRING} STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT :次の点検が必要と判断される条件を設定します。無効の場合は、前の点検から指定の期間が経過した際に点検が必要と判断されます。有効にすると、輸送機器の最大信頼度が指定の値より落ち込んだ場合に次の点検が必要と判断されます @@ -1535,7 +1560,9 @@ STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :カラー新聞 STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :新聞がカラー版になる境目の年を設定します STR_CONFIG_SETTING_STARTING_YEAR :開始年: {STRING} STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :スコアリングの目的でゲームが終了する年。 今年の終わりには、会社のスコアが記録され、ハイスコア画面が表示されますが、プレーヤーはその後もプレイを続けることができます。{}これが開始年より前の場合、ハイスコア画面は表示されません。 +STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} STR_CONFIG_SETTING_ECONOMY_TYPE :エコノミータイプ:{STRING} +STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :オリジナル STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :なだらか STR_CONFIG_SETTING_ALLOW_SHARES :他社株の取引許容: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :有効にすると、ライバル会社の株式を取引できるようになります。この設定を有効にしても、目的の社が設立から丸5年経過していない場合は取引できません @@ -1586,6 +1613,7 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :町の総人口 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :樹木の自然成長: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :ゲーム中、ランダムに生えてくる樹種を設定します。設定によっては樹木の生育に依存する産業に悪影響が生じる可能性があります(「不可」にした場合、亜熱帯地域の伐採所を機能させ続けるためには手動で植林し続ける必要があります) STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :成長するが、熱帯雨林にのみ広がる +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :成長し、どこにでも広がる STR_CONFIG_SETTING_TOOLBAR_POS :メインツールバーの位置: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :画面上のメインツールバーの位置を決めます @@ -1746,6 +1774,7 @@ STR_CONFIG_ERROR_OUT_OF_MEMORY :{WHITE}メモ STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}スプライトキャッシュ中、{BYTES}の割り当てに失敗しました。スプライトキャッシュは{BYTES}に減ったため、OpenTTDの処理速度が低下する恐れがあります。必要メモリ量を減らすには32bitグラフィックを無効にするか、最大ズームイン・ズームアウトのレベルを下げてください # Video initalization errors +STR_VIDEO_DRIVER_ERROR :{WHITE}ビデオ設定にエラーがあります... # Intro window STR_INTRO_CAPTION :{WHITE}OpenTTD {REV} @@ -1910,6 +1939,7 @@ STR_FACE_TIE :ネクタイ: STR_FACE_EARRING :イヤリング: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}ネクタイ/イヤリングを変更します + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}マルチプレイヤーゲーム STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}プレイヤー名: @@ -1953,6 +1983,7 @@ STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}サー STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}サーバー情報を更新します STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}インターネットを検索 +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}インターネットで公開されているサーバーを探す STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}LANで探す STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}ローカルエリアネットワークでサーバーを検索する STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}サーバーを追加 @@ -1971,10 +2002,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}ゲー STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}パスワードを設定 STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}ゲームをパスワードで保護することができます。一般から公然とアクセスされたくない場合等に設定します -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}ゲーム公示 -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}ゲームを公示(インターネット)するか、非公示(LAN)にするかを選びます -STR_NETWORK_START_SERVER_UNADVERTISED :非公示 -STR_NETWORK_START_SERVER_ADVERTISED :公示 STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}接続者数: {NUM} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}最大接続数: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}接続できるクライアントの最大数を指定します。必ずしも全スロットを埋める必要はありません @@ -2039,15 +2066,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}この # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :クライアントリスト -STR_NETWORK_COMPANY_LIST_SPECTATE :観覧モード -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :新会社 # Network client list -STR_NETWORK_CLIENTLIST_KICK :追放 -STR_NETWORK_CLIENTLIST_BAN :参入禁止 -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :全員へ発言 -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :チームへ発言 -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :個人的なメッセージ + + STR_NETWORK_SERVER :サーバー STR_NETWORK_CLIENT :クライアント @@ -2103,6 +2125,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}パス STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}サーバーとの接続を維持できる十分な処理能力がありません STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}マップのダウンロード時間が規定を超過しました STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}タイムアウトによりサーバーへの接続を確立できません +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}プレイヤー名が無効です ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :一般エラー @@ -2138,6 +2161,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :ゲームはま STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :ゲームはまだポーズされています。({STRING}、{STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :ゲームはまだポーズされています。 ({STRING}、{STRING}、{STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :ゲームはまだポーズされています。 ({STRING}、{STRING}、{STRING}、{STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :ゲームはまだポーズされています。 ({STRING}, {STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :ゲームのポーズが解除されました。({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :プレーヤー数不足 STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :クライアントに接続中 @@ -2155,6 +2179,7 @@ STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} は名前を {STRING} に変更しました STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}サーバがセッションを終了しました STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}このサーバーは再起動中です…{}しばらくお待ちください… +STR_NETWORK_MESSAGE_KICKED :*** {STRING}がキックされました。理由: ({STRING}) # Content downloading window STR_CONTENT_TITLE :{WHITE}コンテンツをダウンロード中 @@ -2230,6 +2255,7 @@ STR_MISSING_GRAPHICS_YES_DOWNLOAD :{BLACK}はい STR_MISSING_GRAPHICS_NO_QUIT :{BLACK}いいえ、OpenTTDを終了します STR_MISSING_GRAPHICS_ERROR_TITLE :{WHITE}ダウンロードに失敗しました +STR_MISSING_GRAPHICS_ERROR :{BLACK}グラフィックのダウンロードに失敗しました。{}手動でダウンロードしてください。 # Transparency settings window STR_TRANSPARENCY_CAPTION :{WHITE}透過表示設定 @@ -2249,6 +2275,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}貨物 STR_LINKGRAPH_LEGEND_ALL :{BLACK}全て STR_LINKGRAPH_LEGEND_NONE :{BLACK}なし STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}表示する会社を選択 +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}未使用(運送過多) @@ -2375,6 +2402,7 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}道路 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}軌道用トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}道路の建設/撤去を切り替えます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}軌道の建設/撤去を切り替えます +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}道路の種類を変更/アップグレードします.Shiftは、コスト見積もりの​​作成/表示を切り替えます STR_ROAD_NAME_TRAM :トラムウェイ @@ -2465,6 +2493,7 @@ STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}ラン STR_TREES_RANDOM_TREES_BUTTON :{BLACK}ランダムに広域植林 STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}地表全体にランダムに植林します STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}グローブ +STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}風景をドラッグして小さな森を植えます STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}風景の上をドラッグして、大きな森を植えます。 # Land generation window (SE) @@ -2524,6 +2553,7 @@ STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}費用: STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}調査/探鉱 STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}建設 STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}出資 +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}すべての産業を削除してもよろしいですか? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}産業:{STRING}に関わる産業チェーン @@ -2670,22 +2700,36 @@ STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD # Framerate display window STR_FRAMERATE_CAPTION :{WHITE}フレームレート STR_FRAMERATE_RATE_BLITTER :{BLACK}グラフィックフレームレート:{STRING} +STR_FRAMERATE_SPEED_FACTOR :{BLACK}現在のゲーム速度:{DECIMAL} x +STR_FRAMERATE_CURRENT :{WHITE}現在 +STR_FRAMERATE_AVERAGE :{WHITE}平均 +STR_FRAMERATE_MEMORYUSE :{WHITE}メモリ STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL} ms STR_FRAMERATE_MS_WARN :{YELLOW} {DECIMAL} ms STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL} フレーム/秒 STR_FRAMERATE_FPS_WARN :{YELLOW} {DECIMAL}フレーム/秒 +STR_FRAMERATE_FPS_BAD :{RED} {DECIMAL}FPS STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES} ############ Leave those lines in this order!! STR_FRAMERATE_GAMELOOP :{BLACK}ゲームループの合計: STR_FRAMERATE_GL_ECONOMY :{BLACK}貨物の取り扱い: +STR_FRAMERATE_GL_TRAINS :{BLACK} 鉄道車両のティック: +STR_FRAMERATE_GL_ROADVEHS :{BLACK} 自動車ティック: +STR_FRAMERATE_GL_AIRCRAFT :{BLACK}航空機ティック: +STR_FRAMERATE_DRAWING :{BLACK}グラフィックレンダリング: STR_FRAMERATE_VIDEO :{BLACK}ビデオ出力: +STR_FRAMERATE_SOUND :{BLACK}サウンドミキサー: ############ End of leave-in-this-order ############ Leave those lines in this order!! STR_FRAMETIME_CAPTION_GAMELOOP :ゲームループ STR_FRAMETIME_CAPTION_GL_ECONOMY :貨物の取り扱い STR_FRAMETIME_CAPTION_GL_TRAINS :切符 +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :ワールドティック STR_FRAMETIME_CAPTION_GL_LINKGRAPH :リンクグラフの遅延 +STR_FRAMETIME_CAPTION_DRAWING :グラフィックレンダリング STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :ワールドビューポートレンダリング +STR_FRAMETIME_CAPTION_VIDEO :ビデオ出力 +STR_FRAMETIME_CAPTION_AI :AI {NUM} {STRING} ############ End of leave-in-this-order @@ -2711,8 +2755,10 @@ STR_SAVELOAD_DETAIL_CAPTION :{BLACK}ゲー STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}― 情報なし ― STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING} +STR_SAVELOAD_FILTER_TITLE :{BLACK}フィルター: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}ファイルを上書きする STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}既存のファイルを上書きしてもよろしいですか? +STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Parent directory) STR_SAVELOAD_OSKTITLE :{BLACK}保存名を入力 @@ -2724,6 +2770,14 @@ STR_MAPGEN_BY :{BLACK}× STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}街数: STR_MAPGEN_DATE :{BLACK}日付: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}産業数: +STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}最高峰: +STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}マップの最高峰の最大の高さを1減らします。 +STR_MAPGEN_SNOW_COVERAGE :{BLACK}降雪量: +STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}積雪量を10%減らします +STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK} {NUM}% +STR_MAPGEN_DESERT_COVERAGE :{BLACK}砂漠の範囲: +STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}砂漠の割合を10%増やします +STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}砂漠の範囲を10%減らします STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_LAND_GENERATOR :{BLACK}地形作成: STR_MAPGEN_TERRAIN_TYPE :{BLACK}地形種類: @@ -2750,6 +2804,8 @@ STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}ハイ STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}サイズ: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM} +STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}積雪量(%) +STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}砂漠領域(%) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}開始年の変更 # SE Map generation @@ -3004,6 +3060,7 @@ STR_TOWN_VIEW_RENAME_TOWN_BUTTON :街名を変更 # Town local authority window STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} 地方自治体 STR_LOCAL_AUTHORITY_ZONE :ゾーン +STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}地方自治体の境界を見る STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}社の評判: STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING} STR_LOCAL_AUTHORITY_ACTIONS_TITLE :{BLACK}可能な活動: @@ -3032,6 +3089,7 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}買収 # Goal window STR_GOALS_CAPTION :{WHITE}{COMPANY} 目標 STR_GOALS_SPECTATOR_CAPTION :{WHITE}大目標 +STR_GOALS_GLOBAL_BUTTON_HELPTEXT :{BLACK}グローバルな目標を表示する STR_GOALS_COMPANY_BUTTON :{BLACK}会社 STR_GOALS_COMPANY_BUTTON_HELPTEXT :{BLACK}会社の目標を見る STR_GOALS_TEXT :{ORANGE}{STRING} @@ -3234,6 +3292,7 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}本社 STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}本社ビルを移転します(費用は社の総資産の1%になります)。Shift+クリックで費用を見積もります STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}詳細 STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}インフラ設備の詳細な個数・タイル数を表示します +STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}この会社にお金を渡す STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}顔の変更 STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}社長の顔を変更します @@ -3251,6 +3310,7 @@ STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}この STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :会社名 STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :社長名 +STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION :寄付したい金額を入力してください STR_BUY_COMPANY_MESSAGE :{WHITE}現在、当{COMPANY}は業績悪化に伴い、債務の肩代わりを条件に社の全資産をお譲り致そうと考えております。{}{}債務{CURRENCY_LONG}を一括代済し、この会社を吸収合併しますか? @@ -3259,6 +3319,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION :{WHITE}{COMPANY STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT :{GOLD}線路長: STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS :{WHITE}信号 STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT :{GOLD}道路長(含軌道): +STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT :{GOLD}路面電車軌道: STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT :{GOLD}水運長: STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}運河 STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}停留施設数: @@ -3269,8 +3330,10 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENC # Industry directory STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}産業 STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- なし - +STR_INDUSTRY_DIRECTORY_ITEM_INFO :{BLACK}{CARGO_LONG}{STRING}{YELLOW} ({COMMA}% 輸送済み){BLACK} STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}産業の名前です - 名前をクリックするとこの産業拠点の場所にメイン画面を移動します。Ctrl+クリックでこの産業拠点の場所を新たなビューポートに表示します +STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}受け取った貨物: {SILVER}{STRING} STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :すべての貨物タイプ STR_INDUSTRY_DIRECTORY_FILTER_NONE :なし @@ -3283,6 +3346,7 @@ STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}生産 STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}この産業拠点は間もなく閉鎖されます! STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}必要条件:{YELLOW} {STRING} {STRING} +STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :、{STRING} {STRING} STR_INDUSTRY_VIEW_REQUIRES : {BLACK}必要物資: STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW} {STRING} {BLACK}:{CARGO_SHORT}待機中{STRING} @@ -3353,6 +3417,7 @@ STR_GROUP_RENAME_CAPTION :{BLACK}グル STR_GROUP_PROFIT_THIS_YEAR :今年の利益: STR_GROUP_PROFIT_LAST_YEAR :昨年の利益: +STR_GROUP_OCCUPANCY :選択中: # Build vehicle window STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION :新規機関車(非電化) @@ -3361,6 +3426,7 @@ STR_BUY_VEHICLE_TRAIN_MONORAIL_CAPTION :新規モノレ STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :新規リニア車両 STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :新規車両 +STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :新しい路面電車車両 ############ range for vehicle availability starts STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :新規列車 @@ -3369,6 +3435,7 @@ STR_BUY_VEHICLE_AIRCRAFT_CAPTION :新規航空機 ############ range for vehicle availability ends STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}価格: {GOLD}{CURRENCY_LONG}{BLACK} 重量: {GOLD}{WEIGHT_SHORT} +STR_PURCHASE_INFO_COST_REFIT_WEIGHT :{BLACK}コスト:{GOLD} {CURRENCY_LONG} {BLACK}(修理コスト:{GOLD} {CURRENCY_LONG} {BLACK})重量:{GOLD} {WEIGHT_SHORT} STR_PURCHASE_INFO_SPEED_POWER :{BLACK}最高速度: {GOLD}{VELOCITY}{BLACK} 出力: {GOLD}{POWER} STR_PURCHASE_INFO_SPEED :{BLACK}最高速度: {GOLD}{VELOCITY} STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}外洋/湖での航行速度: {GOLD}{VELOCITY} @@ -3392,6 +3459,7 @@ STR_PURCHASE_INFO_ENGINES_ONLY :エンジンの STR_PURCHASE_INFO_ALL_BUT :{CARGO_LIST}を除いてすべて STR_PURCHASE_INFO_MAX_TE :{BLACK}最大牽引力: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}航続距離: {GOLD}{COMMA} タイル +STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}航空機の機種: {GOLD}{STRING} STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}列車リスト - 個々の情報を見るには列車をクリックします。Ctrl+クリックでその列車種の表示/非表示を切り替えます STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}車両リスト - 個々の情報を見るには車両をクリックします。Ctrl+クリックでその車両種の表示/非表示を切り替えます @@ -3403,12 +3471,15 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_BUTTON :{BLACK}車両 STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}船舶を購入 STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}航空機を購入 +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}購入し改造する +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}船の購入と修理 STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}選択した列車を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}選択した車両を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}選択した船舶を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}選択した航空機を購入します。Shift+クリックで購入費を見積もります +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}ハイライトされた船を購入して修理します。Shift +クリックすると、購入なしの推定コストが表示されます STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}名称を変更 STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}名称を変更 @@ -3524,6 +3595,7 @@ STR_ENGINE_PREVIEW_MONORAIL_LOCOMOTIVE :モノレール STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :リニア列車 STR_ENGINE_PREVIEW_ROAD_VEHICLE :車両 +STR_ENGINE_PREVIEW_TRAM_VEHICLE :路面電車車両 STR_ENGINE_PREVIEW_AIRCRAFT :航空機 STR_ENGINE_PREVIEW_SHIP :船舶 @@ -3571,6 +3643,7 @@ STR_REPLACE_ELRAIL_VEHICLES :機関車(電 STR_REPLACE_MONORAIL_VEHICLES :モノレール車両 STR_REPLACE_MAGLEV_VEHICLES :リニア車両 +STR_REPLACE_ROAD_VEHICLES :道路車両 STR_REPLACE_TRAM_VEHICLES :路面電車の車両 STR_REPLACE_REMOVE_WAGON :{BLACK}列車の短縮: {ORANGE}{STRING} @@ -3611,6 +3684,8 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}車両 STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}船舶の情報を表示 STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}航空機の情報を表示します +STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}現在の列車の動作-クリックして列車を停止/開始します +STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}現在の車両の動作-クリックして車両を停止/開始します STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}現在の船のアクション-クリックして船を停止/開始します STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}現在の航空機のアクション-クリックして航空機を停止/開始します @@ -3653,6 +3728,8 @@ STR_VEHICLE_INFO_AGE :{COMMA}年({COM STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA}年({COMMA}年) STR_VEHICLE_INFO_MAX_SPEED :{BLACK}最高速度: {LTBLUE}{VELOCITY} +STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}最高速度: {LTBLUE}{VELOCITY} {BLACK}航空機のタイプ: {LTBLUE}{STRING} +STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :{BLACK}最高速度: {LTBLUE}{VELOCITY} {BLACK}航空機のタイプ: {LTBLUE}{STRING} {BLACK}範囲: {LTBLUE}{COMMA}タイル STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}重量: {LTBLUE}{WEIGHT_SHORT} {BLACK}出力: {LTBLUE}{POWER}{BLACK} 最高速度: {LTBLUE}{VELOCITY} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}重量: {LTBLUE}{WEIGHT_SHORT} {BLACK}出力: {LTBLUE}{POWER}{BLACK} 最高速度: {LTBLUE}{VELOCITY} {BLACK}最大牽引力: {LTBLUE}{FORCE} @@ -3838,6 +3915,7 @@ STR_ORDER_REFIT_STOP_ORDER :({STRING}に改 STR_ORDER_STOP_ORDER :(運用停止) STR_ORDER_GO_TO_STATION :{1:STATION}へ{0:STRING} {2:STRING} +STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(駅を使用できません){POP_COLOUR} {STRING} {STATION} {STRING} STR_ORDER_IMPLICIT :(自動) @@ -4016,7 +4094,9 @@ STR_AI_LIST_ACCEPT_TOOLTIP :{BLACK}選択 STR_AI_LIST_CANCEL :{BLACK}キャンセル STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}スクリプトを変更しません +STR_SCREENSHOT_ZOOMIN_SCREENSHOT :{BLACK}スクリーンショットを完全に拡大 STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}地図全体のスクリーンショット +STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}ハイトマップスクリーンショット # AI Parameters STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} パラメータ @@ -4076,6 +4156,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :このファイ STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :ファイルを読み込むことができません STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :ファイルに書き込むことができません STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :データ保全性チェック失敗 +STR_GAME_SAVELOAD_ERROR_PATCHPACK :安定版のセーブデータです。 STR_GAME_SAVELOAD_NOT_AVAILABLE :<使用不能> STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}このゲームは路面電車に対応していないバージョンで保存されましたので、すべての路面電車が削除されました。 @@ -4283,6 +4364,7 @@ STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}この輸送機器の自動置換/更新は行われませんでした STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(最低資金が確保できていません) STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}新しい車両は{STRING}を運ぶことができません +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}新しい車両は順番に修理できません{NUM} # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}不可能な線路の組み合わせです @@ -4291,6 +4373,7 @@ STR_ERROR_NO_SUITABLE_RAILROAD_TRACK :{WHITE}適当 STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}先に線路を撤去しなければなりません STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}道路は一方通行または進入禁止です STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}このレール種別との平面交差はできません +STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}この道路では踏切は作れません STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}ここには信号を設置できません STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}ここには線路を建設できません STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}ここから線路を撤去できません @@ -4311,6 +4394,9 @@ STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}ここ STR_ERROR_THERE_IS_NO_ROAD :{WHITE}道路がありません STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}軌道がありません STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}この道路のタイプは変更できません +STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}ここで路面電車の種類を変更できません... +STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}有効な路面電車がありません +STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}軌道に互換性がありません # Waterway construction errors STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}ここには運河を建設できません @@ -4862,6 +4948,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} ブイ STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} 第{COMMA}ブイ STR_FORMAT_COMPANY_NUM :(会社{COMMA}) STR_FORMAT_GROUP_NAME :グループ {COMMA} +STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA} STR_FORMAT_INDUSTRY_NAME :{TOWN}{STRING} STR_FORMAT_WAYPOINT_NAME :{TOWN}中継駅 STR_FORMAT_WAYPOINT_NAME_SERIAL :第{1:COMMA} {0:TOWN}中継駅 diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 3495651e76..471de45fc3 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -1992,6 +1992,7 @@ STR_FACE_TIE :넥타이: STR_FACE_EARRING :귀걸이: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}넥타이/귀걸이 변경 + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}멀티 플레이 STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}플레이어 이름: @@ -2054,10 +2055,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}멀티 STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}비밀번호 설정 STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}서버에 공개적으로 접근하는 것을 막고 싶을 때 비밀번호를 걸어 보호합니다. -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}공개 여부 -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}공개된 게임(인터넷)과 비공개된 게임(LAN) 중에서 선택하세요 -STR_NETWORK_START_SERVER_UNADVERTISED :아니요 -STR_NETWORK_START_SERVER_ADVERTISED :예 STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM}명 STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}최대 접속자 수: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}최대 접속자 수를 선택합니다. 모든 자리가 다 차 있을 필요는 없습니다 @@ -2119,19 +2116,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}접속 STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}서버 암호가 걸려있습니다. 암호를 입력하세요 STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}회사 암호가 걸려있습니다. 암호를 입력하세요 -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}접속자 목록 # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :접속자 목록 -STR_NETWORK_COMPANY_LIST_SPECTATE :관전 -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :새 회사 # Network client list -STR_NETWORK_CLIENTLIST_KICK :추방 -STR_NETWORK_CLIENTLIST_BAN :차단 -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :모두에게 말하기 -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :이 회사에게 말하기 -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :귓속말하기 + + STR_NETWORK_SERVER :서버 STR_NETWORK_CLIENT :접속자 @@ -2176,6 +2167,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}서버 STR_NETWORK_ERROR_CLIENT_START :{WHITE}접속할 수 없습니다 STR_NETWORK_ERROR_TIMEOUT :{WHITE}접속자 #{NUM}의 입력 시간이 초과되었습니다 STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}프로토콜 오류가 발생되어 연결이 끊어졌습니다 +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}플레이에 사용할 이름을 설정하지 않았습니다. 이름은 멀티플레이 창의 상단에서 설정할 수 있습니다. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}이 접속자의 게임 버전이 서버의 버전과 일치하지 않습니다 STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}잘못된 비밀번호입니다 STR_NETWORK_ERROR_SERVER_FULL :{WHITE}서버에 인원이 가득 찼습니다 @@ -2188,6 +2180,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}비밀 STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}사용자의 컴퓨터가 서버와 연결을 유지할 수 있을 만큼 빠르지 않습니다 STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}지도 다운로드 시간을 초과하였습니다 STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}서버 접속 시간을 초과하였습니다 +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}사용할 수 없는 이름입니다 ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :일반 오류 @@ -2210,6 +2203,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :제 시간에 STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :반응 시간 초과 STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :지도 다운로드 시간 초과 STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :지도 생성 / 입장 시간 초과 +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :유효하지 않은 클라이언트 이름 ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}가능한 연결 손실 diff --git a/src/lang/latin.txt b/src/lang/latin.txt index a6eeb3cca2..4d7f6a2980 100644 --- a/src/lang/latin.txt +++ b/src/lang/latin.txt @@ -2088,6 +2088,7 @@ STR_FACE_TIE :Focale: STR_FACE_EARRING :Inauris: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Mutare focale vel inaurem + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Modus Plurium Lusorum STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nomen lusoris: @@ -2146,10 +2147,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Hoc ludi STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Elige tesseram STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Custodire tessera ludum tuum, si non vis publicos iungere -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Ostensum -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Eligere servatrum ostensum (interretis) aut non ostensum (LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Non -STR_NETWORK_START_SERVER_ADVERTISED :Ita STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} clien{P s tes} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Clientes maximi: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Eligere numerum maximum clientorum. Necesse non est omnes loci pleni esse @@ -2211,19 +2208,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Disiunge STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servatrum tutum est. Tesseram inscribe STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Societas tuta est. Tesseram inscribe -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Index clientum # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Index clientum -STR_NETWORK_COMPANY_LIST_SPECTATE :Spectare -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Societas Nova # Network client list -STR_NETWORK_CLIENTLIST_KICK :Dimittere -STR_NETWORK_CLIENTLIST_BAN :Expellere -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Ad omnes loqui -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Ad societatem loqui -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Ad clientem loqui + + STR_NETWORK_SERVER :Servatrum STR_NETWORK_CLIENT :Cliens diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index f1a2888642..5fbf0616c0 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -1960,6 +1960,7 @@ STR_FACE_TIE :Kaklasaite: STR_FACE_EARRING :Auskars: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Mainīt kaklasaiti vai auskarus + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Vairākspēlētāju spēle STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spēlētāja vārds: @@ -2022,10 +2023,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Spēles STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Uzstādīt paroli STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Aizsargā jūsu spēli ar paroli, ja nevēlaties lai tā būtu publiski pieejama -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Izsludināt -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Izvēlieties starp reklamēto (interneta) un nereklamēto (lokālā tīkla, LAN) spēli -STR_NETWORK_START_SERVER_UNADVERTISED :Nē -STR_NETWORK_START_SERVER_ADVERTISED :Jā STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} spēlētāj{P s i u} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maksimālais spēlētāju skaits: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Izvēlēties maksimālo spēlētāju skaitu. Ne visiem slotiem ir jābūt aizpildītiem @@ -2087,19 +2084,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Atvienot STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Serveris ir aizsargāts. Ievadiet paroli STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Uzņēmums ir aizsargāts. Ievadiet paroli -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Klientu saraksts # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spēlētāju saraksts -STR_NETWORK_COMPANY_LIST_SPECTATE :Skatīt -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Jauns uzņēmums # Network client list -STR_NETWORK_CLIENTLIST_KICK :Izmest -STR_NETWORK_CLIENTLIST_BAN :Aizliegt -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Runāt ar visiem -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Runāt ar uzņēmumu -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privāts ziņojums + + STR_NETWORK_SERVER :Serveris STR_NETWORK_CLIENT :Spēlētājs diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt index e5816348c2..b90ee4e996 100644 --- a/src/lang/lithuanian.txt +++ b/src/lang/lithuanian.txt @@ -2204,6 +2204,7 @@ STR_FACE_TIE :Kaklaraištis: STR_FACE_EARRING :Auskaras: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Pakeisti kaklaraištį arba auskarą + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Žaidimas tinkle STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Žaidėjo vardas: @@ -2266,10 +2267,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Žaidimo STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Nustatyti slaptažodi STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Apsaugokite savo žaidimą slaptažodžiu, jei nenorite, kad jis būtų viešai prieinamas -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Reklamuoti -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Pasirinkite tarp reklamuojamo (internetas) ir nereklamuojamo (Vietinis Tinklas, LAN) žaidimo -STR_NETWORK_START_SERVER_UNADVERTISED :Ne -STR_NETWORK_START_SERVER_ADVERTISED :Taip STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P as ai ų} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Didžiausias klientų skaičius: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Pasirinkite didžiausią klientų skaičių. Nebūtinai visos jungtys turi būti užpildytos @@ -2331,19 +2328,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Atsijung STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Serveris apsaugotas. Įvesk slaptažodį STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Kompanija apsaugota. Įvesk slaptažodį -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Žaidėjų sąrašas # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Žaidėjų sąrašas -STR_NETWORK_COMPANY_LIST_SPECTATE :Stebėti -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nauja įmonė # Network client list -STR_NETWORK_CLIENTLIST_KICK :Išmesti (Kick) -STR_NETWORK_CLIENTLIST_BAN :Užblokuoti -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Sakyti visiems -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Sakyti kompanijai -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privati žinutė + + STR_NETWORK_SERVER :Serveris STR_NETWORK_CLIENT :Žaidėjas diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index a5c21ae4a0..1730014d4a 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -1985,6 +1985,7 @@ STR_FACE_TIE :Krawatt: STR_FACE_EARRING :Ouerréng: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Krawatt oder Ouerréng änneren + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spillernumm: @@ -2047,10 +2048,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Den Numm STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Passwuert setzen STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}En Passwuert fir d'Spill setzen, dass et net Public accessibel ass -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Ugekënnegt -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Wiel tëschent engem ugekënnegten (Internet) an net ugekënnegten (LAN) Spill -STR_NETWORK_START_SERVER_UNADVERTISED :Nee -STR_NETWORK_START_SERVER_ADVERTISED :Jo STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} Spiller STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximal Spiller: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Maximal Unzuel vun de Clients. Et muss net all Slot gefëllt sinn. @@ -2112,19 +2109,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Verbindu STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server ass geschützt. Passwuert aginn STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firma ass geschützt. Passwuert aginn -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Spillerlëscht # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spillerlëscht -STR_NETWORK_COMPANY_LIST_SPECTATE :Nokucken -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nei Firma # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kicken -STR_NETWORK_CLIENTLIST_BAN :Bannen -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Mat alle schwetzen -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Mat der Firma schwetzen -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privatmessage + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Spiller diff --git a/src/lang/macedonian.txt b/src/lang/macedonian.txt index 064d0b8e91..844bfd0a36 100644 --- a/src/lang/macedonian.txt +++ b/src/lang/macedonian.txt @@ -960,6 +960,7 @@ STR_ABANDON_GAME_QUERY :{YELLOW}Дал # Face selection window + # Network server list STR_NETWORK_SERVER_LIST_GENERAL_ONLINE :{BLACK}{COMMA}/{COMMA} - {COMMA}/{COMMA} @@ -994,6 +995,8 @@ STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT :{BLACK}{COMMA}x # Network client list + + # Network set password # Network company info join/password diff --git a/src/lang/malay.txt b/src/lang/malay.txt index 76a99e9b06..1507365150 100644 --- a/src/lang/malay.txt +++ b/src/lang/malay.txt @@ -1631,6 +1631,7 @@ STR_FACE_TIE :Tali leher: STR_FACE_EARRING :Anting-anting: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Tukar tali leher atau anting-anting + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Pemain berbilang STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nama pemain: @@ -1689,7 +1690,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nama per STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Tetapkan kata laluan STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Lindungi permainan anda dengan kata laluan jika anda tidak mahu ianya diakses awam -STR_NETWORK_START_SERVER_UNADVERTISED :Tidak STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} pelanggan STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Amaun maksimum pemain: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Tentukan bilangan klien maks. Tidak perlu semua slot diisi @@ -1754,15 +1754,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Syarikat # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Senarai klien -STR_NETWORK_COMPANY_LIST_SPECTATE :Saksi -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Syarikat baru # Network client list -STR_NETWORK_CLIENTLIST_KICK :Tendang -STR_NETWORK_CLIENTLIST_BAN :Larang -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Cakap kepada semua -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Cakap kepada syarikat -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Pesanan peribadi + + STR_NETWORK_SERVER :Pelayan STR_NETWORK_CLIENT :Klien diff --git a/src/lang/maltese.txt b/src/lang/maltese.txt index ea5b7518d8..58f13463c4 100644 --- a/src/lang/maltese.txt +++ b/src/lang/maltese.txt @@ -528,6 +528,7 @@ STR_CHEAT_CHANGE_DATE_QUERY_CAPT :{WHITE}Ibdel is # Face selection window + # Network server list STR_NETWORK_SERVER_LIST_GENERAL_ONLINE :{BLACK}{COMMA}/{COMMA} - {COMMA}/{COMMA} @@ -564,6 +565,8 @@ STR_NETWORK_CONNECTING_DOWNLOADING_2 :{BLACK}{BYTES} # Network client list + + # Network set password # Network company info join/password diff --git a/src/lang/marathi.txt b/src/lang/marathi.txt index e7ac24eac5..8f4c7fbac3 100644 --- a/src/lang/marathi.txt +++ b/src/lang/marathi.txt @@ -892,6 +892,7 @@ STR_FACE_LIPS_MOUSTACHE_TOOLTIP :{BLACK}ओठ STR_FACE_CHIN :हनुवटी: STR_FACE_CHIN_TOOLTIP :{BLACK}हनुवटी बदला + # Network server list STR_NETWORK_SERVER_LIST_GAME_NAME :{BLACK}नाव @@ -934,6 +935,8 @@ STR_NETWORK_CONNECTING_DOWNLOADING_2 :{BLACK}{BYTES} # Network client list + + # Network set password # Network company info join/password diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 9e65d9502e..623c346ac1 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -995,6 +995,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Hver 12. måned STR_GAME_OPTIONS_LANGUAGE :{BLACK}Språk STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Velg språk som skal brukes +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% fullført) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Fullskjerm STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Kryss av denne knappen for å spille OpenTTD i fullskjermmodus @@ -1993,6 +1994,7 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Ørering: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Endre slips eller ørering + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Flerspiller STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spillernavn: @@ -2055,10 +2057,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Spillnav STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Sett passord STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beskytt ditt spill med et passord hvis du ikke vil at hvem som helst skal bli med på det -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Annonsert -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Velg mellom et utlyst (internett) og et ikke utlyst (Lokalnettverk, LAN) spill -STR_NETWORK_START_SERVER_UNADVERTISED :Nei -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" er} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maks antall klienter: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS.small :dra og slipp @@ -2121,19 +2119,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Koble fr STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Tjeneren er beskyttet. Skriv inn passord STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firmaet er beskyttet. Skriv inn passord -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Klientliste # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste over klienter -STR_NETWORK_COMPANY_LIST_SPECTATE :Vær tilskuer -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nytt firma # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kast ut -STR_NETWORK_CLIENTLIST_BAN :Bannlys -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Snakk til alle -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Snakk til firma -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privat melding + + STR_NETWORK_SERVER :Tjener STR_NETWORK_CLIENT :Klient @@ -2178,6 +2170,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Kunne ik STR_NETWORK_ERROR_CLIENT_START :{WHITE}Kunne ikke opprette forbindelse STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tilkobling #{NUM} ble tidsavbrutt STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Forbindelsen ble brutt pga. en protokollfeil +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Spillernavnet ditt er ikke angitt. Navnet kan angis øverst i flerspillervinduet STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Klientversjonen er ikke den samme som tjenerversjonen STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Feil passord STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Tjeneren er full @@ -2190,6 +2183,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Du brukt STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Din datamaskin er ikke rask nok til å holde følge med tjeneren STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Din datamaskin brukte for lang tid på å laste ned kartet STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Din datamaskin brukte for lang tid på å koble til tjeneren +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Spillernavnet ditt er ugyldig ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :generell feil @@ -2212,6 +2206,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :mottok ikke pas STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :generelt tidsavbrudd STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :nedlasting av kart tok for lang tid STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :behandling av kartet tok for lang tid +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :ugyldig klientnavn ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Mulig tap av tilkobling diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt index 9488472931..515ffbed97 100644 --- a/src/lang/norwegian_nynorsk.txt +++ b/src/lang/norwegian_nynorsk.txt @@ -1793,6 +1793,7 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Øyrering: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Byt slips eller øyrering + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Fleirspelar STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spelarnamn: @@ -1851,10 +1852,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Spelnamn STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Set passord STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beskytt spelet ditt med passord så ikkje kven som helst kan verte med på det -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Kunngjort -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Vel mellom spel på internett (kunngjort) og spel på lokalt nett (ikkje kunngjort) -STR_NETWORK_START_SERVER_UNADVERTISED :Nei -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" er} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maks. antal tilletne klientar: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Vel maks. antal klientar. Alle plassane treng ikkje å verte tekne @@ -1919,15 +1916,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firmaet # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste over klientar -STR_NETWORK_COMPANY_LIST_SPECTATE :Vær tilskodar -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nytt firma # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kast ut -STR_NETWORK_CLIENTLIST_BAN :Svartelist -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Snakk til alle -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Snakk til firma -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privat melding + + STR_NETWORK_SERVER :Tenar STR_NETWORK_CLIENT :Klient diff --git a/src/lang/persian.txt b/src/lang/persian.txt index ac5c6ae40c..a6c6a03bcd 100644 --- a/src/lang/persian.txt +++ b/src/lang/persian.txt @@ -1591,6 +1591,7 @@ STR_FACE_TIE :کراوات: STR_FACE_EARRING :گوشواره: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}تغییر کراوات یا گوشواره + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}چندنفره STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}نام بازیگر: @@ -1649,9 +1650,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}بازی STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}ثبت رمز STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}اگر بازی برای استفاده همگان نیست، بازی خود را با رمز محافظت کنید -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}تبلیغ دار -STR_NETWORK_START_SERVER_UNADVERTISED :خیر -STR_NETWORK_START_SERVER_ADVERTISED :بله STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} سرویس گیرنده STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}بیشترین تعداد سرویس گیرنده: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}بیشترین تعداد سرویس گیرنده را مشخص کنید.لازم نیست دقیقا به تعداد نفرات باشد @@ -1716,15 +1714,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}شرکت # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :{WHITE}لیست سرویس گیرنده ها -STR_NETWORK_COMPANY_LIST_SPECTATE :{WHITE}تماشا -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :{WHITE}شرکت جدید # Network client list -STR_NETWORK_CLIENTLIST_KICK :اخراج -STR_NETWORK_CLIENTLIST_BAN :قدغن کردن -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :گفتگو با همه -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :گفتگو با شرکت -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :پیام خصوصی + + STR_NETWORK_SERVER :سرویس دهنده STR_NETWORK_CLIENT :سرویس گیرنده diff --git a/src/lang/polish.txt b/src/lang/polish.txt index d2d888b189..d6af6dc64d 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -2371,6 +2371,7 @@ STR_FACE_TIE :Krawat: STR_FACE_EARRING :Kolczyk: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Zmień krawat lub kolczyk + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Gra wieloosobowa STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nazwa gracza: @@ -2433,10 +2434,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nazwa gr STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Ustaw hasło STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Zabezpiecz grę hasłem jeśli nie chcesz, by była publicznie dostępna -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Publiczny -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Wybierz między rozgrywkami reklamowanymi (internetowymi) a niereklamowanymi (w sieci lokalnej LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Nie -STR_NETWORK_START_SERVER_ADVERTISED :Tak STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" ów ów} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Dopuszczalna liczba klientów: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Ustaw maksymalną liczbę klientów. Nie wszystkie pola muszą być wypełnione. @@ -2498,19 +2495,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Rozłąc STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Serwer jest chroniony. Wprowadź hasło STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firma jest chroniona. Wprowadź hasło -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Lista klientów # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista klientów -STR_NETWORK_COMPANY_LIST_SPECTATE :Obserwuj -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nowa firma # Network client list -STR_NETWORK_CLIENTLIST_KICK :Wyrzuć -STR_NETWORK_CLIENTLIST_BAN :Banuj -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Mów do wszystkich -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Mów do firmy -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Prywatna wiadomość + + STR_NETWORK_SERVER :Serwer STR_NETWORK_CLIENT :Klient diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 36742f76fe..fadf6b9f90 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -1991,6 +1991,7 @@ STR_FACE_TIE :Gravata: STR_FACE_EARRING :Brinco: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Mudar gravata ou brinco + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multi-jogador STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nome do jogador: @@ -2053,10 +2054,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}O nome d STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Definir palavra-chave STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Proteja o jogo com uma senha se não desejar que pessoas indesejadas se juntem -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Anunciado -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Escolher entre jogo público (internet) e privado (Área de Rede Local, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Não -STR_NETWORK_START_SERVER_ADVERTISED :Sim STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Máximo de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Escolha o número máximo de clientes. Não necessitam estar todos presentes. @@ -2118,19 +2115,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Desligar STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor protegido. Introduza palavra-chave STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introduza palavra-chave -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Lista de clientes # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes -STR_NETWORK_COMPANY_LIST_SPECTATE :Assistir -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nova empresa # Network client list -STR_NETWORK_CLIENTLIST_KICK :Expulsar -STR_NETWORK_CLIENTLIST_BAN :Banir -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Falar com todos -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Falar com a empresa -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Mensagem privada + + STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 847b41debf..60cb7a616e 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -1910,6 +1910,7 @@ STR_FACE_TIE :Cravată: STR_FACE_EARRING :Cercei: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Schimbă cravata sau cerceii + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multiplayer STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Numele jucătorului: @@ -1972,10 +1973,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Numele j STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Pune parolă STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protejează-ţi jocul cu o parolă dacă nu vrei să intre jucători neautorizaţi -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Publicat -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Alege între un joc publicat (prin Internet) și unul privat (reț) game -STR_NETWORK_START_SERVER_UNADVERTISED :Nu -STR_NETWORK_START_SERVER_ADVERTISED :Da STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Număr maxim de clienţi: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Alege un număr maxim de clienţi. Nu trebuie ocupate toate locurile. STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Companii maxim: @@ -2036,15 +2033,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Companie # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clienţi -STR_NETWORK_COMPANY_LIST_SPECTATE :Observă -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Companie nouă # Network client list -STR_NETWORK_CLIENTLIST_KICK :Dă afară -STR_NETWORK_CLIENTLIST_BAN :Interzice acces -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Vorbeşte către toţi -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Vorbeşte către companie -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Mesaj privat + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Client diff --git a/src/lang/russian.txt b/src/lang/russian.txt index df060c6a7c..de8c4f84cf 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -2142,6 +2142,7 @@ STR_FACE_TIE :Галстук: STR_FACE_EARRING :Серьга: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Изменить галстук или серьгу + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Сетевая игра STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Имя игрока: @@ -2204,10 +2205,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Назв STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Установить пароль STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Защитите вашу игру паролем, если не хотите, чтобы к ней могли подключиться посторонние. -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Интернет -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Выберите между игрой через Интернет, либо в локальной сети -STR_NETWORK_START_SERVER_UNADVERTISED :Нет -STR_NETWORK_START_SERVER_ADVERTISED :Да STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клиент{P "" а ов} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. количество клиентов: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбор максимального числа клиентов. Не все места должны быть заняты @@ -2269,19 +2266,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Откл STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Сервер защищён. Введите пароль. STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Компания защищена. Введите пароль. -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Список клиентов # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Список клиентов -STR_NETWORK_COMPANY_LIST_SPECTATE :Наблюдать -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Новая компания # Network client list -STR_NETWORK_CLIENTLIST_KICK :Отключить -STR_NETWORK_CLIENTLIST_BAN :Бан -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Сказать всем -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Говорить с компанией -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Личное сообщение + + STR_NETWORK_SERVER :Сервер STR_NETWORK_CLIENT :Клиент @@ -2326,6 +2317,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Не у STR_NETWORK_ERROR_CLIENT_START :{WHITE}Не удалось соединиться STR_NETWORK_ERROR_TIMEOUT :{WHITE}Истекло время ожидания соединения #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Произошла ошибка протокола, и соединение было закрыто +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Не указано имя игрока. Его можно ввести в верхней части окна «Сетевая игра». STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Версия этого клиента не совместима с версией сервера STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Неверный пароль STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен @@ -2338,6 +2330,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Вы н STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Ваш компьютер работает слишком медленно и не поспевает за сервером STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Ваш компьютер тратит много времени на загрузку карты STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Ваш компьютер тратит много времени на подключение к серверу +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Неверно указано имя игрока ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :общая ошибка @@ -2360,6 +2353,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :пароль н STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :время вышло STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :загрузка карты заняла слишком много времени STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :обработка карты заняла слишком много времени +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :имя клиента некорректно ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Подключение утеряно @@ -3269,7 +3263,7 @@ STR_NEWGRF_BROKEN :{WHITE}Файл STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}Меняется состояние локомотива «{1:ENGINE}», находящегося вне депо STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}Меняется длина транспорта «{1:ENGINE}», находящегося вне депо STR_NEWGRF_BROKEN_CAPACITY :{WHITE}Он изменил ёмкость ТС «{1:ENGINE}» за пределами депо или без задания на переоборудование -STR_BROKEN_VEHICLE_LENGTH :{WHITE}Поезд «{VEHICLE}», принадлежащий «{COMPANY}», имеет неправильную длину. Вероятно, это вызвано проблемами в файле новой графики (NewGRF). Игра может рассинхронизироваться или вылететь. +STR_BROKEN_VEHICLE_LENGTH :{WHITE}Поезд «{VEHICLE}», принадлежащий «{COMPANY}», имеет неправильную длину. Вероятно, это вызвано ошибками в одном из модулей NewGRF. Игра может рассинхронизироваться или вылететь. STR_NEWGRF_BUGGY :{WHITE}NewGRF «{0:STRING}» предоставляет неверную информацию. STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Информация о вместимости/переоборудовании для локомотива «{1:ENGINE}» после постройки отличается от сведений в списке покупки, что может помешать функции автообновления/автозамены корректно произвести переоборудование. diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt index 78fb879283..5079e879b7 100644 --- a/src/lang/serbian.txt +++ b/src/lang/serbian.txt @@ -2180,6 +2180,7 @@ STR_FACE_TIE :Kravata: STR_FACE_EARRING :Minđuše: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Promena kravate ili minđuša + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Mrežna partija STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Ime igrača: @@ -2242,10 +2243,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Naziv pa STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Postavi lozinku STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Ukoliko ne želite da bude javno dostupna zaštitite Vašu partiju lozinkom -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK} Sa reklamama -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Odaberite između igre s oglasima (internet) i bez oglasa (Local Area Network, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Ne -STR_NETWORK_START_SERVER_ADVERTISED :Da STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} igrač{P "" a a} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Najviše igrača: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Odaberite koliko najviše može da ima igrača. Nemoraju sva mesta da budu popunjena @@ -2307,19 +2304,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Isključ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server je zaštićen. Unesite lozinku STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Preduzeće je zaštićeno. Unesite lozinku -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Spisak klijenata # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spisak klijenata -STR_NETWORK_COMPANY_LIST_SPECTATE :Praćenje -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Novo preduzeće # Network client list -STR_NETWORK_CLIENTLIST_KICK :Izbaci -STR_NETWORK_CLIENTLIST_BAN :Zabrani pristup -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Razgovaraj sa svima -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Razgovaraj sa ekipom -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privatna poruka + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Igrač diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index 8b568b51dd..993736cc8f 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -1990,6 +1990,7 @@ STR_FACE_TIE :领带 STR_FACE_EARRING :耳环 STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}选择领带或是耳环 + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}联机游戏 STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}玩家名称: @@ -2052,10 +2053,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}游戏 STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}设置密码: STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}如果不希望你的游戏被外人加入,请设置一个密码 -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}发布到互联网 -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}选择是否将游戏发布到官方服务器列表。发布的话,可以让互联网上的玩家找到你的服务器并加入游戏,否则进行局域网内的游戏。 -STR_NETWORK_START_SERVER_UNADVERTISED :否 -STR_NETWORK_START_SERVER_ADVERTISED :是 STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} 客户端 STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}玩家数目: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}选择可以参加的玩家上限(达不到此数量仍然可以开始游戏) @@ -2117,19 +2114,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}断开 STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}服务器需要密码: STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}公司需要密码: -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}客户端列表 # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :客户端列表 -STR_NETWORK_COMPANY_LIST_SPECTATE :旁观 -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :新公司 # Network client list -STR_NETWORK_CLIENTLIST_KICK :踢出 -STR_NETWORK_CLIENTLIST_BAN :禁止 -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :向全体人广播 -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :向本公司广播 -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :私聊 + + STR_NETWORK_SERVER :服务器 STR_NETWORK_CLIENT :客户端 diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index c3e9dee60e..563fcaa41d 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -2053,6 +2053,7 @@ STR_FACE_TIE :Kravata: STR_FACE_EARRING :Náušnica: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Zmeniť kravatu alebo náušnicu + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Hra pre viac hráčov STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Meno hráča: @@ -2115,10 +2116,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Názov h STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Nastaviť heslo STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Zabezpeč hru heslom, ak nechceš povoliť verejný prístup -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Zverejnené -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Vyberte medzi zverejnenou (internet) alebo nezverejnenou (lokálna sieť, LAN) hrou -STR_NETWORK_START_SERVER_UNADVERTISED :Nie -STR_NETWORK_START_SERVER_ADVERTISED :Áno STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" i ov} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Maximálny počet klientov: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Zvoľ maximálny počet klientov. Môže sa ich pripojiť aj menej. @@ -2180,19 +2177,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Odpojiť STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server je chránený. Zadaj heslo STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Spoločnosť je chránená. Zadaj heslo -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Zoznam klientov # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Zoznam klientov -STR_NETWORK_COMPANY_LIST_SPECTATE :Pozorovať -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nová spoločnosť # Network client list -STR_NETWORK_CLIENTLIST_KICK :Vyhodit -STR_NETWORK_CLIENTLIST_BAN :Ban -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Napísať správu všetkým -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Napísať spoločnosti správu -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Súkromná správa + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient @@ -4436,14 +4427,14 @@ STR_ERROR_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Názov s STR_ERROR_CAN_T_CHANGE_PRESIDENT :{WHITE}Meno prezidenta sa nedá zmeniť... STR_ERROR_MAXIMUM_PERMITTED_LOAN :{WHITE}... úverovy limit je {CURRENCY_LONG} -STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemôžeš si požičať viac peňazí... +STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemôžete si požičať viac peňazí... STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... úver už bol splatený STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} potrebuješ STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Úver sa nedá splatiť... STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Nie je možné presunúť peniaze, ktoré sú požičané z banky... STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Nie je možné presunúť peniaze tejto spoločnosti... STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Spoločnosť nie je možné kúpiť ... -STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nemôžeš postaviť sídlo spoločnosti... +STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nemôžete tu postaviť sídlo spoločnosti... STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nemôžeš kúpiť 25% podiel v tejto spoločnosti... STR_ERROR_CAN_T_SELL_25_SHARE_IN :{WHITE}25% podiel v tejto spoločnosti sa nedá predať ... STR_ERROR_PROTECTED :{WHITE}S akciami tejto spoločnosti nie je zatiaľ možné obchodovať... @@ -4466,10 +4457,10 @@ STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... v ce STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... príliš veľa priemyslu STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nemožno vygenerovať priemysel... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING} sa tu nedá postaviť... -STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Nemôžeš tu postaviť tento typ priemyslu... +STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Nemôžete tu postaviť tento typ priemyslu... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... príliš blízko iného priemyslu STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... najskôr je potrebné založiť mesto -STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... povolené len jedno pre 1mesto +STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... povolené len jedno pre každé mesto STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200 :{WHITE}... môže byť postavené v mestách z populáciou väčšou ako 1200 STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}... môže byť postavené len v dažďovom pralese STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}... môže byť postavené len v púšti @@ -4485,13 +4476,13 @@ STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Nenašli STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Pre získanie lepšej mapy zmeňte parametre jej generovania # Station construction related errors -STR_ERROR_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Nemôžeš tu postaviť železničnú stanicu... -STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Nemôžeš tu postaviť autobusovú zastávku... +STR_ERROR_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Nemôžete tu postaviť železničnú stanicu... +STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Nemôžete tu postaviť autobusovú zastávku... STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nemôžeš tu postaviť vykládku... -STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Nemôžeš postaviť električkovú osobnú stanicu... -STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Nemôžeš postaviť električkovú nákladnú stanicu... -STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Nemôžeš tu postaviť prístav... -STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Nemôžeš tu postaviť letisko... +STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Nemôžete tu postaviť električkovú zastávku... +STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Nemôžete tu postaviť električkovú vykládku... +STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Nemôžete tu postaviť prístav... +STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Nemôžete tu postaviť letisko... STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Susedí z viacerými stanicami/výkladkami STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... stanica je príliš veľká @@ -4539,8 +4530,8 @@ STR_ERROR_BUOY_IN_THE_WAY :{WHITE}... bój STR_ERROR_BUOY_IS_IN_USE :{WHITE}... bóju používa iná spoločnosť! # Depot related errors -STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Nemôžeš tu postaviť vlakové depo... -STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Nemôžeš tu postaviť garáž... +STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Nemôžete tu postaviť vlakové depo... +STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Nemôžete tu postaviť garáž... STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Nemôžeš tu postaviť električkové depo... STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Nemôžeš tu postaviť lodenicu... @@ -4580,7 +4571,7 @@ STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Cesta je STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}Nie sú povolené priecestia pre tento typ železnice STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}Nie sú povolené priecestia pre tento typ cesty STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Nemôžeš tu umiestniť návestidlá... -STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Nemôžeš tu stavať železničné koľaje... +STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Nemôžete tu postaviť železničnú trať... STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Nemôžeš tu odstrániť železničné koľaje... STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Nemôžeš tu odstrániť návestidlá... STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}Tu nie je možné zameniť návestidlá... @@ -4592,7 +4583,7 @@ STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}Nemôže # Road construction errors STR_ERROR_MUST_REMOVE_ROAD_FIRST :{WHITE}Najprv treba odstrániť cestu STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION :{WHITE}... na jednosmerných cestách nie sú dovolené križovatky -STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}Nemôžeš tu postaviť cestu... +STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}Nemôžete tu postaviť cestu... STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}Nemôžeš tu stavať električkovú trať... STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Nemôžeš tu odstrániť cestu... STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Nemôžeš tu odstrániť električkovú trať... @@ -4606,15 +4597,15 @@ STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}... neko # Waterway construction errors STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Tu sa nedá postaviť vodný kanál... -STR_ERROR_CAN_T_BUILD_LOCKS :{WHITE}Tu sa nedá postaviť stavidlo... +STR_ERROR_CAN_T_BUILD_LOCKS :{WHITE}Nemôžete tu postaviť stavidlá... STR_ERROR_CAN_T_PLACE_RIVERS :{WHITE}Tu nie je možné umiestniť rieku... STR_ERROR_MUST_BE_BUILT_ON_WATER :{WHITE}... musíš postaviť na vode -STR_ERROR_CAN_T_BUILD_ON_WATER :{WHITE}... nemôžeš postaviť na vode -STR_ERROR_CAN_T_BUILD_ON_SEA :{WHITE}... nemôžeš postaviť na otvorenom mori +STR_ERROR_CAN_T_BUILD_ON_WATER :{WHITE}... nemôže byť postavené na vode +STR_ERROR_CAN_T_BUILD_ON_SEA :{WHITE}... nemôže byť postavené na otvorenom mori STR_ERROR_CAN_T_BUILD_ON_CANAL :{WHITE}... nemôže byť postavené na vodnom kanále STR_ERROR_CAN_T_BUILD_ON_RIVER :{WHITE}... nemôže byť postavené na rieke STR_ERROR_MUST_DEMOLISH_CANAL_FIRST :{WHITE}Najprv sa musí zbúrať vodný kanál -STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Tu nie je možné postaviť akvadukt... +STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Nemôžete tu postaviť akvadukt... # Tree related errors STR_ERROR_TREE_ALREADY_HERE :{WHITE}... strom tu už je @@ -4622,7 +4613,7 @@ STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE :{WHITE}... zlý STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Nemôžeš tu zasadiť strom... # Bridge related errors -STR_ERROR_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Nemôžeš tu postaviť most... +STR_ERROR_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Nemôžete tu postaviť most... STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Most musíš najskôr zbúrať STR_ERROR_CAN_T_START_AND_END_ON :{WHITE}Nemožno začať a skončiť na tom istom mieste STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT :{WHITE}Konce mosta nie sú v rovnakej výške @@ -4740,7 +4731,7 @@ STR_ERROR_CAN_T_ADD_ORDER_SHARED :{WHITE}... vozi STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Nemožno zdieľať zoznam príkazov ... STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST :{WHITE}Nie je možné prestať zdieľať zoznam príkazov... -STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Nemozno kopirovat zoznam prikazov ... +STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Nemožno kopírovať zoznam príkazov ... STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... príliš ďaleko z predchádzajúceho cieľa STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... lietadlo nemá dostatočný dosah diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt index d1614d12eb..c75a000e0b 100644 --- a/src/lang/slovenian.txt +++ b/src/lang/slovenian.txt @@ -2025,6 +2025,7 @@ STR_FACE_TIE :Kravata: STR_FACE_EARRING :Uhani: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Spremeni kravato ali uhane + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Več igralcev STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Ime igralca: @@ -2083,10 +2084,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Ime bo p STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Nastavi geslo STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Zaščiti igro z geslom, če želiš preprečiti dostop nepovabljenim -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Oglaševano -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Izberi med oglaševano (internet) in neoglaševano (Local Area Network, LAN) igro -STR_NETWORK_START_SERVER_UNADVERTISED :Ne -STR_NETWORK_START_SERVER_ADVERTISED :Da STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} gost{P "" a i ov} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Dovoljeno število gostov: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Izberite največje število gostov. Ni potrebno, da so vsi prisotni @@ -2151,15 +2148,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Podjetje # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Seznam gostov -STR_NETWORK_COMPANY_LIST_SPECTATE :Opazuj -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Novo podjetje # Network client list -STR_NETWORK_CLIENTLIST_KICK :Brcni -STR_NETWORK_CLIENTLIST_BAN :Blokiraj -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Pogovor vsem -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Pogovor podjetju -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Zasebno sporočilo + + STR_NETWORK_SERVER :Strežnik STR_NETWORK_CLIENT :Gost diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 3d1a705163..1af0a7fc4f 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -1992,6 +1992,7 @@ STR_FACE_TIE :Corbata: STR_FACE_EARRING :Pendientes: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambiar corbata o pendientes + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijugador STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nombre del jugador: @@ -2054,10 +2055,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}La parti STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Establecer contraseña STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Protege tu partida con una contraseña si no quieres que sea universalmente accesible -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Público -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Permite escoger entre una partida pública (internet) y una partida privada (LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :No -STR_NETWORK_START_SERVER_ADVERTISED :Sí STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Número máximo de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Selecciona el número máximo de clientes. No es necesario ocupar todos los espacios @@ -2119,19 +2116,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Desconec STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor protegido. Introduce la contraseña STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introduce la contraseña -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Lista de Clientes # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes -STR_NETWORK_COMPANY_LIST_SPECTATE :Observar -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nueva empresa # Network client list -STR_NETWORK_CLIENTLIST_KICK :Expulsar (Kick) -STR_NETWORK_CLIENTLIST_BAN :Prohibir (Ban) -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Hablar a todos -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Hablar a empresa -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Mensaje privado + + STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 0c81885e17..74b8b10cff 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -1992,6 +1992,7 @@ STR_FACE_TIE :Corbata: STR_FACE_EARRING :Aretes: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambiar corbata o aretes + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijugador STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Nombre del jugador: @@ -2054,10 +2055,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}La parti STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Establecer contraseña STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Proteger la partida con una contraseña para prevenir el acceso a otras personas -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Público -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Permitir escoger entre una partida pública (Internet) y una partida privada (LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :No -STR_NETWORK_START_SERVER_ADVERTISED :Sí STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} cliente{P "" s} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Número máximo de clientes: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Elegir el número máximo de clientes. No es necesario que se conecten todos @@ -2119,19 +2116,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Desconec STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor protegido. Introducir contraseña STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introducir contraseña -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Lista de clientes # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes -STR_NETWORK_COMPANY_LIST_SPECTATE :Observar -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nueva empresa # Network client list -STR_NETWORK_CLIENTLIST_KICK :Expulsar -STR_NETWORK_CLIENTLIST_BAN :Prohibir acceso -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Hablar a todos -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Hablar a una empresa -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Mensaje privado + + STR_NETWORK_SERVER :Servidor STR_NETWORK_CLIENT :Cliente @@ -2176,6 +2167,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}No se pu STR_NETWORK_ERROR_CLIENT_START :{WHITE}No se pudo conectar STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tiempo de espera agotado en conexión #{NUM} STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Se produjo un error de protocolo y la conexión fue cerrada +STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Aún no tienes nombre de jugador, pero lo puedes poner en la parte superior de la ventana de Multijugador. STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}La versión de este cliente no corresponde con la versión del servidor STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Contraseña incorrecta STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo @@ -2188,6 +2180,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Tardaste STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Tu computadora es demasiado lenta para seguir la velocidad del servidor STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Tu computadora tardó demasiado en descargar el mapa STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Tu computadora tardó demasiado en conectarse al servidor +STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Tu nombre de jugador no es válido ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :error general @@ -2210,6 +2203,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :no se recibió STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :tiempo agotado en general STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :la descarga del mapa tardó demasiado STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :el procesado del mapa tardó demasiado +STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nombre de cliente no válido ############ End of leave-in-this-order STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Posible pérdida de conexión diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 54bfa40661..d28125b9b1 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -1990,6 +1990,7 @@ STR_FACE_TIE :Slips: STR_FACE_EARRING :Örhänge: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Ändra slips eller örhänge + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Flera spelare STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Spelarnamn: @@ -2052,10 +2053,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Namnet p STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Bestäm lösenord STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Skydda spelet med ett lösenord så att inte andra än dem som har lösenordet kan gå med i spelet -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Publikt -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Välj mellan ett publikt (internet) eller icke publikt (Local Area Network. LAN) spel -STR_NETWORK_START_SERVER_UNADVERTISED :Nej -STR_NETWORK_START_SERVER_ADVERTISED :Ja STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" er} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Max antal tillåtna klienter: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Välj max antal tillåtna klienter. Alla platser måste inte fyllas. @@ -2117,19 +2114,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Koppla i STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servern är skyddad. Ange lösenord STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Företaget är skyddat. Ange lösenord -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Klientlista # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Klientlista -STR_NETWORK_COMPANY_LIST_SPECTATE :Åskåda -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Nytt företag # Network client list -STR_NETWORK_CLIENTLIST_KICK :Kasta ut -STR_NETWORK_CLIENTLIST_BAN :Bannlys -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Prata med alla -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Prata med alla i företaget -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Privat meddelande + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Klient diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt index 0f3b782e84..bfdd69caa2 100644 --- a/src/lang/tamil.txt +++ b/src/lang/tamil.txt @@ -1734,6 +1734,7 @@ STR_FACE_TIE :Tie: STR_FACE_EARRING :கம்மல்: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Tie அல்லது காதணியை மாற்றவும் + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}பல்வீரர் STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}விளையாடுபவரின் பெயர்: @@ -1789,9 +1790,6 @@ STR_NETWORK_START_SERVER_CAPTION :{WHITE}பு STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}விளையாட்டு பெயர்: STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}கடவுச்சொல்லினை அமைக்கவும் -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}விளம்பரப்படுத்தப்பட்ட -STR_NETWORK_START_SERVER_UNADVERTISED :இல்லை -STR_NETWORK_START_SERVER_ADVERTISED :ஆம் STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} விளையாடுபவர்{P "" கள்} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}அதிகபட்ச வீரர்கள்: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}வாடிக்கையாளர்களின் அதிகபட்ச எண்ணிக்கையைத் தேர்வுசெய்க. எல்லா இடங்களும் நிரப்பப்பட வேண்டியதில்லை @@ -1850,19 +1848,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}இண STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}சர்வர் காக்கப்பட்டுள்ளது. கடவுச்சொல்லினை இடவும் STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}நிற்வனம் காக்கப்பட்டுள்ளது. கடவுச்சொல்லினை இடவும் -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}விளையாடுவோர் பட்டியல் # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :விளையாடுவோர் பட்டியல் -STR_NETWORK_COMPANY_LIST_SPECTATE :கவனி -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :புதிய நிறுவனம் # Network client list -STR_NETWORK_CLIENTLIST_KICK :உதை -STR_NETWORK_CLIENTLIST_BAN :அனுமதிக்காதே -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :அனைவருடனும் பேசு -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :நிறுவனத்திடம் பேசு -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :இரகசிய தகவல் + + STR_NETWORK_SERVER :சர்வர் STR_NETWORK_CLIENT :Client diff --git a/src/lang/thai.txt b/src/lang/thai.txt index 2a3b5aed10..9bc03a74b3 100644 --- a/src/lang/thai.txt +++ b/src/lang/thai.txt @@ -1820,6 +1820,7 @@ STR_FACE_TIE :เนคไท STR_FACE_EARRING :ต่างหู: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}เปลี่ยนเนคไทหรือต่างหู + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}เล่นหลายคน STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}ชื่อผู้เล่น: @@ -1878,10 +1879,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}ชื STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}กำหนดรหัสผ่าน STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}ป้องกันเกมด้วยรหัสผ่านหากไม่ต้องการให้มีการเข้าร่วมจากบุคคลทั่วไป -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}การประกาศ -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}เลือกระหว่างการโฆษณา (internet) หรือไม่โฆษณา (Local Area Network, LAN) เกม -STR_NETWORK_START_SERVER_UNADVERTISED :ไม่ใช่ -STR_NETWORK_START_SERVER_ADVERTISED :ใช่ STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} ลูกข่าย STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}ลูกข่ายสูงสุด: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}เลือกจำนวนมากสุดของลูกข่าย (ไม่จำเป็นต้องครบตามจำนวนนี้) @@ -1946,15 +1943,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}บร # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :รายการลูกข่าย -STR_NETWORK_COMPANY_LIST_SPECTATE :ผู้ชม -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :บริษัทใหม่ # Network client list -STR_NETWORK_CLIENTLIST_KICK :เตะ -STR_NETWORK_CLIENTLIST_BAN :แบน -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :พูดกับผู้เล่นทั้งหมด -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :พูดกับผู้เล่นในบริษัทเดียวกัน -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :ข้อความส่วนตัว + + STR_NETWORK_SERVER :เซิฟเวอร์ STR_NETWORK_CLIENT :ลูกข่าย diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index 99b446d669..7384d0a45b 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -1879,6 +1879,7 @@ STR_FACE_TIE :領帶: STR_FACE_EARRING :耳飾: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}改變領帶或耳飾 + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}多人遊戲 STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}玩家名稱: @@ -1939,10 +1940,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}遊戲 STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}設定密碼 STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}如果您不想讓大眾連線的話,可以用密碼保護遊戲 -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}已啟用宣傳 -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}選擇是否在互聯網上宣傳此遊戲 -STR_NETWORK_START_SERVER_UNADVERTISED :否 -STR_NETWORK_START_SERVER_ADVERTISED :是 STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} 玩家 STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}用戶端上限: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}選擇連線人數上限,但不是每個名額都要有人連線 @@ -2007,15 +2004,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}公司 # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :用戶端清單 -STR_NETWORK_COMPANY_LIST_SPECTATE :旁觀者 -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :新公司 # Network client list -STR_NETWORK_CLIENTLIST_KICK :踢除 -STR_NETWORK_CLIENTLIST_BAN :封鎖 -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :對全員說話 -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :對公司說話 -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :私人訊息 + + STR_NETWORK_SERVER :伺服器 STR_NETWORK_CLIENT :用戶端 diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index fb378c4c9f..cbedd61fae 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -1928,6 +1928,7 @@ STR_FACE_TIE :Kravat: STR_FACE_EARRING :Küpe: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Kravatı veya küpeyi değiştir + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Çok Oyunculu STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Oyuncu adı: @@ -1986,10 +1987,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Bu oyun STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Parola koy STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Erişimi kısıtlamak için oyuna parola koy -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Duyurulan -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Duyurulan (internet) ve duyurulmayan (yerel ağ, LAN) oyun türlerinden birini seçin -STR_NETWORK_START_SERVER_UNADVERTISED :Hayır -STR_NETWORK_START_SERVER_ADVERTISED :Evet STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} istemci STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Azami istemci sayısı: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}İzin verilen en fazla oyuncu sayısını seç. Her yerin dolması gerekmez @@ -2051,19 +2048,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Bağlant STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Sunucu korumalı. Parola girin STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Şirket korumalı. Parola girin -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}İstemci listesi # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Oyuncu listesi -STR_NETWORK_COMPANY_LIST_SPECTATE :Gözlemle -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Yeni şirket # Network client list -STR_NETWORK_CLIENTLIST_KICK :At -STR_NETWORK_CLIENTLIST_BAN :Yasakla -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Herkesle konuş -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Şirketle konuş -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Özel mesaj + + STR_NETWORK_SERVER :Sunucu STR_NETWORK_CLIENT :İstemci diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt index 0d26d41cc3..4ce593db54 100644 --- a/src/lang/ukrainian.txt +++ b/src/lang/ukrainian.txt @@ -2113,6 +2113,7 @@ STR_FACE_TIE :Краватк STR_FACE_EARRING :Сережки: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Змінити комір або сережки + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Мережева гра STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Ім'я гравця: @@ -2175,10 +2176,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Назв STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Встановити пароль STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Захистіть вашу гру паролем, якщо не бажаєте загального доступу -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Інтернет -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Вибір між рекламованою (інтернет) і не рекламованою (локальна мережа, LAN) грою -STR_NETWORK_START_SERVER_UNADVERTISED :Ні -STR_NETWORK_START_SERVER_ADVERTISED :Так STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клієнт{P "" а ів} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. клієнтів: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Виберіть максимальну кількість клієнтів. Не всі слоти мають бути зайняті @@ -2240,19 +2237,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Роз' STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Сервер захищено паролем. Введіть пароль STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Компанія захищена паролем. Введіть пароль -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Список клієнтів # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Список клієнтів -STR_NETWORK_COMPANY_LIST_SPECTATE :Спостерігати -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Нова компанія # Network client list -STR_NETWORK_CLIENTLIST_KICK :Відключити гравця -STR_NETWORK_CLIENTLIST_BAN :Бан -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Повідомлення всім -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Повідомлення компанії -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Приватне повідомлення + + STR_NETWORK_SERVER :Сервер STR_NETWORK_CLIENT :Клієнт diff --git a/src/lang/urdu.txt b/src/lang/urdu.txt index 70cb48636b..330cf32824 100644 --- a/src/lang/urdu.txt +++ b/src/lang/urdu.txt @@ -1482,6 +1482,7 @@ STR_FACE_TIE :ٹائی: STR_FACE_EARRING :بالیاں: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}ٹائی یا بالیاں بدلیں + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}زیادہ کھلاڑی STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}کھلاڑی کا نام: @@ -1604,15 +1605,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}کمپن # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :{WHITE}کلائینٹس کی فہرست -STR_NETWORK_COMPANY_LIST_SPECTATE :{WHITE}نظارہ کریں -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :{WHITE}نئی کمپنی # Network client list -STR_NETWORK_CLIENTLIST_KICK :ٹھڈا -STR_NETWORK_CLIENTLIST_BAN :پابندی -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :سب سے بات کریں -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :کمپنی سے بات کریں -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :پرائیویٹ پیغام + + STR_NETWORK_SERVER :سرور STR_NETWORK_CLIENT :کلائینٹ diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index da4bf597b5..389a8f4a19 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -1988,6 +1988,7 @@ STR_FACE_TIE :Cà vạt: STR_FACE_EARRING :Bông tai: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Thay đổi cà vạt hoặc bông tai + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Ván Chơi Mạng STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Tên người chơi: @@ -2050,10 +2051,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Tên c STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Đặt mật khẩu STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Bảo vệ game của bạn bằng mật khẩu nếu bạn không muốn người khác vào tùy tiện -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Đã quảng bá -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Lựa chọn ván chơi quảng bá (ra ngoài internet) và không quảng bá (Local Area Network, LAN) -STR_NETWORK_START_SERVER_UNADVERTISED :Không -STR_NETWORK_START_SERVER_ADVERTISED :Có STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} máy trạm STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Số máy trạm tối đa: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Chọn số lượng máy trạm tối đa. Không nhất thiết phải chọn đầy các dòng @@ -2115,19 +2112,13 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}Ngắt k STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server yêu cầu xác thực. Nhập mật khẩu STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Công ty yêu cầu xác thực. Nhập mật khẩu -STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}Danh sách máy trạm # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Danh sách máy trạm -STR_NETWORK_COMPANY_LIST_SPECTATE :Xem -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Công ty mới # Network client list -STR_NETWORK_CLIENTLIST_KICK :Đá -STR_NETWORK_CLIENTLIST_BAN :Cấm -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Nói với tất cả -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Nói cho công ty -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Thông điệp riêng + + STR_NETWORK_SERVER :Server STR_NETWORK_CLIENT :Máy trạm diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index f08bd8ff12..cff7088277 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -1877,6 +1877,7 @@ STR_FACE_TIE :Tei: STR_FACE_EARRING :Clustlws: STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Newid tei neu glustlws + # Network server list STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Amlchwaraewr STR_NETWORK_SERVER_LIST_PLAYER_NAME :{BLACK}Enw chwaraewr: @@ -1935,10 +1936,6 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Bydd y g STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Gosod cyfrinair STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Diogelwch eich gêm â chyfrinair os nad ydych am i fynediad ato fod yn gyhoeddus -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Hysbys -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Dewis rhwyd gêm a hysbysebir (rhyngrwyd) neu un anhysbys (rhwydwaith leol) -STR_NETWORK_START_SERVER_UNADVERTISED :Na -STR_NETWORK_START_SERVER_ADVERTISED :Ia STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} gwestai STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Uchafswm nifer gwesteion: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Dewiswch uchafswm y gwesteion. Does dim rhaid llanw pob slot @@ -2003,15 +2000,10 @@ STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Mae'r cw # Network company list added strings STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Rhestr Cleientiaid -STR_NETWORK_COMPANY_LIST_SPECTATE :Gwylio -STR_NETWORK_COMPANY_LIST_NEW_COMPANY :Cwmni newydd # Network client list -STR_NETWORK_CLIENTLIST_KICK :Cicio -STR_NETWORK_CLIENTLIST_BAN :Gwahardd -STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL :Siarad â phawb -STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY :Siarad a'r cwmni -STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Neges breifat + + STR_NETWORK_SERVER :Gweinydd STR_NETWORK_CLIENT :Gwestai From 27031b396f4a41842e597abb2867bbe2832d315c Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sun, 25 Apr 2021 14:27:30 -0400 Subject: [PATCH 15/22] Change: [Actions] Reword bug/crash report instructions (#9104) --- .github/ISSUE_TEMPLATE/bug.md | 4 ++-- .github/ISSUE_TEMPLATE/crash.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 0af8a89791..4801435901 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -5,13 +5,13 @@ title: "Bug Report" --- ## Version of OpenTTD - + ## Expected result ## Actual result - + ## Steps to reproduce diff --git a/.github/ISSUE_TEMPLATE/crash.md b/.github/ISSUE_TEMPLATE/crash.md index f7d127e930..00f62f05c9 100644 --- a/.github/ISSUE_TEMPLATE/crash.md +++ b/.github/ISSUE_TEMPLATE/crash.md @@ -6,7 +6,7 @@ title: "Crash Report" ## Version of OpenTTD - + ## Steps to reproduce From 224625942c44ec33519010ae320b3821d933229a Mon Sep 17 00:00:00 2001 From: PeterN Date: Sun, 25 Apr 2021 19:34:16 +0100 Subject: [PATCH 16/22] Fix: Count engine details text in lines rather than pixels. (#9107) This allows the details panel to scale correctly for different zoom levels. --- src/autoreplace_gui.cpp | 8 ++++---- src/build_vehicle_gui.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index d16e0916e1..e04eba302a 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -81,7 +81,7 @@ class ReplaceVehicleWindow : public Window { bool replace_engines; ///< If \c true, engines are replaced, if \c false, wagons are replaced (only for trains). bool reset_sel_engine; ///< Also reset #sel_engine while updating left and/or right and no valid engine selected. GroupID sel_group; ///< Group selected to replace. - int details_height; ///< Minimal needed height of the details panels (found so far). + int details_height; ///< Minimal needed height of the details panels, in text lines (found so far). byte sort_criteria; ///< Criteria of sorting vehicles. bool descending_sort_order; ///< Order of sorting vehicles. bool show_hidden_engines; ///< Whether to show the hidden engines. @@ -229,7 +229,7 @@ public: this->engines[0].ForceRebuild(); this->engines[1].ForceRebuild(); this->reset_sel_engine = true; - this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; + this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9); this->sel_engine[0] = INVALID_ENGINE; this->sel_engine[1] = INVALID_ENGINE; this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype]; @@ -274,7 +274,7 @@ public: case WID_RV_LEFT_DETAILS: case WID_RV_RIGHT_DETAILS: - size->height = this->details_height; + size->height = FONT_HEIGHT_NORMAL * this->details_height + padding.height; break; case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: { @@ -482,7 +482,7 @@ public: NWidgetBase *nwi = this->GetWidget(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS); int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT, nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine[side], ted); - needed_height = std::max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM); + needed_height = std::max(needed_height, (text_end - (int)nwi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL); } } if (needed_height != this->details_height) { // Details window are not high enough, enlarge them. diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index a7a7d80428..8ac0494558 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1055,7 +1055,7 @@ struct BuildVehicleWindow : Window { CargoID cargo_filter[NUM_CARGO + 3]; ///< Available cargo filters; CargoID or CF_ANY or CF_NONE or CF_ENGINES StringID cargo_filter_texts[NUM_CARGO + 4]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID byte cargo_filter_criteria; ///< Selected cargo filter - int details_height; ///< Minimal needed height of the details panels (found so far). + int details_height; ///< Minimal needed height of the details panels, in text lines (found so far). Scrollbar *vscroll; TestedEngineDetails te; ///< Tested cost and capacity after refit. @@ -1115,7 +1115,7 @@ struct BuildVehicleWindow : Window { widget->tool_tip = STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP + type; widget->SetLowered(this->show_hidden_engines); - this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; + this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9); this->FinishInitNested(tile == INVALID_TILE ? (int)type : tile); @@ -1553,7 +1553,7 @@ struct BuildVehicleWindow : Window { break; case WID_BV_PANEL: - size->height = this->details_height; + size->height = FONT_HEIGHT_NORMAL * this->details_height + padding.height; break; case WID_BV_SORT_ASCENDING_DESCENDING: { @@ -1620,12 +1620,12 @@ struct BuildVehicleWindow : Window { NWidgetBase *nwi = this->GetWidget(WID_BV_PANEL); int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT, nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine, this->te); - needed_height = std::max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM); + needed_height = std::max(needed_height, (text_end - (int)nwi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL); } if (needed_height != this->details_height) { // Details window are not high enough, enlarge them. int resize = needed_height - this->details_height; this->details_height = needed_height; - this->ReInit(0, resize); + this->ReInit(0, resize * FONT_HEIGHT_NORMAL); return; } } From 97288bc286bf4b4b92cf29bcd051c49b2299624b Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Sun, 25 Apr 2021 20:11:59 +0100 Subject: [PATCH 17/22] Fix #9109: Malformed STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD in Japanese lang (#9110) --- src/lang/japanese.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index f4cc22bf0a..867f929d1f 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -2402,7 +2402,7 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}道路 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}軌道用トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}道路の建設/撤去を切り替えます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}軌道の建設/撤去を切り替えます -STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}道路の種類を変更/アップグレードします.Shiftは、コスト見積もりの​​作成/表示を切り替えます +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}道路の種類を変更/アップグレードします.Shiftは、コスト見積もりの作成/表示を切り替えます STR_ROAD_NAME_TRAM :トラムウェイ From 8b302761d4ca51f41eaff4097c9afa4f3aec5ec5 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 18 Apr 2021 14:42:06 +0200 Subject: [PATCH 18/22] Codechange: allow different limits in packet sizes --- src/network/core/packet.cpp | 17 +++++++++++------ src/network/core/packet.h | 15 +++++++++------ src/network/core/tcp.cpp | 2 +- src/network/core/udp.cpp | 3 ++- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 428bc65ba4..39531c0a40 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -19,6 +19,7 @@ /** * Create a packet that is used to read from a network socket. * @param cs The socket handler associated with the socket we are reading from. + * @param limit The maximum size of packets to accept. * @param initial_read_size The initial amount of data to transfer from the socket into the * packet. This defaults to just the required bytes to determine the * packet's size. That default is the wanted for streams such as TCP @@ -27,7 +28,7 @@ * loose some the data of the packet, so there you pass the maximum * size for the packet you expect from the network. */ -Packet::Packet(NetworkSocketHandler *cs, size_t initial_read_size) : next(nullptr), pos(0) +Packet::Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size) : next(nullptr), pos(0), limit(limit) { assert(cs != nullptr); @@ -37,9 +38,13 @@ Packet::Packet(NetworkSocketHandler *cs, size_t initial_read_size) : next(nullpt /** * Creates a packet to send - * @param type of the packet to send + * @param type The type of the packet to send + * @param limit The maximum number of bytes the packet may have. Default is SEND_MTU. + * Be careful of compatibility with older clients/servers when changing + * the limit as it might break things if the other side is not expecting + * much larger packets than what they support. */ -Packet::Packet(PacketType type) : next(nullptr), pos(0), cs(nullptr) +Packet::Packet(PacketType type, size_t limit) : next(nullptr), pos(0), cs(nullptr) { /* Allocate space for the the size so we can write that in just before sending the packet. */ this->Send_uint16(0); @@ -93,7 +98,7 @@ void Packet::PrepareToSend() */ bool Packet::CanWriteToPacket(size_t bytes_to_write) { - return this->Size() + bytes_to_write < SEND_MTU; + return this->Size() + bytes_to_write < this->limit; } /* @@ -191,7 +196,7 @@ void Packet::Send_string(const char *data) */ size_t Packet::Send_bytes(const byte *begin, const byte *end) { - size_t amount = std::min(end - begin, SEND_MTU - this->Size()); + size_t amount = std::min(end - begin, this->limit - this->Size()); this->buffer.insert(this->buffer.end(), begin, begin + amount); return amount; } @@ -260,7 +265,7 @@ bool Packet::ParsePacketSize() /* If the size of the packet is less than the bytes required for the size and type of * the packet, or more than the allowed limit, then something is wrong with the packet. * In those cases the packet can generally be regarded as containing garbage data. */ - if (size < sizeof(PacketSize) + sizeof(PacketType) || size > SEND_MTU) return false; + if (size < sizeof(PacketSize) + sizeof(PacketType) || size > this->limit) return false; this->buffer.resize(size); this->pos = sizeof(PacketSize); diff --git a/src/network/core/packet.h b/src/network/core/packet.h index 1ac7f18a18..db051005c5 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -25,10 +25,11 @@ typedef uint8 PacketType; ///< Identifier for the packet * Internal entity of a packet. As everything is sent as a packet, * all network communication will need to call the functions that * populate the packet. - * Every packet can be at most SEND_MTU bytes. Overflowing this - * limit will give an assertion when sending (i.e. writing) the - * packet. Reading past the size of the packet when receiving - * will return all 0 values and "" in case of the string. + * Every packet can be at most a limited number bytes set in the + * constructor. Overflowing this limit will give an assertion when + * sending (i.e. writing) the packet. Reading past the size of the + * packet when receiving will return all 0 values and "" in case of + * the string. * * --- Points of attention --- * - all > 1 byte integral values are written in little endian, @@ -47,13 +48,15 @@ private: PacketSize pos; /** The buffer of this packet. */ std::vector buffer; + /** The limit for the packet size. */ + size_t limit; /** Socket we're associated with. */ NetworkSocketHandler *cs; public: - Packet(NetworkSocketHandler *cs, size_t initial_read_size = sizeof(PacketSize)); - Packet(PacketType type); + Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size = sizeof(PacketSize)); + Packet(PacketType type, size_t limit = SEND_MTU); static void AddToQueue(Packet **queue, Packet *packet); static Packet *PopFromQueue(Packet **queue); diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp index a749b6195b..be70efdd2f 100644 --- a/src/network/core/tcp.cpp +++ b/src/network/core/tcp.cpp @@ -126,7 +126,7 @@ Packet *NetworkTCPSocketHandler::ReceivePacket() if (!this->IsConnected()) return nullptr; if (this->packet_recv == nullptr) { - this->packet_recv = new Packet(this); + this->packet_recv = new Packet(this, SEND_MTU); } Packet *p = this->packet_recv; diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index 3bd2151fe1..8872fa295a 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -119,7 +119,8 @@ void NetworkUDPSocketHandler::ReceivePackets() struct sockaddr_storage client_addr; memset(&client_addr, 0, sizeof(client_addr)); - Packet p(this, SEND_MTU); + /* The limit is SEND_MTU, but also allocate that much as we need to read the whole packet in one go. */ + Packet p(this, SEND_MTU, SEND_MTU); socklen_t client_len = sizeof(client_addr); /* Try to receive anything */ From d6000c2ec5f61c599d8859b981f2dac6a92e0755 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 18 Apr 2021 14:49:39 +0200 Subject: [PATCH 19/22] Codechange: differentiate between UDP, TCP and compatibility MTU values --- src/network/core/config.h | 8 +++++--- src/network/core/packet.cpp | 2 +- src/network/core/packet.h | 2 +- src/network/core/tcp.cpp | 2 +- src/network/core/udp.cpp | 4 ++-- src/network/network_admin.cpp | 6 +++--- src/network/network_content.cpp | 8 ++++---- src/network/network_udp.cpp | 6 +++--- 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/network/core/config.h b/src/network/core/config.h index 1483419ea5..572b4720db 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -30,7 +30,9 @@ static const uint16 NETWORK_DEFAULT_PORT = 3979; ///< The defau static const uint16 NETWORK_ADMIN_PORT = 3977; ///< The default port for admin network static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The default port debug-log is sent to (TCP) -static const uint16 SEND_MTU = 1460; ///< Number of bytes we can pack in a single packet +static const uint16 UDP_MTU = 1460; ///< Number of bytes we can pack in a single UDP packet +static const uint16 TCP_MTU = 1460; ///< Number of bytes we can pack in a single TCP packet +static const uint16 COMPAT_MTU = 1460; ///< Number of bytes we can pack in a single packet for backward compatibility static const byte NETWORK_GAME_ADMIN_VERSION = 1; ///< What version of the admin network do we use? static const byte NETWORK_GAME_INFO_VERSION = 4; ///< What version of game-info do we use? @@ -46,14 +48,14 @@ static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maxim static const uint NETWORK_CLIENTS_LENGTH = 200; ///< The maximum length for the list of clients that controls a company, in bytes including '\0' static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maximum length of a client's name, in bytes including '\0' static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0' -static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = SEND_MTU - 3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than SEND_MTU including header (3 bytes) +static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = COMPAT_MTU-3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than COMPAT_MTU including header (3 bytes) static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0' static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF /** * Maximum number of GRFs that can be sent. - * This limit is reached when PACKET_UDP_SERVER_RESPONSE reaches the maximum size of SEND_MTU bytes. + * This limit is reached when PACKET_UDP_SERVER_RESPONSE reaches the maximum size of UDP_MTU bytes. */ static const uint NETWORK_MAX_GRF_COUNT = 62; diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 39531c0a40..40e6640550 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -39,7 +39,7 @@ Packet::Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size) /** * Creates a packet to send * @param type The type of the packet to send - * @param limit The maximum number of bytes the packet may have. Default is SEND_MTU. + * @param limit The maximum number of bytes the packet may have. Default is COMPAT_MTU. * Be careful of compatibility with older clients/servers when changing * the limit as it might break things if the other side is not expecting * much larger packets than what they support. diff --git a/src/network/core/packet.h b/src/network/core/packet.h index db051005c5..d55dad316a 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -56,7 +56,7 @@ private: public: Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size = sizeof(PacketSize)); - Packet(PacketType type, size_t limit = SEND_MTU); + Packet(PacketType type, size_t limit = COMPAT_MTU); static void AddToQueue(Packet **queue, Packet *packet); static Packet *PopFromQueue(Packet **queue); diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp index be70efdd2f..72e66a0b55 100644 --- a/src/network/core/tcp.cpp +++ b/src/network/core/tcp.cpp @@ -126,7 +126,7 @@ Packet *NetworkTCPSocketHandler::ReceivePacket() if (!this->IsConnected()) return nullptr; if (this->packet_recv == nullptr) { - this->packet_recv = new Packet(this, SEND_MTU); + this->packet_recv = new Packet(this, TCP_MTU); } Packet *p = this->packet_recv; diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index 8872fa295a..e8299f7b62 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -119,8 +119,8 @@ void NetworkUDPSocketHandler::ReceivePackets() struct sockaddr_storage client_addr; memset(&client_addr, 0, sizeof(client_addr)); - /* The limit is SEND_MTU, but also allocate that much as we need to read the whole packet in one go. */ - Packet p(this, SEND_MTU, SEND_MTU); + /* The limit is UDP_MTU, but also allocate that much as we need to read the whole packet in one go. */ + Packet p(this, UDP_MTU, UDP_MTU); socklen_t client_len = sizeof(client_addr); /* Try to receive anything */ diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 057ad59883..1b86c3e561 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -560,8 +560,8 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origi /* If the length of both strings, plus the 2 '\0' terminations and 3 bytes of the packet * are bigger than the MTU, just ignore the message. Better safe than sorry. It should * never occur though as the longest strings are chat messages, which are still 30% - * smaller than SEND_MTU. */ - if (strlen(origin) + strlen(string) + 2 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY; + * smaller than COMPAT_MTU. */ + if (strlen(origin) + strlen(string) + 2 + 3 >= COMPAT_MTU) return NETWORK_RECV_STATUS_OKAY; Packet *p = new Packet(ADMIN_PACKET_SERVER_CONSOLE); @@ -610,7 +610,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames() for (uint i = 0; i < CMD_END; i++) { const char *cmdname = GetCommandName(i); - /* Should SEND_MTU be exceeded, start a new packet + /* Should COMPAT_MTU be exceeded, start a new packet * (magic 5: 1 bool "more data" and one uint16 "command id", one * byte for string '\0' termination and 1 bool "no more data" */ if (p->CanWriteToPacket(strlen(cmdname) + 5)) { diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 5292252354..fb95ff72b4 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -221,9 +221,9 @@ void ClientNetworkContentSocketHandler::RequestContentList(uint count, const Con * A packet begins with the packet size and a byte for the type. * Then this packet adds a uint16 for the count in this packet. * The rest of the packet can be used for the IDs. */ - uint p_count = std::min(count, (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); + uint p_count = std::min(count, (COMPAT_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); - Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_ID); + Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_ID, COMPAT_MTU); p->Send_uint16(p_count); for (uint i = 0; i < p_count; i++) { @@ -248,7 +248,7 @@ void ClientNetworkContentSocketHandler::RequestContentList(ContentVector *cv, bo this->Connect(); assert(cv->size() < 255); - assert(cv->size() < (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) / + assert(cv->size() < (COMPAT_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) / (sizeof(uint8) + sizeof(uint32) + (send_md5sum ? /*sizeof(ContentInfo::md5sum)*/16 : 0))); Packet *p = new Packet(send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID); @@ -363,7 +363,7 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContentFallback(const Co * A packet begins with the packet size and a byte for the type. * Then this packet adds a uint16 for the count in this packet. * The rest of the packet can be used for the IDs. */ - uint p_count = std::min(count, (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); + uint p_count = std::min(count, (COMPAT_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); Packet *p = new Packet(PACKET_CONTENT_CLIENT_CONTENT); p->Send_uint16(p_count); diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index aa34515bdd..f7db689d4b 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -256,10 +256,10 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_DETAIL_INFO(Packet *p, Networ /** * A client has requested the names of some NewGRFs. * - * Replying this can be tricky as we have a limit of SEND_MTU bytes + * Replying this can be tricky as we have a limit of UDP_MTU bytes * in the reply packet and we can send up to 100 bytes per NewGRF * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name). - * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it + * As UDP_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it * could be that a packet overflows. To stop this we only reply * with the first N NewGRFs so that if the first N + 1 NewGRFs * would be sent, the packet overflows. @@ -295,7 +295,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ * The name could be an empty string, if so take the filename. */ packet_len += sizeof(c.grfid) + sizeof(c.md5sum) + std::min(strlen(f->GetName()) + 1, (size_t)NETWORK_GRF_NAME_LENGTH); - if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply + if (packet_len > UDP_MTU - 4) { // 4 is 3 byte header + grf count in reply break; } in_reply[in_reply_count] = f; From 21f58ab437992761caefd11f931c45086cc3d216 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 18 Apr 2021 14:56:25 +0200 Subject: [PATCH 20/22] Change: use 32 KiB packets to transfer the savegame --- src/network/core/config.h | 16 +++++++++++++++- src/network/network_server.cpp | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/network/core/config.h b/src/network/core/config.h index 572b4720db..866d1791d4 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -31,7 +31,21 @@ static const uint16 NETWORK_ADMIN_PORT = 3977; ///< The defau static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The default port debug-log is sent to (TCP) static const uint16 UDP_MTU = 1460; ///< Number of bytes we can pack in a single UDP packet -static const uint16 TCP_MTU = 1460; ///< Number of bytes we can pack in a single TCP packet +/* + * Technically a TCP packet could become 64kiB, however the high bit is kept so it becomes possible in the future + * to go to (significantly) larger packets if needed. This would entail a strategy such as employed for UTF-8. + * + * Packets up to 32 KiB have the high bit not set: + * 00000000 00000000 0bbbbbbb aaaaaaaa -> aaaaaaaa 0bbbbbbb + * Send_uint16(GB(size, 0, 15) + * + * Packets up to 1 GiB, first uint16 has high bit set so it knows to read a + * next uint16 for the remaining bits of the size. + * 00dddddd cccccccc bbbbbbbb aaaaaaaa -> cccccccc 10dddddd aaaaaaaa bbbbbbbb + * Send_uint16(GB(size, 16, 14) | 0b10 << 14) + * Send_uint16(GB(size, 0, 16)) + */ +static const uint16 TCP_MTU = 32767; ///< Number of bytes we can pack in a single TCP packet static const uint16 COMPAT_MTU = 1460; ///< Number of bytes we can pack in a single packet for backward compatibility static const byte NETWORK_GAME_ADMIN_VERSION = 1; ///< What version of the admin network do we use? diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 5489db8480..7d10f04fe3 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -158,7 +158,7 @@ struct PacketWriter : SaveFilter { /* We want to abort the saving when the socket is closed. */ if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION); - if (this->current == nullptr) this->current = new Packet(PACKET_SERVER_MAP_DATA); + if (this->current == nullptr) this->current = new Packet(PACKET_SERVER_MAP_DATA, TCP_MTU); std::lock_guard lock(this->mutex); @@ -169,7 +169,7 @@ struct PacketWriter : SaveFilter { if (!this->current->CanWriteToPacket(1)) { this->AppendQueue(); - if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA); + if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA, TCP_MTU); } } From a3c9eca722e73b823c5c47f49da2fb0ba754ee5b Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 18 Apr 2021 14:59:23 +0200 Subject: [PATCH 21/22] Change: use 32 KiB packets to send requests to the content server --- src/network/network_content.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index fb95ff72b4..a208f3c6e2 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -221,9 +221,9 @@ void ClientNetworkContentSocketHandler::RequestContentList(uint count, const Con * A packet begins with the packet size and a byte for the type. * Then this packet adds a uint16 for the count in this packet. * The rest of the packet can be used for the IDs. */ - uint p_count = std::min(count, (COMPAT_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); + uint p_count = std::min(count, (TCP_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); - Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_ID, COMPAT_MTU); + Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_ID, TCP_MTU); p->Send_uint16(p_count); for (uint i = 0; i < p_count; i++) { @@ -248,10 +248,10 @@ void ClientNetworkContentSocketHandler::RequestContentList(ContentVector *cv, bo this->Connect(); assert(cv->size() < 255); - assert(cv->size() < (COMPAT_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) / + assert(cv->size() < (TCP_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) / (sizeof(uint8) + sizeof(uint32) + (send_md5sum ? /*sizeof(ContentInfo::md5sum)*/16 : 0))); - Packet *p = new Packet(send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID); + Packet *p = new Packet(send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID, TCP_MTU); p->Send_uint8((uint8)cv->size()); for (const ContentInfo *ci : *cv) { @@ -363,9 +363,9 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContentFallback(const Co * A packet begins with the packet size and a byte for the type. * Then this packet adds a uint16 for the count in this packet. * The rest of the packet can be used for the IDs. */ - uint p_count = std::min(count, (COMPAT_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); + uint p_count = std::min(count, (TCP_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32)); - Packet *p = new Packet(PACKET_CONTENT_CLIENT_CONTENT); + Packet *p = new Packet(PACKET_CONTENT_CLIENT_CONTENT, TCP_MTU); p->Send_uint16(p_count); for (uint i = 0; i < p_count; i++) { From 5afb09008286759fce9fcf109881eabc078b7301 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 25 Apr 2021 19:59:19 +0200 Subject: [PATCH 22/22] Change: [Network] Remove now defunct savegame transfer packet limiter --- src/network/network_server.cpp | 71 ++++++++-------------------------- 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 7d10f04fe3..67952bca69 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -112,25 +112,27 @@ struct PacketWriter : SaveFilter { } /** - * Checks whether there are packets. - * It's not 100% threading safe, but this is only asked for when checking - * whether there still is something to send. Then another call will be made - * to actually get the Packet, which will be the only one popping packets - * and thus eventually setting this on false. + * Transfer all packets from here to the network's queue while holding + * the lock on our mutex. + * @param socket The network socket to write to. + * @return True iff the last packet of the map has been sent. */ - bool HasPackets() + bool TransferToNetworkQueue(ServerNetworkGameSocketHandler *socket) { - return this->packets != nullptr; - } + /* Unsafe check for the queue being empty or not. */ + if (this->packets == nullptr) return false; - /** - * Pop a single created packet from the queue with packets. - */ - Packet *PopPacket() - { std::lock_guard lock(this->mutex); - return Packet::PopFromQueue(&this->packets); + while (this->packets != nullptr) { + Packet *p = Packet::PopFromQueue(&this->packets); + bool last_packet = p->GetPacketType() == PACKET_SERVER_MAP_DONE; + socket->SendPacket(p); + + if (last_packet) return true; + } + + return false; } /** Append the current packet to the queue. */ @@ -592,8 +594,6 @@ void ServerNetworkGameSocketHandler::CheckNextClientToSendMap(NetworkClientSocke /** This sends the map to the client */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() { - static uint16 sent_packets; // How many packets we did send successfully last time - if (this->status < STATUS_AUTHORIZED) { /* Illegal call, return error and ignore the packet */ return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED); @@ -613,28 +613,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() this->last_frame = _frame_counter; this->last_frame_server = _frame_counter; - sent_packets = 4; // We start with trying 4 packets - /* Make a dump of the current game */ if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed"); } if (this->status == STATUS_MAP) { - bool last_packet = false; - bool has_packets = false; - - for (uint i = 0; (has_packets = this->savegame->HasPackets()) && i < sent_packets; i++) { - Packet *p = this->savegame->PopPacket(); - last_packet = p->GetPacketType() == PACKET_SERVER_MAP_DONE; - - this->SendPacket(p); - - if (last_packet) { - /* There is no more data, so break the for */ - break; - } - } - + bool last_packet = this->savegame->TransferToNetworkQueue(this); if (last_packet) { /* Done reading, make sure saving is done as well */ this->savegame->Destroy(); @@ -646,27 +630,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() this->CheckNextClientToSendMap(); } - - switch (this->SendPackets()) { - case SPS_CLOSED: - return NETWORK_RECV_STATUS_CONN_LOST; - - case SPS_ALL_SENT: - /* All are sent, increase the sent_packets but do not overflow! */ - if (has_packets && sent_packets < std::numeric_limits::max() / 2) { - sent_packets *= 2; - } - break; - - case SPS_PARTLY_SENT: - /* Only a part is sent; leave the transmission state. */ - break; - - case SPS_NONE_SENT: - /* Not everything is sent, decrease the sent_packets */ - if (sent_packets > 1) sent_packets /= 2; - break; - } } return NETWORK_RECV_STATUS_OKAY; }