Merge branch 'master' into jgrpp-beta

# Conflicts:
#	src/engine_base.h
#	src/gfxinit.cpp
#	src/graph_gui.cpp
#	src/lang/brazilian_portuguese.txt
#	src/lang/dutch.txt
#	src/lang/french.txt
#	src/lang/korean.txt
#	src/lang/norwegian_bokmal.txt
#	src/lang/portuguese.txt
#	src/lang/russian.txt
#	src/lang/spanish.txt
#	src/lang/spanish_MX.txt
#	src/network/core/address.cpp
#	src/network/core/game_info.h
#	src/network/core/os_abstraction.h
#	src/network/core/udp.cpp
#	src/network/network_client.cpp
#	src/network/network_client.h
#	src/network/network_internal.h
#	src/newgrf_engine.cpp
#	src/settings_gui.cpp
#	src/station_cmd.cpp
#	src/string_func.h
#	src/town_gui.cpp
#	src/video/video_driver.cpp
#	src/widget_type.h
pull/332/head
Jonathan G Rennison 3 years ago
commit 2bd535e834

@ -65,10 +65,14 @@ Module.preRun.push(function() {
}
window.openttd_server_list = function() {
add_server = Module.cwrap("em_openttd_add_server", null, ["string", "number"]);
add_server = Module.cwrap("em_openttd_add_server", null, ["string"]);
/* Add servers that support WebSocket here. Example:
* add_server("localhost", 3979); */
/* Add servers that support WebSocket here. Examples:
* add_server("localhost");
* add_server("localhost:3979");
* add_server("127.0.0.1:3979");
* add_server("[::1]:3979");
*/
}
var leftButtonDown = false;

@ -969,16 +969,15 @@ DEF_CONSOLE_CMD(ConNetworkReconnect)
break;
}
if (StrEmpty(_settings_client.network.last_host)) {
if (StrEmpty(_settings_client.network.last_joined)) {
IConsolePrint(CC_DEFAULT, "No server for reconnecting.");
return true;
}
/* Don't resolve the address first, just print it directly as it comes from the config file. */
IConsolePrintF(CC_DEFAULT, "Reconnecting to %s:%d...", _settings_client.network.last_host, _settings_client.network.last_port);
IConsolePrintF(CC_DEFAULT, "Reconnecting to %s ...", _settings_client.network.last_joined);
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, playas);
return true;
return NetworkClientConnectGame(_settings_client.network.last_joined, playas);
}
DEF_CONSOLE_CMD(ConNetworkConnect)
@ -991,37 +990,8 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
}
if (argc < 2) return false;
if (_networking) NetworkDisconnect(); // we are in network-mode, first close it!
const char *port = nullptr;
const char *company = nullptr;
char *ip = argv[1];
/* Default settings: default port and new company */
uint16 rport = NETWORK_DEFAULT_PORT;
CompanyID join_as = COMPANY_NEW_COMPANY;
ParseGameConnectionString(&company, &port, ip);
IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip);
if (company != nullptr) {
join_as = (CompanyID)atoi(company);
IConsolePrintF(CC_DEFAULT, " company-no: %d", join_as);
/* From a user pov 0 is a new company, internally it's different and all
* companies are offset by one to ease up on users (eg companies 1-8 not 0-7) */
if (join_as != COMPANY_SPECTATOR) {
if (join_as > MAX_COMPANIES) return false;
join_as--;
}
}
if (port != nullptr) {
rport = atoi(port);
IConsolePrintF(CC_DEFAULT, " port: %s", port);
}
NetworkClientConnectGame(ip, rport, join_as);
return true;
return NetworkClientConnectGame(argv[1], COMPANY_NEW_COMPANY);
}
/*********************************

@ -67,12 +67,6 @@ static_assert(lengthof(_orig_rail_vehicle_info) + lengthof(_orig_road_vehicle_in
const uint EngineOverrideManager::NUM_DEFAULT_ENGINES = _engine_counts[VEH_TRAIN] + _engine_counts[VEH_ROAD] + _engine_counts[VEH_SHIP] + _engine_counts[VEH_AIRCRAFT];
Engine::Engine() :
overrides_count(0),
overrides(nullptr)
{
}
Engine::Engine(VehicleType type, EngineID base)
{
this->type = type;
@ -137,11 +131,6 @@ Engine::Engine(VehicleType type, EngineID base)
}
}
Engine::~Engine()
{
UnloadWagonOverrides(this);
}
/**
* Checks whether the engine is a valid (non-articulated part of an) engine.
* @return true if enabled

@ -18,6 +18,12 @@
#include "3rdparty/cpp-btree/btree_map.h"
struct WagonOverride {
std::vector<EngineID> engines;
CargoID cargo;
const SpriteGroup *group;
};
typedef Pool<Engine, EngineID, 64, 64000> EnginePool;
extern EnginePool _engine_pool;
@ -59,17 +65,15 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
* evaluating callbacks.
*/
GRFFilePropsBase<NUM_CARGO + 2> grf_prop;
uint16 overrides_count;
struct WagonOverride *overrides;
std::vector<WagonOverride> overrides;
uint16 list_position;
SpriteGroupCallbacksUsed callbacks_used = SGCU_ALL;
uint64 cb36_properties_used = UINT64_MAX;
btree::btree_map<const SpriteGroup *, uint64> sprite_group_cb36_properties_used;
Engine();
Engine() {}
Engine(VehicleType type, EngineID base);
~Engine();
bool IsEnabled() const;
/**

@ -960,7 +960,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit Malaio
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Dirigem na esquerda
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Dirigem na direita
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nomes das cidades
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nome das cidades:
STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Selecionar o estilo dos nomes das cidades
############ start of townname region
@ -1000,6 +1000,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :A cada 12 meses
STR_GAME_OPTIONS_LANGUAGE :{BLACK}Idioma
STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Selecionar o idioma da interface do jogo
STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% concluído)
STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Tela cheia
STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Marcar esta caixa para jogar OpenTTD modo de tela cheia
@ -1997,6 +1998,8 @@ STR_FACE_TIE :Gravata:
STR_FACE_EARRING :Brinco:
STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Alterar gravata ou brinco
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multi-jogador
@ -2060,6 +2063,8 @@ 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_VISIBILITY_LABEL :{BLACK}Visibilidade
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se outras pessoas podem ver seu servidor na lista pública
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
@ -2123,12 +2128,45 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa está protegida. Digite a senha
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jogadores online
STR_NETWORK_COMPANY_LIST_SPECTATE :Assistir
# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijogador
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nome
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nome do servidor que você está jogando
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Edita o nome do seu servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nome do servidor
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidade
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se outras pessoas podem ver seu servidor na lista pública
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jogador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nome
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Seu nome de jogador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Edita seu nome de jogador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Seu nome de jogador
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Ações administrativas a serem executadas para esse cliente
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Ações administrativas a serem executadas para essa empresa
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Junta-se a essa empresa
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Envia uma mensagem a esse jogador
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Envia uma mensagem a todos os jogadores dessa empresa
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Envia uma mensagem a todos os espectadores
STR_NETWORK_CLIENT_LIST_SPECTATORS :Espectadores
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova empresa)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Cria uma nova empresa e se une a ela
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Esse é você
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Esse é o hospedeiro do jogo
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Banir
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Excluir
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Desbloqueio com senha
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Ação de administrador
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Você tem certeza que quer expulsar o jogador '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Você tem certeza que quer banir o jogador '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Você tem certeza que quer excluir a empresa '{COMPANY}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Você tem certeza que quer restaurar a senha da empresa '{COMPANY}'?
STR_NETWORK_SERVER :Servidor
STR_NETWORK_CLIENT :Cliente
@ -2173,6 +2211,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Não foi
STR_NETWORK_ERROR_CLIENT_START :{WHITE}Não foi possível estabelecer conexão
STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tempo de espera esgotado na conexão #{NUM}
STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ocorreu um erro de protocolo e a conexão foi encerrada
STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Seu nome de jogador não foi definido. O nome pode ser definido no topo da janela de Multijogador
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}A versão deste cliente não condiz com a versão do servidor
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Senha incorreta
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}O servidor está cheio
@ -2185,6 +2224,8 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Você de
STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Seu computador é lento demais para acompanhar o servidor
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Seu computador demorou demais para baixar o mapa
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Seu computador demorou demais para entrar no servidor
STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Seu nome de jogador não é válido
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}O servidor requisitado é muito antigo para esse cliente
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :erro geral
@ -2207,6 +2248,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :não recebeu se
STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :tempo esgotado
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :a baixa do mapa demorou demais
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :o processamento do mapa demorou demais
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nome de cliente inválido
############ End of leave-in-this-order
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possível perda de conexão
@ -3050,6 +3092,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Atenção:
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Erro: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Erro Fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Um erro de NewGRF fatal ocorreu:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Um erro NewGRF ocorreu:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} não irá funcionar com a versão do TTDPatch encontrada pelo OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} funciona na versão {STRING} de TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} é projetado para ser usado com {STRING}

@ -2225,6 +2225,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}El teu o
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}El teu ordinador ha tardat massa a descarregar el mapa
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}El teu ordinador ha tardat massa a unir-se al servidor
STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}El vostre nom de jugador no és vàlid.
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}El servidor és massa antic per a aquest client.
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :error general
@ -3091,6 +3092,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Alerta: {S
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}S'ha produït un error fatal de NewGRF:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}S'ha produït un error relacionat amb els NewGRF:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} no funcionarà amb la versió TTDPatch informada per l'OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} és per la versió {STRING} de TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} està dissenyat per ser utilitzat amb {STRING}

@ -959,7 +959,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Maleisische Rin
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Links rijden
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Rechts rijden
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Plaatsnamen
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Plaatsnamen:
STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Stijl voor plaatsnamen kiezen
############ start of townname region
@ -999,6 +999,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Iedere 12 maand
STR_GAME_OPTIONS_LANGUAGE :{BLACK}Taal
STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Taal selecteren voor gebruikersscherm
STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% voltooid)
STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Volledig scherm
STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Vink dit vakje aan om OpenTTD in het volledige scherm te spelen
@ -1996,6 +1997,8 @@ STR_FACE_TIE :Stropdas:
STR_FACE_EARRING :Oorbel:
STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Verander das of oorbel
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privé
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Openbaar
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Netwerkspel
@ -2052,13 +2055,15 @@ STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Vul je n
STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Voer het IP-adres van de server in
# Start new multiplayer server
STR_NETWORK_START_SERVER_CAPTION :{WHITE}Start nieuw multiplayerspel
STR_NETWORK_START_SERVER_CAPTION :{WHITE}Nieuw spel met meerdere spelers starten
STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}Spelnaam:
STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}De spelnaam wordt weergegeven aan andere spelers in het multiplayerspelselectiemenu
STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}De spelnaam wordt weergegeven aan andere spelers in het spelselectiemenu voor meerdere spelers
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_VISIBILITY_LABEL :{BLACK}Zichtbaarheid
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Bepaalt of andere mensen je server kunnen zien in de openbare lijst
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.
@ -2122,12 +2127,45 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Server i
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Bedrijf is beveiligd. Voer wachtwoord in
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spelerslijst
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Spelers online
STR_NETWORK_COMPANY_LIST_SPECTATE :Toekijken
# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Meerdere spelers
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Naam
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}De naam van de server waar je speelt
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}De naam van je server bewerken
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Servernaam
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Zichtbaarheid
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Bepaalt of andere mensen je server kunnen zien in de openbare lijst
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Speler
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Naam
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Je spelernaam
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Je spelernaam bewerken
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Je spelernaam
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Beheeracties die nodig zijn voor deze client
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Beheeracties die nodig zijn voor dit bedrijf
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Meedoen met dit bedrijf
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Een bericht sturen naar deze speler
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Een bericht versturen naar alle spelers van dit bedrijf
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Een bericht sturen naar alle toeschouwers
STR_NETWORK_CLIENT_LIST_SPECTATORS :Toeschouwers
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nieuw bedrijf)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Een nieuw bedrijf maken en meedoen
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dit ben jij
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dit is de host van het spel
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Eruit schoppen
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bannen
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Verwijderen
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Wachtwoord ontgrendelen
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Beheeractie
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Weet je zeker dat je de speler '{STRING}' eruit wilt schoppen?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Weet je zeker dat je de speler '{STRING}' wilt bannen?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Weet je zeker dat je het bedrijf '{COMPANY}' wilt verwijderen?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Weet je zeker dat je het wachtwoord voor bedrijf '{COMPANY}' wilt terugstellen?
STR_NETWORK_SERVER :Server
STR_NETWORK_CLIENT :Speler
@ -2172,6 +2210,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Kan serv
STR_NETWORK_ERROR_CLIENT_START :{WHITE}Kan geen verbinding maken
STR_NETWORK_ERROR_TIMEOUT :{WHITE}Verbinding nr. {NUM} kostte te veel tijd
STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Er is een protocolfout gedetecteerd en de verbinding werd gesloten
STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Je spelernaam is nog niet ingesteld. Je stelt de naam in bovenin het venster Meerdere spelers
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}De revisie van deze client komt niet overeen met de revisie van de server
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Ongeldig wachtwoord
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}De server is vol
@ -2184,6 +2223,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Het invo
STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Uw computer is te traag om de server bij te houden
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Uw computer deed er te lang over om de kaart te downloaden
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Uw computer deed er te lang over om met de server te verbinden
STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Je spelernaam is niet geldig
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :algemene fout
@ -2206,6 +2246,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :wachtwoord niet
STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :algemene time-out
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :downloaden van de kaart duurde te lang
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :verwerken van de kaart duurde te lang
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :ongeldige clientnaam
############ End of leave-in-this-order
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Mogelijk verbinding verbroken
@ -3049,6 +3090,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Waarschuwi
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Fout: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatale fout: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Een fatale NewGRF-fout is ontstaan:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Er is een NewGRF-fout opgetreden:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} werkt niet met de TTDPatch-versie die is opgegeven door OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} is voor versie {STRING} van TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} is ontwikkeld voor {STRING}

@ -2649,6 +2649,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Your com
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
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}The queried server is too old for this client
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :general error

@ -3114,6 +3114,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Warning: {
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}A fatal NewGRF error has occurred:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}A NewGRF error has occurred:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} will not work with the TTDPatch version reported by OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} is for the {STRING} version of TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} is designed to be used with {STRING}

@ -3090,6 +3090,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Varoitus:
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Virhe: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Virhe: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Vakava NewGRF-virhe on tapahtunut:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF-virhe on tapahtunut:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} ei toimi OpenTTD:n ilmoittaman TTDPatch-version kanssa
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} on TTD:n {STRING}-versiota varten
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} ja {STRING} on suunniteltu toimimaan yhdessä
@ -4473,7 +4474,7 @@ STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Ei voi r
STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Satamaa ei voi rakentaa tähän...
STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Lentokenttää ei voi rakentaa...
STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Liitä yhteen useampi asema/lastausalue.
STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Vieressä on useampi kuin yksi olemassaoleva asema tai kuormausalue.
STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... asema liian levittäytynyt
STR_ERROR_TOO_MANY_STATIONS_LOADING :{WHITE}Liian monta asemaa ja lastausaluetta.
STR_ERROR_TOO_MANY_STATION_SPECS :{WHITE}Rautatieasema on jakautunut liian moneen osaan
@ -4506,7 +4507,7 @@ STR_ERROR_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Satama p
STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Lentokenttä pitää tuhota ensin.
# Waypoint related errors
STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Liittää useamman kuin yhden reittipisteen
STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Vieressä on useampi kuin yksi olemassaoleva reittipiste.
STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Liian lähellä toista reittipistettä
STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Junien reittipistettä ei voi rakentaa tähän...

@ -960,7 +960,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malaysian Ringg
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Conduite à gauche
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Conduite à droite
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Noms des villes
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nom des villes{NBSP}:
STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Sélectionner la nationalité des noms des villes
############ start of townname region
@ -1000,6 +1000,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Tous les 12 moi
STR_GAME_OPTIONS_LANGUAGE :{BLACK}Langue
STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Sélectionner la langue à utiliser pour l'interface
STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}{NBSP}% terminé{P "" s})
STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Plein écran
STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Cocher cette case pour jouer à OpenTTD en plein écran
@ -1997,6 +1998,8 @@ 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
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privé
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Public
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijoueurs
@ -2060,6 +2063,8 @@ 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_VISIBILITY_LABEL :{BLACK}Visibilité
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Possibilité pour les autres personnes de vous voir dans la liste publique
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
@ -2123,12 +2128,45 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Le serve
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}La compagnie est protégée. Entrez le mot de passe
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste des clients
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Joueurs en ligne
STR_NETWORK_COMPANY_LIST_SPECTATE :Spectateur
# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijoueur
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Serveur
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nom
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nom du serveur sur lequel vous jouez
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Éditer le nom de votre serveur
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nom du serveur
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilité
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Possibilité pour les autres personnes de voir votre serveur dans la liste publique
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Joueur
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nom
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Votre nom de jeu
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Éditer votre nom
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Votre nom de jeu
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Actions administratives à accomplir pour ce client
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Actions administratives à accomplir pour cette compagnie
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Rejoindre cette compagnie
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Envoyer un message à cette personne
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Envoyer un message à tous les joueurs de cette compagnie
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Envoyer un message à tous les spectateurs
STR_NETWORK_CLIENT_LIST_SPECTATORS :Spectateurs
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nouvelle compagnie)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Créer une nouvelle compagnie et la rejoindre
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}C'est vous
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}C'est l'hôte du jeu
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Exclure
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bannir
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Supprimer
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Débloquer le mot de passe
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Action administrative
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Êtes-vous sûr de vouloir exclure '{STRING}'{NBSP}?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Êtes-vous sûr de vouloir bannir '{STRING}'{NBSP}?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Êtes-vous sûr de vouloir supprimer la compagnie '{COMPANY}'{NBSP}?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Êtes-vous sûr de vouloir réinitialiser le mot de passe de la compagnie '{COMPANY}'?
STR_NETWORK_SERVER :Serveur
STR_NETWORK_CLIENT :Client
@ -2173,6 +2211,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Le serve
STR_NETWORK_ERROR_CLIENT_START :{WHITE}Échec de la connexion
STR_NETWORK_ERROR_TIMEOUT :{WHITE}La connexion n°{NBSP}{NUM} a dépassé le temps d'attente
STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Une erreur de protocole a été détectée et la connexion a été fermée
STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}Vous n'avez pas de nom. Il doit être entré en haut de la fenêtre Multijoueur
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Le numéro de version/révision de ce client ne correspond pas à celui du serveur
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Mot de passe incorrect
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Le serveur est complet
@ -2185,6 +2224,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Vous ave
STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Votre ordinateur est trop lent pour suivre le serveur
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Votre ordinateur a mis trop de temps pour télécharger la carte
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Votre ordinateur a mis trop de temps pour rejoindre le serveur
STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Votre nom n'est pas valide
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :erreur générale
@ -2207,6 +2247,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :aucun mot de pa
STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :délai dépassé
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :télécharger la carte a pris trop de temps
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :le traitement de la carte a pris trop de temps
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nom client invalide
############ End of leave-in-this-order
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possible perte de connexion
@ -3050,6 +3091,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Attention{
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Erreur{NBSP}: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Erreur fatale{NBSP}: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Une erreur NewGRF fatale est survenue{NBSP}:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Une erreur NewGRF est survenue{NBSP}:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} ne fonctionnera pas avec la version de TTDPatch rapportée par OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} est conçu pour la version {STRING} de TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} est conçu pour être utilisé avec {STRING}

@ -3785,6 +3785,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Warnung: {
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Fehler: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Schwerer Fehler: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ein schwerer NewGRF-Fehler ist aufgetreten:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Ein NewGRF-Fehler ist aufgetreten:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} funktioniert nicht im Zusammenhang mit der von OpenTTD ermittelten TTDPatch-Version
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} ist für die {STRING}-Version von TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} ist für die Nutzung mit {STRING} vorgesehen

@ -2231,8 +2231,8 @@ STR_CONFIG_ERROR :{WHITE}설정
STR_CONFIG_ERROR_ARRAY :{WHITE}... 배열 '{STRING}'에서 오류 발생
STR_CONFIG_ERROR_INVALID_VALUE :{WHITE}... '{1:STRING}'에 잘못된 값('{0:STRING}')이 지정되었습니다.
STR_CONFIG_ERROR_TRAILING_CHARACTERS :{WHITE}... '{STRING}' 설정의 끝에 후행 문자가 있습니다.
STR_CONFIG_ERROR_DUPLICATE_GRFID :{WHITE}... NewGRF '{STRING}' 무시중: '{STRING}'{G 1 "과" "와"} GRF ID가 겹침
STR_CONFIG_ERROR_INVALID_GRF :{WHITE}... 유효하지 않은 NewGRF '{STRING}' 무시중: {STRING}
STR_CONFIG_ERROR_DUPLICATE_GRFID :{WHITE}... '{STRING}' NewGRF를 무시합니다: '{STRING}'{G 1 "과" "와"} GRF ID가 겹침
STR_CONFIG_ERROR_INVALID_GRF :{WHITE}... 유효하지 않은 '{STRING}' NewGRF를 무시합니다: {STRING}
STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND :찾을 수 없음
STR_CONFIG_ERROR_INVALID_GRF_UNSAFE :사용하기에 불안함
STR_CONFIG_ERROR_INVALID_GRF_SYSTEM :NewGRF 시스템
@ -2649,6 +2649,7 @@ 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}사용할 수 없는 이름입니다
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}검색한 서버는 현재 버전에 비해 너무 오래된 서버입니다
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :일반 오류
@ -3927,7 +3928,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}경고: {S
STR_NEWGRF_ERROR_MSG_ERROR :{RED}오류: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}치명적 오류: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}치명적인 NewGRF 오류가 발생했습니다:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF 오류가 발생했습니다: {}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF 관련 오류가 발생했습니다:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING}{G 1 "은" "는"} OpenTTD에서 보고된 TTDPatch 버전에서 작동하지 않을 것입니다
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING}{G 1 "은" "는"} {STRING} 버전의 TTD를 위한 것입니다
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING}{G 1 "은" "는"} {STRING}{G 1 "와" "과"} 같이 사용해야 합니다

@ -961,7 +961,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malaysisk Ringg
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Venstrekjøring
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Høyrekjøring
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Bynavn
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Bynavn:
STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Velg nasjonalitet på bynavn
############ start of townname region
@ -2000,6 +2000,8 @@ STR_FACE_TIE :Slips:
STR_FACE_EARRING :Ørering:
STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Endre slips eller ørering
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privat
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Offentlig
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Flerspiller
@ -2063,6 +2065,8 @@ 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_VISIBILITY_LABEL :{BLACK}Synlighet
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Om andre mennesker kan se serveren din i den offentlige oppføringen
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
@ -2127,12 +2131,45 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Tjeneren
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Firmaet er beskyttet. Skriv inn passord
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Liste over klienter
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Påloggede spillere
STR_NETWORK_COMPANY_LIST_SPECTATE :Vær tilskuer
# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Flerspiller
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Server
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Navn
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Navnet på serveren du spiller på
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Rediger navnet på serveren
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Servernavn
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Synlighet
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Om andre mennesker kan se serveren din i den offentlige oppføringen
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Spiller
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Navn
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Ditt spillernavn
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Rediger ditt spillernavn
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Ditt spillernavn
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Administrative handlinger å utføre for denne klienten
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Administrative tiltak å utføre for dette firmaet
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Bli med i dette firmaet
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Send en melding til denne spilleren
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Send en melding til alle spillerne i dette firmaet
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Send en melding til alle tilskuerne
STR_NETWORK_CLIENT_LIST_SPECTATORS :Tilskuere
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nytt firma)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Opprett et nytt firma og bli med i det
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dette er deg
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dette er verten for spillet
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Spark
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Utesteng
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Slett
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Låse opp passord
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Administratorhandling
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Er du sikker på at du vil utestenge spiller '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Er du sikker på at du vil utestenge spiller '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Er du sikker på at du vil slette firmaet '{COMPANY}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Er du sikker på at du vil tilbakestille passordet til firma '{COMPANY}'?
STR_NETWORK_SERVER :Tjener
STR_NETWORK_CLIENT :Klient
@ -2191,6 +2228,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Din data
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
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}Den forespurte serveren er for gammel for denne klienten
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :generell feil
@ -3057,6 +3095,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Advarsel:
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Feil: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}En fatal NewGRF-feil har oppstått:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}En NewGRF feil har oppstått:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} virker ikke med TTDPatch-versjonen som er rapportert av OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} er for versjon {STRING} av TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} er laget for bruk med {STRING}

@ -960,7 +960,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit da Mal
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Circular pela esquerda
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Circular pela direita
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nomes das localidades
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nomes das localidades:
STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Seleccionar o estilo dos nomes das localidades
############ start of townname region
@ -1000,6 +1000,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Cada 12 meses
STR_GAME_OPTIONS_LANGUAGE :{BLACK}Idioma
STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}Seleccionar o idioma da interface do jogo
STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% completado)
STR_GAME_OPTIONS_FULLSCREEN :{BLACK}Ecrã Inteiro
STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}Seleccione esta opção para jogar o OpenTTD em modo de ecrã inteiro
@ -1997,6 +1998,8 @@ STR_FACE_TIE :Gravata:
STR_FACE_EARRING :Brinco:
STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Mudar gravata ou brinco
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multi-jogador
@ -2049,7 +2052,7 @@ STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Adiciona
STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Iniciar servidor
STR_NETWORK_SERVER_LIST_START_SERVER_TOOLTIP :{BLACK}Iniciar um servidor próprio
STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Digite teu nome
STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Introduza o seu nome
STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Introduza o endereço IP do servidor
# Start new multiplayer server
@ -2060,6 +2063,8 @@ 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_VISIBILITY_LABEL :{BLACK}Visibilidade
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se as outras pessoas podem ver o seu servidor na lista pública
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.
@ -2123,12 +2128,45 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introduza palavra-chave
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jogadores "online"
STR_NETWORK_COMPANY_LIST_SPECTATE :Assistir
# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multi-jogador
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nome
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nome do servidor onde está a jogar
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Editar o nome do seu servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nome do servidor
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidade
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Se as outras pessoas podem ver o seu servidor na lista pública
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jogador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nome
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}O seu nome de jogador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Editar o seu nome de jogador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :O seu nome de jogador
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Ações administrativas para executar a este cliente
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Ações administrativas para executar a esta empresa
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Juntar-se a esta empresa
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Enviar uma mensagem a este jogador
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Enviar uma mensagem a todos os jogadores desta empresa
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Enviar uma mensagem a todos os espectadores
STR_NETWORK_CLIENT_LIST_SPECTATORS :Espectadores
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova empresa)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Criar uma nova empresa e juntar-se a ela
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este é você
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este é o anfitrião do jogo
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Banir
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Apagar
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :desbloquear com palavra-passe
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Ação administrativa
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Tem a certeza que quer expulsar o jogador '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Tem a certeza que quer banir o jogador '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Tem a certeza que quer apagar a empresa '{COMPANY}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Tem a certeza que quer restabelecer a palavra-chave da empresa '{COMPANY}'?
STR_NETWORK_SERVER :Servidor
STR_NETWORK_CLIENT :Cliente
@ -2173,6 +2211,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}Não foi
STR_NETWORK_ERROR_CLIENT_START :{WHITE}Não foi possível estabelecer ligação
STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tempo de espera esgotado na conexão #{NUM}.
STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Ocorreu um erro de protocolo e a ligação foi encerrada
STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}O seu nome de jogador não foi definido. O nome pode ser definido no topo da janela de Multi-jogador
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}A revisão deste cliente não condiz com a revisão do servidor
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Palavra-chave incorrecta
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Servidor cheio
@ -2185,6 +2224,8 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Demorou
STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}O seu computador é demasiado lento para acompanhar com o servidor
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}O seu computador demorou demasiado a transferir o mapa
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}O seu computador demorou demasiado a ligar ao servidor
STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}O seu nome de jogador não é válido
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}O servidor consultado é muito antigo para este cliente
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :erro geral
@ -2207,6 +2248,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :não foi recebi
STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :demasiado tempo (geral)
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :demorou demasiado a transferir o mapa
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :demorou demasiado a processar o mapa
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nome de cliente inválido
############ End of leave-in-this-order
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Possível perda de conexão
@ -3050,6 +3092,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Aviso: {SI
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Erro: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ocorreu um erro fatal num NewGRF:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Ocorreu um erro de NewGRF:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} não funciona com a versão do TTDPatch reportada por OpenTTD.
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} é para a versão {STRING} do TTD.
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} foi concebido para ser usado com {STRING}

@ -396,7 +396,7 @@ STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}Если
STR_BUTTON_DEFAULT :{BLACK}По умолчанию
STR_BUTTON_CANCEL :{BLACK}Отмена
STR_BUTTON_OK :{BLACK}OK
STR_WARNING_PASSWORD_SECURITY :{YELLOW}Внимание: администраторы сервера могут увидеть ваш пароль.
STR_WARNING_PASSWORD_SECURITY :{YELLOW}Внимание: администраторы сервера могут увидеть текст, введённый в это поле.
# On screen keyboard window
STR_OSK_KEYBOARD_LAYOUT :`1234567890-=\qwertyuiop[]asdfghjkl;' zxcvbnm,./ .
@ -931,7 +931,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_PAUSED_LINK_GRAPH :{ORANGE}* * ПАУЗА (ожидает обновления графа распределения) * *
STR_STATUSBAR_AUTOSAVE :{RED}АВТОСОХРАНЕНИЕ
STR_STATUSBAR_SAVING_GAME :{RED}* * СОХРАНЕНИЕ ИГРЫ * *
@ -2151,6 +2151,8 @@ STR_FACE_TIE :Галстук:
STR_FACE_EARRING :Серьга:
STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Изменить галстук или серьгу
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Публичный
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Частный
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Сетевая игра
@ -2169,7 +2171,7 @@ STR_NETWORK_SERVER_LIST_DATE_CAPTION :{BLACK}Дата
STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP :{BLACK}Текущая дата
STR_NETWORK_SERVER_LIST_YEARS_CAPTION :{BLACK}Года
STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP :{BLACK}Количество лет{}в игре
STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP :{BLACK}Язык, версия сервера и т.п.
STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP :{BLACK}Язык, версия сервера и{NBSP}т.{NBSP}п.
STR_NETWORK_SERVER_LIST_CLICK_GAME_TO_SELECT :{BLACK}Выберите игру из списка
STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER :{BLACK}Последний сервер, к которому вы подключались:
@ -2184,20 +2186,20 @@ STR_NETWORK_SERVER_LIST_SERVER_VERSION :{SILVER}Вер
STR_NETWORK_SERVER_LIST_SERVER_ADDRESS :{SILVER}Адрес сервера: {WHITE}{STRING}
STR_NETWORK_SERVER_LIST_START_DATE :{SILVER}Дата начала: {WHITE}{DATE_SHORT}
STR_NETWORK_SERVER_LIST_CURRENT_DATE :{SILVER}Текущая дата: {WHITE}{DATE_SHORT}
STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Защищено паролем!
STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}СЕРВЕР ОТКЛЮЧЕН
STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Защищён паролем!
STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}СЕРВЕР ОТКЛЮЧЁН
STR_NETWORK_SERVER_LIST_SERVER_FULL :{SILVER}СЕРВЕР ЗАПОЛНЕН
STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}ВЕРСИЯ НЕ ПОДХОДИТ
STR_NETWORK_SERVER_LIST_GRF_MISMATCH :{SILVER}НЕ СОВПАДАЕТ НАБОР NEWGRF
STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Присоединиться
STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Обновить сервер
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_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}Поиск общедоступных серверов в интернете
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Искать в ЛВС
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Поиск серверов в локальной сети
STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Добавить сервер
STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Добавить сервер в список, который будет автоматически проверяться на идущие игры
STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Запуск сервера
@ -2214,15 +2216,17 @@ 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_VISIBILITY_LABEL :{BLACK}Видимость
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Видимость вашего сервера в публичном списке
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}Выбор максимального числа клиентов. Не все места должны быть заняты
STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбор максимального числа клиентов. Не все места обязательно должны быть заняты.
STR_NETWORK_START_SERVER_COMPANIES_SELECT :{BLACK}{NUM} компани{P я и й}
STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Макс. количество компаний:
STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Ограничить максимальное количество компаний на сервере
STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} наблюдател{P ь я ей}
STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Макс. количество наблюдателей:
STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Ограничить максимальное количество наблюдателей на сервере
STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} зрител{P ь я ей}
STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Макс. количество зрителей:
STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Ограничить максимальное количество зрителей на сервере
STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN :{BLACK}Язык общения:
STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP :{BLACK}Другие игроки будут знать, на каком языке общаются на сервере
@ -2232,7 +2236,7 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_OSKTITLE :{BLACK}Введ
STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}Состояние сетевой игры
STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}Подготовка соединения: {ORANGE}{STRING}
STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}Список компаний в игре. Вы можете присоединиться к существующей или основать новую, если есть свободный слот
STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}Список компаний в игре. Вы можете присоединиться к одной из существующих или основать новую, если есть свободная позиция.
STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}ИНФОРМАЦИЯ О КОМПАНИИ
STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}Название компании: {WHITE}{STRING}
@ -2277,22 +2281,49 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Серв
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Компания защищена. Введите пароль.
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Список клиентов
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Список игроков
STR_NETWORK_COMPANY_LIST_SPECTATE :Наблюдать
# Network client list
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Действия администратора, применимые к этому клиенту
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Сетевая игра
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Сервер
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Название
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Название вашего сервера
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Сменить название сервера
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Название сервера
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Видимость
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Видимость вашего сервера в публичном списке
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Игрок
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Имя
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Ваше игровое имя
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Изменить имя игрока
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Ваше игровое имя
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Административные действия, применимые к этому игроку
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Административные действия, применимые к этой компании
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Присоединиться к этой компании
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Отправить сообщение этому игроку
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Послать сообщение всем игрокам этой компании
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Послать сообщение всем зрителям
STR_NETWORK_CLIENT_LIST_SPECTATORS :Зрители
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Новая компания)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Основать новую транспортную компанию и присоединиться к ней
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Это вы!
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Это организатор игры
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Отключить
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Заблокировать
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Удалить
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Сбросить пароль
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Подтверждение действия
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}Отключить игрока «{STRING}»?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}Заблокировать игрока «{STRING}»?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}Удалить компанию «{COMPANY}»?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}Сбросить пароль у компании «{COMPANY}»?
STR_NETWORK_SERVER :Сервер
STR_NETWORK_CLIENT :Клиент
STR_NETWORK_SPECTATORS :Наблюдатели
STR_NETWORK_SPECTATORS :Зрители
# Network set password
STR_COMPANY_PASSWORD_CANCEL :{BLACK}Не сохранять пароль
@ -2337,8 +2368,8 @@ 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}Сервер переполнен
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас забанили на этом сервере
STR_NETWORK_ERROR_KICKED :{WHITE}Вас выкинули из игры
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас заблокировали на этом сервере
STR_NETWORK_ERROR_KICKED :{WHITE}Вас отключили от игры
STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Причина: {STRING}
STR_NETWORK_ERROR_CHEATER :{WHITE}Чит-коды не разрешены на этом сервере
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}Вы посылали на сервер слишком много команд
@ -2347,6 +2378,7 @@ 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}Неверно указано имя игрока
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}На сервере запущена устаревшая версия игры
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :общая ошибка
@ -2389,13 +2421,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :количес
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :подключение клиентов
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :вручную
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :игровой скрипт
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :ожидает обновления графы ссылок
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :ожидает обновления графа распределения
############ End of leave-in-this-order
STR_NETWORK_MESSAGE_CLIENT_LEAVING :покинул
STR_NETWORK_MESSAGE_CLIENT_LEAVING :отключение
STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} подключился к игре
STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} подключился к игре (клиент #{2:NUM})
STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} подключился к компании #{2:NUM}
STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} подключился наблюдателем
STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} подключился в качестве зрителя
STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} основал новую компанию (#{2:NUM})
STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} покинул игру ({2:STRING})
STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} изменил имя на {STRING}
@ -3240,6 +3272,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Внима
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Ошибка: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Критическая ошибка: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ошибка при работе с NewGRF:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Ошибка, связанная с модулем NewGRF:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} не будет работать с версией TTDPatch, сообщенной OpenTTD.
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :Файл {1:STRING} требует {STRING}-версию TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} сделан для использования совместно с {STRING}
@ -5371,7 +5404,7 @@ STR_DEFAULT_SIGN_NAME :Табличк
STR_COMPANY_SOMEONE :кто-то
STR_SAVEGAME_NAME_DEFAULT :{COMPANY}, {STRING}
STR_SAVEGAME_NAME_SPECTATOR :Наблюдатель, {1:STRING}
STR_SAVEGAME_NAME_SPECTATOR :Зритель, {1:STRING}
# Viewport strings
STR_VIEWPORT_TOWN_POP :{WHITE}{TOWN} ({COMMA})

@ -960,7 +960,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit malasio
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Conducir por la izquierda
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Conducir por la derecha
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de municipios
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de municipios:
STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Selección del estilo del nombre de los municipios
############ start of townname region
@ -1998,6 +1998,8 @@ STR_FACE_TIE :Corbata:
STR_FACE_EARRING :Pendientes:
STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambiar corbata o pendientes
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijugador
@ -2061,6 +2063,8 @@ 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_VISIBILITY_LABEL :{BLACK}Visibilidad
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Establece si otras personas pueden ver el servidor en la lista de servidores públicos
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
@ -2124,12 +2128,45 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introduce la contraseña
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jugadores en línea
STR_NETWORK_COMPANY_LIST_SPECTATE :Observar
# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijugador
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nombre
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nombre del servidor en el que estás jugando
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Modifica el nombre de tu servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nombre del servidor
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidad
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Establece si otras personas pueden ver el servidor en la lista de servidores públicos
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jugador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nombre
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Tu nombre de jugador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Modifica tu nombre de jugador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Tu nombre de jugador
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Acciones de administrador a realizar para este cliente
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Acciones de administrador a realizar para esta compañía
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Unirse a esta compañía
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Manda un mensaje a este jugador
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Manda un mensaje a todos los jugadores de esta compañía
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Manda un mensaje a todos los observadores
STR_NETWORK_CLIENT_LIST_SPECTATORS :Observadores
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nueva compañía)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crea una nueva companía y te une a ella
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Éste eres tú
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Éste es el servidor de la partida
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Prohibir el acceso
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Eliminar
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Eliminar contraseña
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Acción de administrador
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}¿Estás seguro de que deseas expulsar al jugador '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}¿Estás seguro de que deseas prohibir el acceso al jugador '{STRING}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}¿Estás seguro de que quieres eliminar la compañía '{COMPANY}'?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}¿Estás seguro de que quieres eliminar la contraseña de la compañía '{COMPANY}'?
STR_NETWORK_SERVER :Servidor
STR_NETWORK_CLIENT :Cliente
@ -2174,6 +2211,7 @@ STR_NETWORK_ERROR_SERVER_START :{WHITE}No se ha
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 ha producido un error de protocolo y la conexión ha sido cerrada
STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}No se ha establecido tu nombre de jugador. El nombre se puede establecer 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
@ -2186,6 +2224,7 @@ STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Has tard
STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Su ordenador es demasiado lento para seguir la velocidad del servidor
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Su ordenador necesitó demasiado tiempo para descargar el mapa
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Su ordenador necesitó demasiado tiempo para conectar 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
@ -2208,6 +2247,7 @@ STR_NETWORK_ERROR_CLIENT_TIMEOUT_PASSWORD :no se ha recibi
STR_NETWORK_ERROR_CLIENT_TIMEOUT_COMPUTER :tiempo agotado en general
STR_NETWORK_ERROR_CLIENT_TIMEOUT_MAP :la descarga del mapa ha necesitado demasiado tiempo
STR_NETWORK_ERROR_CLIENT_TIMEOUT_JOIN :el procesado del mapa ha necesitado demasiado tiempo
STR_NETWORK_ERROR_CLIENT_INVALID_CLIENT_NAME :nombre de cliente inválido
############ End of leave-in-this-order
STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}Posible pérdida de conexión
@ -3051,6 +3091,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Atención:
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Error Fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ha ocurrido un error fatal de NewGRF:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Ha ocurrido un error de NewGRF:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} no funcionará con la con la versión de TTDPatch informada por OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} es para la versión {STRING} de TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} está diseñado para ser usado con {STRING}

@ -960,7 +960,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit malasio
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Manejar por la izquierda
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Manejar por la derecha
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de pueblos
STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Nombres de pueblos:
STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Elegir el estilo de nombres para pueblos
############ start of townname region
@ -1998,6 +1998,8 @@ STR_FACE_TIE :Corbata:
STR_FACE_EARRING :Aretes:
STR_FACE_TIE_EARRING_TOOLTIP :{BLACK}Cambiar corbata o aretes
STR_NETWORK_SERVER_VISIBILITY_PRIVATE :Privado
STR_NETWORK_SERVER_VISIBILITY_PUBLIC :Público
# Network server list
STR_NETWORK_SERVER_LIST_CAPTION :{WHITE}Multijugador
@ -2061,6 +2063,8 @@ 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_VISIBILITY_LABEL :{BLACK}Visibilidad
STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Quién puede ver tu servidor en la lista pública
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
@ -2124,12 +2128,45 @@ STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}Servidor
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}Empresa protegida. Introducir contraseña
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Lista de clientes
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Jugadores conectados
STR_NETWORK_COMPANY_LIST_SPECTATE :Observar
# Network client list
STR_NETWORK_CLIENT_LIST_CAPTION :{WHITE}Multijugador
STR_NETWORK_CLIENT_LIST_SERVER :{BLACK}Servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME :{BLACK}Nombre
STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Nombre del servidor en el que estás jugando
STR_NETWORK_CLIENT_LIST_SERVER_NAME_EDIT_TOOLTIP :{BLACK}Modificar nombre del servidor
STR_NETWORK_CLIENT_LIST_SERVER_NAME_QUERY_CAPTION :Nombre del servidor
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Visibilidad
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY_TOOLTIP :{BLACK}Quién puede ver tu servidor en la lista pública
STR_NETWORK_CLIENT_LIST_PLAYER :{BLACK}Jugador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME :{BLACK}Nombre
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_TOOLTIP :{BLACK}Tu nombre de jugador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_EDIT_TOOLTIP :{BLACK}Modificar nombre de jugador
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Tu nombre de jugador
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP :{BLACK}Acciones administrativas para este cliente
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP :{BLACK}Acciones administrativas para esta empresa
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Unirse a esta empresa
STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP :{BLACK}Enviar mensaje a este jugador
STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP :{BLACK}Enviar mensaje a todos los jugadores de la empresa
STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP :{BLACK}Enviar mensaje a los espectadores
STR_NETWORK_CLIENT_LIST_SPECTATORS :Espectadores
STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nueva empresa)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crear nueva empresa y unirse a ella
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este eres tú
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este es el host del juego
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bloquear acceso
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET :Eliminar
STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK :Restablecer contraseña
STR_NETWORK_CLIENT_LIST_ASK_CAPTION :{WHITE}Acción de aministrador
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK :{YELLOW}¿Sacar al jugador "{STRING}"?
STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN :{YELLOW}¿Bloquear acceso al jugador "{STRING}"?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET :{YELLOW}¿Eliminar la empresa "{COMPANY}"?
STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK :{YELLOW}¿Restablecer contraseña de la empresa "{COMPANY}"?
STR_NETWORK_SERVER :Servidor
STR_NETWORK_CLIENT :Cliente
@ -2188,6 +2225,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Tu compu
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
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}El servidor es demasiado viejo para este cliente
############ Leave those lines in this order!!
STR_NETWORK_ERROR_CLIENT_GENERAL :error general
@ -3054,6 +3092,7 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Atención:
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Error fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Ocurrió un error fatal de NewGRF:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Ocurrió un error de NewGRF:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} no funcionará con la con la versión de TTDPatch reportada por OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} es la para la versión {STRING} de TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} está diseñado para usarse con {STRING}

@ -8,6 +8,7 @@ add_files(
game_info.h
host.cpp
host.h
os_abstraction.cpp
os_abstraction.h
packet.cpp
packet.h

@ -94,6 +94,18 @@ void NetworkAddress::GetAddressAsString(char *buffer, const char *last, bool wit
}
}
/**
* Get the address as a string, e.g. 127.0.0.1:12345.
* @param with_family whether to add the family (e.g. IPvX).
* @return the address
*/
std::string NetworkAddress::GetAddressAsString(bool with_family)
{
char buf[NETWORK_HOSTNAME_LENGTH + 6 + 7];
this->GetAddressAsString(buf, lastof(buf), with_family);
return buf;
}
/**
* Get the address as a string, e.g. 127.0.0.1:12345.
* @param with_family whether to add the family (e.g. IPvX).
@ -311,12 +323,11 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
{
const char *type = NetworkAddress::SocketTypeAsString(runp->ai_socktype);
const char *family = NetworkAddress::AddressFamilyAsString(runp->ai_family);
char address[NETWORK_HOSTNAME_LENGTH + 6 + 7];
NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(address, lastof(address));
std::string address = NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString();
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (sock == INVALID_SOCKET) {
DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkGetLastErrorString());
DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkError::GetLast().AsString());
return INVALID_SOCKET;
}
@ -325,8 +336,8 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed", type);
int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen);
if (err != 0 && NetworkGetLastError() != EINPROGRESS) {
DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address, family, NetworkGetLastErrorString());
if (err != 0 && !NetworkError::GetLast().IsConnectInProgress()) {
DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address.c_str(), family, NetworkError::GetLast().AsString());
closesocket(sock);
return INVALID_SOCKET;
}
@ -342,28 +353,28 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
tv.tv_sec = DEFAULT_CONNECT_TIMEOUT_SECONDS;
int n = select(FD_SETSIZE, NULL, &write_fd, NULL, &tv);
if (n < 0) {
DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address, NetworkGetLastErrorString());
DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), NetworkError::GetLast().AsString());
closesocket(sock);
return INVALID_SOCKET;
}
/* If no fd is selected, the timeout has been reached. */
if (n == 0) {
DEBUG(net, 1, "[%s] timed out while connecting to %s", type, address);
DEBUG(net, 1, "[%s] timed out while connecting to %s", type, address.c_str());
closesocket(sock);
return INVALID_SOCKET;
}
/* Retrieve last error, if any, on the socket. */
err = GetSocketError(sock);
if (err != 0) {
DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address, NetworkGetErrorString(err));
NetworkError socket_error = GetSocketError(sock);
if (socket_error.HasError()) {
DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address.c_str(), socket_error.AsString());
closesocket(sock);
return INVALID_SOCKET;
}
/* Connection succeeded. */
DEBUG(net, 1, "[%s] connected to %s", type, address);
DEBUG(net, 1, "[%s] connected to %s", type, address.c_str());
return sock;
}
@ -388,48 +399,47 @@ static SOCKET ListenLoopProc(addrinfo *runp)
{
const char *type = NetworkAddress::SocketTypeAsString(runp->ai_socktype);
const char *family = NetworkAddress::AddressFamilyAsString(runp->ai_family);
char address[NETWORK_HOSTNAME_LENGTH + 6 + 7];
NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString(address, lastof(address));
std::string address = NetworkAddress(runp->ai_addr, (int)runp->ai_addrlen).GetAddressAsString();
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (sock == INVALID_SOCKET) {
DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, NetworkGetLastErrorString());
DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString());
return INVALID_SOCKET;
}
if (runp->ai_socktype == SOCK_STREAM && !SetNoDelay(sock)) {
DEBUG(net, 3, "[%s] setting TCP_NODELAY failed for port %s", type, address);
DEBUG(net, 3, "[%s] setting TCP_NODELAY failed for port %s", type, address.c_str());
}
int on = 1;
/* The (const char*) cast is needed for windows!! */
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) {
DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, NetworkGetLastErrorString());
DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString());
}
#ifndef __OS2__
if (runp->ai_family == AF_INET6 &&
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) {
DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, NetworkGetLastErrorString());
DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address.c_str(), NetworkError::GetLast().AsString());
}
#endif
if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) {
DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, NetworkGetLastErrorString());
DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString());
closesocket(sock);
return INVALID_SOCKET;
}
if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, NetworkGetLastErrorString());
DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address.c_str(), NetworkError::GetLast().AsString());
closesocket(sock);
return INVALID_SOCKET;
}
/* Connection succeeded */
if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed for %s port %s", type, family, address);
if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed for %s port %s", type, family, address.c_str());
DEBUG(net, 1, "[%s] listening on %s port %s", type, family, address);
DEBUG(net, 1, "[%s] listening on %s port %s", type, family, address.c_str());
return sock;
}

@ -190,8 +190,8 @@ struct NetworkAddressDumper {
const char *GetAddressAsString(NetworkAddress *addr, bool with_family = true);
private:
/* 6 = for the : and 5 for the decimal port number */
char buf[NETWORK_HOSTNAME_LENGTH + 6 + 7];
/* 7 extra are for with_family, which adds " (IPvX)". */
char buf[NETWORK_HOSTNAME_PORT_LENGTH + 7];
};
#endif /* NETWORK_CORE_ADDRESS_H */

@ -57,6 +57,7 @@ static const byte NETWORK_MASTER_SERVER_VERSION = 2; ///< What vers
static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0'
static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0'
static const uint NETWORK_HOSTNAME_LENGTH = 80; ///< The maximum length of the host name, in bytes including '\0'
static const uint NETWORK_HOSTNAME_PORT_LENGTH = 80 + 6; ///< The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port number (with a max of 65536)
static const uint NETWORK_SERVER_ID_LENGTH = 33; ///< The maximum length of the network id of the servers, in bytes including '\0'
static const uint NETWORK_REVISION_LENGTH = 33; ///< The maximum length of the revision, in bytes including '\0'
static const uint NETWORK_LONG_REVISION_LENGTH = 64; ///< The maximum length of the revision, in bytes including '\0'

@ -13,7 +13,6 @@
#include "../../debug.h"
#include "os_abstraction.h"
#include "packet.h"
#include "../../string_func.h"
#include "../../safeguards.h"
@ -48,20 +47,3 @@ void NetworkCoreShutdown()
WSACleanup();
#endif
}
#if defined(_WIN32)
/**
* Return the string representation of the given error from the OS's network functions.
* @param error The error number (from \c NetworkGetLastError()).
* @return The error message, potentially an empty string but never \c nullptr.
*/
const char *NetworkGetErrorString(int error)
{
static char buffer[512];
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) {
seprintf(buffer, lastof(buffer), "Unknown error %d", error);
}
return buffer;
}
#endif /* defined(_WIN32) */

@ -74,7 +74,6 @@ struct NetworkGameInfo : NetworkServerGameInfo {
uint32 map_width; ///< Map width
uint32 map_height; ///< Map height
char server_name[NETWORK_NAME_LENGTH]; ///< Server name
char hostname[NETWORK_HOSTNAME_LENGTH]; ///< Hostname of the server (if any)
char short_server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0) (truncated)
char server_revision[NETWORK_LONG_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0)
bool dedicated; ///< Is this a dedicated server?

@ -0,0 +1,217 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* @file os_abstraction.cpp OS specific implementations of functions of the OS abstraction layer for network stuff.
*
* The general idea is to have simple abstracting functions for things that
* require different implementations for different environments.
* In here the functions, and their documentation, are defined only once
* and the implementation contains the #ifdefs to change the implementation.
* Since Windows is usually different that is usually the first case, after
* that the behaviour is usually Unix/BSD-like with occasional variation.
*/
#include "stdafx.h"
#include "os_abstraction.h"
#include "../../string_func.h"
#include <mutex>
#include "../../safeguards.h"
/**
* Construct the network error with the given error code.
* @param error The error code.
*/
NetworkError::NetworkError(int error) : error(error)
{
}
/**
* Check whether this error describes that the operation would block.
* @return True iff the operation would block.
*/
bool NetworkError::WouldBlock() const
{
#if defined(_WIN32)
return this->error == WSAEWOULDBLOCK;
#else
/* Usually EWOULDBLOCK and EAGAIN are the same, but sometimes they are not
* and the POSIX.1 specification states that either should be checked. */
return this->error == EWOULDBLOCK || this->error == EAGAIN;
#endif
}
/**
* Check whether this error describes a connection reset.
* @return True iff the connection is reset.
*/
bool NetworkError::IsConnectionReset() const
{
#if defined(_WIN32)
return this->error == WSAECONNRESET;
#else
return this->error == ECONNRESET;
#endif
}
/**
* Check whether this error describes a connect is in progress.
* @return True iff the connect is already in progress.
*/
bool NetworkError::IsConnectInProgress() const
{
#if defined(_WIN32)
return this->error == WSAEWOULDBLOCK;
#else
return this->error == EINPROGRESS;
#endif
}
/**
* Get the string representation of the error message.
* @return The string representation that will get overwritten by next calls.
*/
const char *NetworkError::AsString() const
{
if (this->message.empty()) {
#if defined(_WIN32)
char buffer[512];
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, this->error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) {
seprintf(buffer, lastof(buffer), "Unknown error %d", this->error);
}
this->message.assign(buffer);
#else
/* Make strerror thread safe by locking access to it. There is a thread safe strerror_r, however
* the non-POSIX variant is available due to defining _GNU_SOURCE meaning it is not portable.
* The problem with the non-POSIX variant is that it does not necessarily fill the buffer with
* the error message but can also return a pointer to a static bit of memory, whereas the POSIX
* variant always fills the buffer. This makes the behaviour too erratic to work with. */
static std::mutex mutex;
std::lock_guard<std::mutex> guard(mutex);
this->message.assign(strerror(this->error));
#endif
}
return this->message.c_str();
}
/**
* Check whether an error was actually set.
* @return True iff an error was set.
*/
bool NetworkError::HasError() const
{
return this->error != 0;
}
/**
* Get the last network error.
* @return The network error.
*/
/* static */ NetworkError NetworkError::GetLast()
{
#if defined(_WIN32)
return NetworkError(WSAGetLastError());
#elif defined(__OS2__)
return NetworkError(sock_errno());
#else
return NetworkError(errno);
#endif
}
/**
* Try to set the socket into non-blocking mode.
* @param d The socket to set the non-blocking more for.
* @return True if setting the non-blocking mode succeeded, otherwise false.
*/
bool SetNonBlocking(SOCKET d)
{
#if defined(_WIN32)
u_long nonblocking = 1;
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
#elif defined __EMSCRIPTEN__
return true;
#else
int nonblocking = 1;
return ioctl(d, FIONBIO, &nonblocking) == 0;
#endif
}
/**
* Try to set the socket into blocking mode.
* @param d The socket to set the blocking more for.
* @return True if setting the blocking mode succeeded, otherwise false.
*/
bool SetBlocking(SOCKET d)
{
#if defined(_WIN32)
u_long nonblocking = 0;
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
#elif defined __EMSCRIPTEN__
return true;
#else
int nonblocking = 0;
return ioctl(d, FIONBIO, &nonblocking) == 0;
#endif
}
/**
* Try to set the socket to not delay sending.
* @param d The socket to disable the delaying for.
* @return True if disabling the delaying succeeded, otherwise false.
*/
bool SetNoDelay(SOCKET d)
{
#ifdef __EMSCRIPTEN__
return true;
#else
int flags = 1;
/* The (const char*) cast is needed for windows */
return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char *)&flags, sizeof(flags)) == 0;
#endif
}
/**
* Try to shutdown the socket in one or both directions.
* @param d The socket to disable the delaying for.
* @param read Whether to shutdown the read direction.
* @param write Whether to shutdown the write direction.
* @param linger_timeout The socket linger timeout.
* @return True if successful
*/
bool ShutdownSocket(SOCKET d, bool read, bool write, uint linger_timeout)
{
if (!read && !write) return true;
#ifdef _WIN32
LINGER ln = { 1U, (uint16) linger_timeout };
#else
struct linger ln = { 1, (int) linger_timeout };
#endif
setsockopt(d, SOL_SOCKET, SO_LINGER, (const char*)&ln, sizeof(ln));
int how = SD_BOTH;
if (!read) how = SD_SEND;
if (!write) how = SD_RECEIVE;
return shutdown(d, how) == 0;
}
/**
* Get the error from a socket, if any.
* @param d The socket to get the error from.
* @return The errno on the socket.
*/
NetworkError GetSocketError(SOCKET d)
{
int err;
socklen_t len = sizeof(err);
getsockopt(d, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
return NetworkError(err);
}

@ -14,6 +14,26 @@
#ifndef NETWORK_CORE_OS_ABSTRACTION_H
#define NETWORK_CORE_OS_ABSTRACTION_H
/**
* Abstraction of a network error where all implementation details of the
* error codes are encapsulated in this class and the abstraction layer.
*/
class NetworkError {
private:
int error; ///< The underlying error number from errno or WSAGetLastError.
mutable std::string message; ///< The string representation of the error (set on first call to #AsString).
public:
NetworkError(int error);
bool HasError() const;
bool WouldBlock() const;
bool IsConnectionReset() const;
bool IsConnectInProgress() const;
const char *AsString() const;
static NetworkError GetLast();
};
/* Include standard stuff per OS */
/* Windows stuff */
@ -23,21 +43,6 @@
#include <ws2tcpip.h>
#include <windows.h>
/**
* Get the last error code from any of the OS's network functions.
* What it returns and when it is reset, is implementation defined.
* @return The last error code.
*/
#define NetworkGetLastError() WSAGetLastError()
#undef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#undef ECONNRESET
#define ECONNRESET WSAECONNRESET
#undef EINPROGRESS
#define EINPROGRESS WSAEWOULDBLOCK
const char *NetworkGetErrorString(int error);
/* Windows has some different names for some types */
typedef unsigned long in_addr_t;
@ -74,10 +79,7 @@ typedef unsigned long in_addr_t;
# endif
# define SOCKET int
# define INVALID_SOCKET -1
# define ioctlsocket ioctl
# define closesocket close
# define NetworkGetLastError() (errno)
# define NetworkGetErrorString(error) (strerror(error))
# define SD_RECEIVE SHUT_RD
# define SD_SEND SHUT_WR
# define SD_BOTH SHUT_RDWR
@ -128,10 +130,7 @@ typedef unsigned long in_addr_t;
#if defined(__OS2__)
# define SOCKET int
# define INVALID_SOCKET -1
# define ioctlsocket ioctl
# define closesocket close
# define NetworkGetLastError() (sock_errno())
# define NetworkGetErrorString(error) (strerror(error))
# define SD_RECEIVE SHUT_RD
# define SD_SEND SHUT_WR
# define SD_BOTH SHUT_RDWR
@ -206,105 +205,11 @@ static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address
}
#endif
/**
* Return the string representation of the last error from the OS's network functions.
* @return The error message, potentially an empty string but never \c nullptr.
*/
static inline const char *NetworkGetLastErrorString()
{
return NetworkGetErrorString(NetworkGetLastError());
}
/**
* Try to set the socket into non-blocking mode.
* @param d The socket to set the non-blocking more for.
* @return True if setting the non-blocking mode succeeded, otherwise false.
*/
static inline bool SetNonBlocking(SOCKET d)
{
#ifdef __EMSCRIPTEN__
return true;
#else
# ifdef _WIN32
u_long nonblocking = 1;
# else
int nonblocking = 1;
# endif
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
#endif
}
/**
* Try to set the socket into blocking mode.
* @param d The socket to set the blocking more for.
* @return True if setting the blocking mode succeeded, otherwise false.
*/
static inline bool SetBlocking(SOCKET d)
{
#ifdef _WIN32
u_long nonblocking = 0;
#else
int nonblocking = 0;
#endif
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
}
/**
* Try to set the socket to not delay sending.
* @param d The socket to disable the delaying for.
* @return True if disabling the delaying succeeded, otherwise false.
*/
static inline bool SetNoDelay(SOCKET d)
{
#ifdef __EMSCRIPTEN__
return true;
#else
/* XXX should this be done at all? */
int b = 1;
/* The (const char*) cast is needed for windows */
return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
#endif
}
/**
* Try to shutdown the socket in one or both directions.
* @param d The socket to disable the delaying for.
* @param read Whether to shutdown the read direction.
* @param write Whether to shutdown the write direction.
* @param linger_timeout The socket linger timeout.
* @return True if successful
*/
static inline bool ShutdownSocket(SOCKET d, bool read, bool write, uint linger_timeout)
{
if (!read && !write) return true;
#ifdef _WIN32
LINGER ln = { 1U, (uint16) linger_timeout };
#else
struct linger ln = { 1, (int) linger_timeout };
#endif
setsockopt(d, SOL_SOCKET, SO_LINGER, (const char*)&ln, sizeof(ln));
int how = SD_BOTH;
if (!read) how = SD_SEND;
if (!write) how = SD_RECEIVE;
return shutdown(d, how) == 0;
}
/**
* Get the error from a socket, if any.
* @param d The socket to get the error from.
* @return The errno on the socket.
*/
static inline int GetSocketError(SOCKET d)
{
int err;
socklen_t len = sizeof(err);
getsockopt(d, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
return err;
}
bool SetNonBlocking(SOCKET d);
bool SetBlocking(SOCKET d);
bool SetNoDelay(SOCKET d);
bool ShutdownSocket(SOCKET d, bool read, bool write, uint linger_timeout);
NetworkError GetSocketError(SOCKET d);
/* Make sure these structures have the size we expect them to be */
static_assert(sizeof(in_addr) == 4); ///< IPv4 addresses should be 4 bytes.

@ -114,11 +114,11 @@ SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down)
Packet *p = this->packet_queue.front().get();
res = p->TransferOut<int>(send, this->sock, 0);
if (res == -1) {
int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
NetworkError err = NetworkError::GetLast();
if (!err.WouldBlock()) {
/* Something went wrong.. close client! */
if (!closing_down) {
DEBUG(net, 0, "send failed with error %s", NetworkGetErrorString(err));
DEBUG(net, 0, "send failed with error %s", err.AsString());
this->CloseConnection();
}
return SPS_CLOSED;
@ -165,10 +165,10 @@ std::unique_ptr<Packet> NetworkTCPSocketHandler::ReceivePacket()
while (p->RemainingBytesToTransfer() != 0) {
res = p->TransferIn<int>(recv, this->sock, 0);
if (res == -1) {
int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
/* Something went wrong... (ECONNRESET is connection reset by peer) */
if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err));
NetworkError err = NetworkError::GetLast();
if (!err.WouldBlock()) {
/* Something went wrong... */
if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString());
this->CloseConnection();
return nullptr;
}
@ -194,10 +194,10 @@ std::unique_ptr<Packet> NetworkTCPSocketHandler::ReceivePacket()
while (p->RemainingBytesToTransfer() != 0) {
res = p->TransferIn<int>(recv, this->sock, 0);
if (res == -1) {
int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
/* Something went wrong... (ECONNRESET is connection reset by peer) */
if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err));
NetworkError err = NetworkError::GetLast();
if (!err.WouldBlock()) {
/* Something went wrong... */
if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString());
this->CloseConnection();
return nullptr;
}

@ -27,8 +27,8 @@ static const char* _packet_game_type_names[] {
"SERVER_ERROR",
"CLIENT_COMPANY_INFO",
"SERVER_COMPANY_INFO",
"CLIENT_GAME_INFO",
"SERVER_GAME_INFO",
"CLIENT_GAME_INFO",
"SERVER_GAME_INFO_EXTENDED",
"SERVER_CHECK_NEWGRFS",
"CLIENT_NEWGRFS_CHECKED",

@ -44,8 +44,8 @@ enum PacketGameType {
PACKET_SERVER_COMPANY_INFO, ///< Information about a single company.
/* Packets used to get the game info. */
PACKET_CLIENT_GAME_INFO, ///< Request information about the server.
PACKET_SERVER_GAME_INFO, ///< Information about the server.
PACKET_CLIENT_GAME_INFO, ///< Request information about the server.
/*
* Packets after here assume that the client

@ -12,7 +12,7 @@
#include "../../stdafx.h"
#include "../../debug.h"
#include "../../rev.h"
#include "../network_func.h"
#include "../network_internal.h"
#include "game_info.h"
#include "tcp_http.h"
@ -203,11 +203,7 @@ int NetworkHTTPSocketHandler::HandleHeader()
*url = '\0';
/* Fetch the hostname, and possible port number. */
const char *port = nullptr;
ParseConnectionString(&port, hname);
NetworkAddress address(hname, port == nullptr ? 80 : atoi(port));
NetworkAddress address = ParseConnectionString(hname, 80);
/* Restore the URL. */
*url = '/';
@ -229,10 +225,10 @@ int NetworkHTTPSocketHandler::Receive()
for (;;) {
ssize_t res = recv(this->sock, (char *)this->recv_buffer + this->recv_pos, lengthof(this->recv_buffer) - this->recv_pos, 0);
if (res == -1) {
int err = NetworkGetLastError();
if (err != EWOULDBLOCK) {
/* Something went wrong... (ECONNRESET is connection reset by peer) */
if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err));
NetworkError err = NetworkError::GetLast();
if (!err.WouldBlock()) {
/* Something went wrong... */
if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString());
return -1;
}
/* Connection would block, so stop for now */

@ -64,7 +64,7 @@ public:
DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str());
if (p.TransferOut<int>(send, s, 0) < 0) {
DEBUG(net, 0, "send failed with error %s", NetworkGetLastErrorString());
DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString());
}
closesocket(s);
break;
@ -81,7 +81,7 @@ public:
p.PrepareToSend();
if (p.TransferOut<int>(send, s, 0) < 0) {
DEBUG(net, 0, "send failed with error %s", NetworkGetLastErrorString());
DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString());
}
closesocket(s);
@ -151,7 +151,7 @@ public:
if (sockets.size() == 0) {
DEBUG(net, 0, "[server] could not start network: could not create listening socket");
NetworkError(STR_NETWORK_ERROR_SERVER_START);
ShowNetworkError(STR_NETWORK_ERROR_SERVER_START);
return false;
}

@ -127,7 +127,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
/* Enable broadcast */
unsigned long val = 1;
if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkGetLastErrorString());
DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkError::GetLast().AsString());
}
}
@ -136,7 +136,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
DEBUG(net, 7, "[udp] sendto(%s)", NetworkAddressDumper().GetAddressAsString(&send));
/* Check for any errors, but ignore it otherwise */
if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", NetworkAddressDumper().GetAddressAsString(&send), NetworkGetLastErrorString());
if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", NetworkAddressDumper().GetAddressAsString(&send), NetworkError::GetLast().AsString());
if (!all) break;
}

@ -306,7 +306,7 @@ uint NetworkCalculateLag(const NetworkClientSocket *cs)
/* There was a non-recoverable error, drop back to the main menu with a nice
* error */
void NetworkError(StringID error_string)
void ShowNetworkError(StringID error_string)
{
_switch_mode = SM_MENU;
ShowErrorMessage(error_string, INVALID_STRING_ID, WL_CRITICAL);
@ -476,14 +476,14 @@ static void CheckPauseOnJoin()
}
/**
* Converts a string to ip/port
* Format: IP:port
* Converts a string to ip/port/company
* Format: IP:port#company
*
* connection_string will be re-terminated to separate out the hostname, port will
* be set to the port strings given by the user, inside the memory area originally
* occupied by connection_string.
* occupied by connection_string. Similar for company, if set.
*/
void ParseConnectionString(const char **port, char *connection_string)
void ParseFullConnectionString(const char **company, const char **port, char *connection_string)
{
bool ipv6 = (strchr(connection_string, ':') != strrchr(connection_string, ':'));
for (char *p = connection_string; *p != '\0'; p++) {
@ -496,6 +496,12 @@ void ParseConnectionString(const char **port, char *connection_string)
ipv6 = false;
break;
case '#':
if (company == nullptr) continue;
*company = p + 1;
*p = '\0';
break;
case ':':
if (ipv6) break;
*port = p + 1;
@ -506,38 +512,48 @@ void ParseConnectionString(const char **port, char *connection_string)
}
/**
* Converts a string to ip/port/company
* Format: IP:port#company
* Convert a string containing either "hostname" or "hostname:ip" to a
* NetworkAddress.
*
* connection_string will be re-terminated to separate out the hostname, and company and port will
* be set to the company and port strings given by the user, inside the memory area originally
* occupied by connection_string.
* @param connection_string The string to parse.
* @param default_port The default port to set port to if not in connection_string.
* @return A valid NetworkAddress of the parsed information.
*/
void ParseGameConnectionString(const char **company, const char **port, char *connection_string)
NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port)
{
bool ipv6 = (strchr(connection_string, ':') != strrchr(connection_string, ':'));
for (char *p = connection_string; *p != '\0'; p++) {
switch (*p) {
case '[':
ipv6 = true;
break;
char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH];
strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string));
case ']':
ipv6 = false;
break;
const char *port = nullptr;
ParseFullConnectionString(nullptr, &port, internal_connection_string);
case '#':
*company = p + 1;
*p = '\0';
break;
int rport = port != nullptr ? atoi(port) : default_port;
return NetworkAddress(internal_connection_string, rport);
}
case ':':
if (ipv6) break;
*port = p + 1;
*p = '\0';
break;
}
}
/**
* Convert a string containing either "hostname" or "hostname:ip" to a
* NetworkAddress, where the string can be postfixed with "#company" to
* indicate the requested company.
*
* @param company Pointer to the company variable to set iff indicted.
* @param connection_string The string to parse.
* @param default_port The default port to set port to if not in connection_string.
* @return A valid NetworkAddress of the parsed information.
*/
NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port)
{
char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH + 4]; // 4 extra for the "#" and company
strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string));
const char *port_s = nullptr;
const char *company_s = nullptr;
ParseFullConnectionString(&company_s, &port_s, internal_connection_string);
if (company_s != nullptr) *company = (CompanyID)atoi(company_s);
int port = port_s != nullptr ? atoi(port_s) : default_port;
return NetworkAddress(internal_connection_string, port);
}
/**
@ -619,8 +635,11 @@ static void NetworkInitialize(bool close_admins = true)
/** Non blocking connection create to query servers */
class TCPQueryConnecter : TCPConnecter {
private:
bool request_company_info;
public:
TCPQueryConnecter(const NetworkAddress &address) : TCPConnecter(address) {}
TCPQueryConnecter(const NetworkAddress &address, bool request_company_info) : TCPConnecter(address), request_company_info(request_company_info) {}
void OnFailure() override
{
@ -630,45 +649,53 @@ public:
void OnConnect(SOCKET s) override
{
_networking = true;
new ClientNetworkGameSocketHandler(s);
MyClient::SendInformationQuery();
new ClientNetworkGameSocketHandler(s, address);
MyClient::SendInformationQuery(request_company_info);
}
};
/**
* Query a server to fetch his game-info.
* @param address the address to query.
* @param request_company_info Whether to request company info too.
*/
void NetworkTCPQueryServer(NetworkAddress address)
void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info)
{
if (!_network_available) return;
NetworkDisconnect();
NetworkInitialize();
new TCPQueryConnecter(address);
new TCPQueryConnecter(address, request_company_info);
}
/* Validates an address entered as a string and adds the server to
/**
* Validates an address entered as a string and adds the server to
* the list. If you use this function, the games will be marked
* as manually added. */
void NetworkAddServer(const char *b)
* as manually added.
* @param connection_string The IP:port of the server to add.
* @return The entry on the game list.
*/
NetworkGameList *NetworkAddServer(const std::string &connection_string)
{
if (*b != '\0') {
const char *port = nullptr;
char host[NETWORK_HOSTNAME_LENGTH];
uint16 rport;
if (connection_string.empty()) return nullptr;
strecpy(host, b, lastof(host));
NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT);
strecpy(_settings_client.network.connect_to_ip, b, lastof(_settings_client.network.connect_to_ip));
rport = NETWORK_DEFAULT_PORT;
/* Ensure the item already exists in the list */
NetworkGameList *item = NetworkGameListAddItem(address);
if (StrEmpty(item->info.server_name)) {
ClearGRFConfigList(&item->info.grfconfig);
address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name));
item->manually = true;
ParseConnectionString(&port, host);
if (port != nullptr) rport = atoi(port);
NetworkUDPQueryServer(NetworkAddress(host, rport), true);
NetworkRebuildHostList();
UpdateNetworkGameWindow();
}
NetworkTCPQueryServer(address);
return item;
}
/**
@ -707,41 +734,99 @@ public:
void OnFailure() override
{
NetworkError(STR_NETWORK_ERROR_NOCONNECTION);
ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
}
void OnConnect(SOCKET s) override
{
_networking = true;
new ClientNetworkGameSocketHandler(s);
new ClientNetworkGameSocketHandler(s, this->address);
IConsoleCmdExec("exec scripts/on_client.scr 0");
NetworkClient_Connected();
}
};
/* Used by clients, to connect to a server */
void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password, const char *join_company_password)
/**
* Join a client to the server at with the given connection string.
* The default for the passwords is \c nullptr. When the server or company needs a
* password and none is given, the user is asked to enter the password in the GUI.
* This function will return false whenever some information required to join is not
* correct such as the company number or the client's name, or when there is not
* networking avalabile at all. If the function returns false the connection with
* the existing server is not disconnected.
* It will return true when it starts the actual join process, i.e. when it
* actually shows the join status window.
*
* @param connection_string The IP address, port and company number to join as.
* @param default_company The company number to join as when none is given.
* @param join_server_password The password for the server.
* @param join_company_password The password for the company.
* @return Whether the join has started.
*/
bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password)
{
if (!_network_available) return;
CompanyID join_as = default_company;
NetworkAddress address = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT);
if (port == 0) return;
if (join_as != COMPANY_NEW_COMPANY && join_as != COMPANY_SPECTATOR) {
join_as--;
if (join_as >= MAX_COMPANIES) {
return false;
}
}
if (!NetworkValidateClientName()) return;
return NetworkClientConnectGame(address, join_as, join_server_password, join_company_password);
}
/**
* Join a client to the server at the given address.
* See the overloaded NetworkClientConnectGame for more details.
*
* @param address The network address of the server to join to.
* @param join_as The company number to join as.
* @param join_server_password The password for the server.
* @param join_company_password The password for the company.
* @return Whether the join has started.
*/
bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password, const char *join_company_password)
{
if (!_network_available) return false;
if (!NetworkValidateClientName()) return false;
_network_join.address = address;
_network_join.company = join_as;
_network_join.server_password = join_server_password;
_network_join.company_password = join_company_password;
strecpy(_settings_client.network.last_host, hostname, lastof(_settings_client.network.last_host));
_settings_client.network.last_port = port;
_network_join_as = join_as;
_network_join_server_password = join_server_password;
_network_join_company_password = join_company_password;
if (_game_mode == GM_MENU) {
/* From the menu we can immediately continue with the actual join. */
NetworkClientJoinGame();
} else {
/* When already playing a game, first go back to the main menu. This
* disconnects the user from the current game, meaning we can safely
* load in the new. After all, there is little point in continueing to
* play on a server if we are connecting to another one.
*/
_switch_mode = SM_JOIN_GAME;
}
return true;
}
/**
* Actually perform the joining to the server. Use #NetworkClientConnectGame
* when you want to connect to a specific server/company. This function
* assumes _network_join is already fully set up.
*/
void NetworkClientJoinGame()
{
NetworkDisconnect();
NetworkInitialize();
strecpy(_settings_client.network.last_joined, _network_join.address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined));
_network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
ShowJoinStatusWindow();
new TCPClientConnecter(NetworkAddress(hostname, port));
new TCPClientConnecter(_network_join.address);
}
static void NetworkInitGameInfo()
@ -1126,13 +1211,14 @@ static void NetworkGenerateServerId()
seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output);
}
void NetworkStartDebugLog(const char *hostname, uint16 port)
void NetworkStartDebugLog(const std::string &connection_string)
{
extern SOCKET _debug_socket; // Comes from debug.c
DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", hostname, port);
NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT);
DEBUG(net, 0, "Redirecting DEBUG() to %s", address.GetAddressAsString().c_str());
NetworkAddress address(hostname, port);
SOCKET s = address.Connect();
if (s == INVALID_SOCKET) {
DEBUG(net, 0, "Failed to open socket for redirection DEBUG()");
@ -1180,9 +1266,9 @@ void NetworkShutDown()
#ifdef __EMSCRIPTEN__
extern "C" {
void CDECL em_openttd_add_server(const char *host, int port)
void CDECL em_openttd_add_server(const char *connection_string)
{
NetworkUDPQueryServer(NetworkAddress(host, port), true);
NetworkAddServer(connection_string);
}
}

@ -150,9 +150,9 @@ void ClientNetworkEmergencySave()
* Create a new socket for the client side of the game connection.
* @param s The socket to connect with.
*/
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler (SOCKET s)
: NetworkGameSocketHandler (s),
savegame (nullptr), token (0), status (STATUS_INACTIVE)
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler (SOCKET s, NetworkAddress address)
: NetworkGameSocketHandler(s),
address(address), savegame(nullptr), token(0), status(STATUS_INACTIVE)
{
assert(ClientNetworkGameSocketHandler::my_client == nullptr);
ClientNetworkGameSocketHandler::my_client = this;
@ -324,7 +324,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
#endif
if (_sync_state_checksum != _state_checksum.state) info.flags |= DesyncExtraInfo::DEIF_STATE;
NetworkError(STR_NETWORK_ERROR_DESYNC);
ShowNetworkError(STR_NETWORK_ERROR_DESYNC);
DEBUG(desync, 1, "sync_err: date{%08x; %02x; %02x} {%x, " OTTD_PRINTFHEX64 "} != {%x, " OTTD_PRINTFHEX64 "}"
, _date, _date_fract, _tick_skip_counter, _sync_seed_1, _sync_state_checksum, _random.state[0], _state_checksum.state);
DEBUG(net, 0, "Sync error detected!");
@ -389,13 +389,8 @@ static uint8 _network_server_max_companies;
/** Maximum number of spectators of the currently joined server. */
static uint8 _network_server_max_spectators;
/** Who would we like to join as. */
CompanyID _network_join_as;
/** Login password from -p argument */
const char *_network_join_server_password = nullptr;
/** Company password from -P argument */
const char *_network_join_company_password = nullptr;
/** Information about the game to join to. */
NetworkJoinInfo _network_join;
/** Make sure the server ID length is the same as a md5 hash. */
static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1);
@ -408,11 +403,9 @@ static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1);
/**
* Query the server for server information.
*/
NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery()
NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery(bool request_company_info)
{
my_client->status = STATUS_COMPANY_INFO;
_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
my_client->status = STATUS_GAME_INFO;
Packet *p = new Packet(PACKET_CLIENT_GAME_INFO);
p->Send_uint32(FIND_SERVER_EXTENDED_TOKEN);
@ -421,7 +414,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery()
p->Send_uint16(0); // version
my_client->SendPacket(p);
my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO));
if (request_company_info) {
my_client->status = STATUS_COMPANY_INFO;
_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO));
}
return NETWORK_RECV_STATUS_OKAY;
}
@ -437,7 +436,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendJoin()
p->Send_string(_openttd_revision);
p->Send_uint32(_openttd_newgrf_version);
p->Send_string(_settings_client.network.client_name); // Client name
p->Send_uint8 (_network_join_as); // PlayAs
p->Send_uint8 (_network_join.company); // PlayAs
p->Send_uint8 (0); // Used to be language
my_client->SendPacket(p);
return NETWORK_RECV_STATUS_OKAY;
@ -698,9 +697,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p)
{
if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_INACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_GAME_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
NetworkGameList *item = GetLobbyGameInfo();
if (item == nullptr) {
/* This is not the lobby, so add it to the game list. */
item = NetworkGameListAddItem(this->address);
}
/* Clear any existing GRFConfig chain. */
ClearGRFConfigList(&item->info.grfconfig);
@ -711,6 +714,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packe
/* Ensure we consider the server online. */
item->online = true;
/* It could be either window, but only one is open, so redraw both. */
SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
/* We will receive company info next, so keep connection open. */
@ -870,6 +875,15 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p
NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8();
/* If we query a server that is 1.11.1 or older, we get an
* NETWORK_ERROR_NOT_EXPECTED on requesting the game info. Show a special
* error popup in that case.
*/
if (error == NETWORK_ERROR_NOT_EXPECTED && (this->status == STATUS_GAME_INFO || this->status == STATUS_COMPANY_INFO)) {
ShowErrorMessage(STR_NETWORK_ERROR_SERVER_TOO_OLD, INVALID_STRING_ID, WL_CRITICAL);
return NETWORK_RECV_STATUS_CLOSE_QUERY;
}
StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
/* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
@ -933,7 +947,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSW
p->Recv_string(_password_server_id, sizeof(_password_server_id));
if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
const char *password = _network_join_server_password;
const char *password = _network_join.server_password;
if (!StrEmpty(password)) {
return SendGamePassword(password);
}
@ -952,7 +966,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PA
p->Recv_string(_password_server_id, sizeof(_password_server_id));
if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
const char *password = _network_join_company_password;
const char *password = _network_join.company_password;
if (!StrEmpty(password)) {
return SendCompanyPassword(password);
}
@ -1077,10 +1091,10 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
/* New company/spectator (invalid company) or company we want to join is not active
* Switch local company to spectator and await the server's judgement */
if (_network_join_as == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join_as)) {
if (_network_join.company == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join.company)) {
SetLocalCompany(COMPANY_SPECTATOR);
if (_network_join_as != COMPANY_SPECTATOR) {
if (_network_join.company != COMPANY_SPECTATOR) {
/* We have arrived and ready to start playing; send a command to make a new company;
* the server will give us a client-id and let us in */
_network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
@ -1089,7 +1103,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
}
} else {
/* take control over an existing company */
SetLocalCompany(_network_join_as);
SetLocalCompany(_network_join.company);
}
return NETWORK_RECV_STATUS_OKAY;
@ -1420,6 +1434,7 @@ const char *ClientNetworkGameSocketHandler::GetServerStatusName(ServerStatus sta
{
static const char* _server_status_names[] {
"INACTIVE",
"GAME_INFO",
"COMPANY_INFO",
"JOIN",
"NEWGRFS_CHECK",

@ -15,12 +15,14 @@
/** Class for handling the client side of the game connection. */
class ClientNetworkGameSocketHandler : public NetworkGameSocketHandler {
private:
NetworkAddress address; ///< Address we are connected to.
struct PacketReader *savegame; ///< Packet reader for reading the savegame.
byte token; ///< The token we need to send back to the server to prove we're the right client.
/** Status of the connection with the server. */
enum ServerStatus {
STATUS_INACTIVE, ///< The client is not connected nor active.
STATUS_GAME_INFO, ///< We are trying to get the game information.
STATUS_COMPANY_INFO, ///< We are trying to get company information.
STATUS_JOIN, ///< We are trying to join a server.
STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs.
@ -84,7 +86,7 @@ protected:
static NetworkRecvStatus SendMapOk();
void CheckConnection();
public:
ClientNetworkGameSocketHandler(SOCKET s);
ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address);
~ClientNetworkGameSocketHandler();
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override;
@ -92,7 +94,7 @@ public:
std::string GetDebugInfo() const override;
static NetworkRecvStatus SendInformationQuery();
static NetworkRecvStatus SendInformationQuery(bool request_company_info);
static NetworkRecvStatus SendJoin();
static NetworkRecvStatus SendCommand(const CommandPacket *cp);
@ -127,9 +129,15 @@ typedef ClientNetworkGameSocketHandler MyClient;
void NetworkClient_Connected();
void NetworkClientSetCompanyPassword(const char *password);
extern CompanyID _network_join_as;
/** Information required to join a server. */
struct NetworkJoinInfo {
NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr), company_password(nullptr) {}
NetworkAddress address; ///< The address of the server to join.
CompanyID company; ///< The company to join.
const char *server_password; ///< The password of the server to join.
const char *company_password; ///< The password of the company to join.
};
extern const char *_network_join_server_password;
extern const char *_network_join_company_password;
extern NetworkJoinInfo _network_join;
#endif /* NETWORK_CLIENT_H */

@ -45,14 +45,14 @@ void NetworkReboot();
void NetworkDisconnect(bool blocking = false, bool close_admins = true);
void NetworkGameLoop();
void NetworkBackgroundLoop();
void ParseConnectionString(const char **port, char *connection_string);
void ParseGameConnectionString(const char **company, const char **port, char *connection_string);
void NetworkStartDebugLog(const char *hostname, uint16 port);
void ParseFullConnectionString(const char **company, const char **port, char *connection_string);
void NetworkStartDebugLog(const std::string &connection_string);
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats);
void NetworkUpdateClientInfo(ClientID client_id);
void NetworkClientsToSpectators(CompanyID cid);
void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr);
bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password = nullptr, const char *join_company_password = nullptr);
void NetworkClientJoinGame();
void NetworkClientRequestMove(CompanyID company, const char *pass = "");
void NetworkClientSendRcon(const char *password, const char *command);
void NetworkClientSendSettingsPassword(const char *password);

@ -51,7 +51,6 @@ static void NetworkGameListHandleDelayedInsert()
ClearGRFConfigList(&item->info.grfconfig);
memset(&item->info, 0, sizeof(item->info));
strecpy(item->info.server_name, ins_item->info.server_name, lastof(item->info.server_name));
strecpy(item->info.hostname, ins_item->info.hostname, lastof(item->info.hostname));
item->online = false;
}
item->manually |= ins_item->manually;
@ -70,15 +69,6 @@ static void NetworkGameListHandleDelayedInsert()
*/
NetworkGameList *NetworkGameListAddItem(NetworkAddress address)
{
const char *hostname = address.GetHostname();
/* Do not query the 'any' address. */
if (StrEmpty(hostname) ||
strcmp(hostname, "0.0.0.0") == 0 ||
strcmp(hostname, "::") == 0) {
return nullptr;
}
NetworkGameList *item, *prev_item;
prev_item = nullptr;
@ -96,7 +86,6 @@ NetworkGameList *NetworkGameListAddItem(NetworkAddress address)
} else {
prev_item->next = item;
}
DEBUG(net, 4, "[gamelist] added server to list");
UpdateNetworkGameWindow();
@ -152,7 +141,7 @@ void NetworkGameListRequery()
/* item gets mostly zeroed by NetworkUDPQueryServer */
uint8 retries = item->retries;
NetworkUDPQueryServer(NetworkAddress(item->address));
NetworkUDPQueryServer(item->address);
item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries;
}
}

@ -489,9 +489,8 @@ public:
EM_ASM(if (window["openttd_server_list"]) openttd_server_list());
#endif
this->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
this->last_joined = NetworkAddServer(_settings_client.network.last_joined);
this->server = this->last_joined;
if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address);
this->requery_timer.SetInterval(MILLISECONDS_PER_TICK);
@ -662,9 +661,8 @@ public:
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_VERSION); // server version
y += FONT_HEIGHT_NORMAL;
char network_addr_buffer[NETWORK_HOSTNAME_LENGTH + 6 + 7];
sel->address.GetAddressAsString(network_addr_buffer, lastof(network_addr_buffer));
SetDParamStr(0, network_addr_buffer);
std::string address = sel->address.GetAddressAsString();
SetDParamStr(0, address.c_str());
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_ADDRESS); // server address
y += FONT_HEIGHT_NORMAL;
@ -753,7 +751,7 @@ public:
ShowQueryString(
STR_JUST_RAW_STRING,
STR_NETWORK_SERVER_LIST_ENTER_IP,
NETWORK_HOSTNAME_LENGTH, // maximum number of characters including '\0'
NETWORK_HOSTNAME_PORT_LENGTH, // maximum number of characters including '\0'
this, CS_ALPHANUMERAL, QSF_ACCEPT_UNCHANGED);
break;
@ -763,14 +761,12 @@ public:
case WID_NG_JOIN: // Join Game
if (this->server != nullptr) {
seprintf(_settings_client.network.last_host, lastof(_settings_client.network.last_host), "%s", this->server->address.GetHostname());
_settings_client.network.last_port = this->server->address.GetPort();
ShowNetworkLobbyWindow(this->server);
}
break;
case WID_NG_REFRESH: // Refresh
if (this->server != nullptr) NetworkUDPQueryServer(this->server->address);
if (this->server != nullptr) NetworkTCPQueryServer(this->server->address);
break;
case WID_NG_NEWGRF: // NewGRF Settings
@ -845,7 +841,10 @@ public:
void OnQueryTextFinished(char *str) override
{
if (!StrEmpty(str)) NetworkAddServer(str);
if (!StrEmpty(str)) {
strecpy(_settings_client.network.connect_to_ip, str, lastof(_settings_client.network.connect_to_ip));
NetworkAddServer(str);
}
}
void OnResize() override
@ -988,7 +987,7 @@ void ShowNetworkGameWindow()
first = false;
/* Add all servers from the config file to our list. */
for (const auto &iter : _network_host_list) {
NetworkAddServer(iter.c_str());
NetworkAddServer(iter);
}
}
@ -1487,22 +1486,22 @@ struct NetworkLobbyWindow : public Window {
case WID_NL_JOIN: // Join company
/* Button can be clicked only when it is enabled. */
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, this->company);
NetworkClientConnectGame(this->server->address, this->company);
break;
case WID_NL_NEW: // New company
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_NEW_COMPANY);
NetworkClientConnectGame(this->server->address, COMPANY_NEW_COMPANY);
break;
case WID_NL_SPECTATE: // Spectate game
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_SPECTATOR);
NetworkClientConnectGame(this->server->address, COMPANY_SPECTATOR);
break;
case WID_NL_REFRESH: // Refresh
/* Clear the information so removed companies don't remain */
for (auto &company : this->company_info) company = {};
NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
NetworkTCPQueryServer(this->server->address, true);
break;
}
}
@ -1570,7 +1569,9 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START);
DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
strecpy(_settings_client.network.last_joined, ngl->address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined));
NetworkTCPQueryServer(ngl->address, true);
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
}

@ -94,10 +94,10 @@ extern uint8 _network_reconnect;
extern CompanyMask _network_company_passworded;
void NetworkTCPQueryServer(NetworkAddress address);
void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info = false);
void GetBindAddresses(NetworkAddressList *addresses, uint16 port);
void NetworkAddServer(const char *b);
struct NetworkGameList *NetworkAddServer(const std::string &connection_string);
void NetworkRebuildHostList();
void UpdateNetworkGameWindow();
@ -119,11 +119,15 @@ void NetworkExecuteLocalCommandQueue();
void NetworkFreeLocalCommandQueue();
void NetworkSyncCommandQueue(NetworkClientSocket *cs);
void NetworkError(StringID error_string);
void ShowNetworkError(StringID error_string);
void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", NetworkTextMessageData data = NetworkTextMessageData());
uint NetworkCalculateLag(const NetworkClientSocket *cs);
StringID GetNetworkErrorMsg(NetworkErrorCode err);
bool NetworkFindName(char *new_name, const char *last);
const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed);
bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr);
NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port);
NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port);
#endif /* NETWORK_INTERNAL_H */

@ -111,7 +111,6 @@ static void DoNetworkUDPQueryServer(NetworkAddress &address, bool needs_mutex, b
/* Clear item in gamelist */
NetworkGameList *item = CallocT<NetworkGameList>(1);
address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name));
strecpy(item->info.hostname, address.GetHostname(), lastof(item->info.hostname));
item->address = address;
item->manually = manually;
NetworkGameListAddItemDelayed(item);
@ -453,10 +452,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE_Common(Packet *p, Ne
if (in_request_count > 0) flush_request();
}
if (item->info.hostname[0] == '\0') {
seprintf(item->info.hostname, lastof(item->info.hostname), "%s", client_addr->GetHostname());
}
if (client_addr->GetAddress()->ss_family == AF_INET6) {
strecat(item->info.server_name, " (IPv6)", lastof(item->info.server_name));
}

@ -31,62 +31,29 @@
bool _sprite_group_resolve_check_veh_check = false;
bool _sprite_group_resolve_check_veh_curvature_check = false;
struct WagonOverride {
EngineID *train_id;
uint trains;
CargoID cargo;
const SpriteGroup *group;
};
void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const SpriteGroup *group, EngineID *train_id, uint trains)
{
Engine *e = Engine::Get(engine);
WagonOverride *wo;
assert(cargo < NUM_CARGO + 2); // Include CT_DEFAULT and CT_PURCHASE pseudo cargoes.
e->overrides_count++;
e->overrides = ReallocT(e->overrides, e->overrides_count);
wo = &e->overrides[e->overrides_count - 1];
WagonOverride *wo = &e->overrides.emplace_back();
wo->group = group;
wo->cargo = cargo;
wo->trains = trains;
wo->train_id = MallocT<EngineID>(trains);
memcpy(wo->train_id, train_id, trains * sizeof *train_id);
wo->engines.assign(train_id, train_id + trains);
}
const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine)
{
const Engine *e = Engine::Get(engine);
for (uint i = 0; i < e->overrides_count; i++) {
const WagonOverride *wo = &e->overrides[i];
if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue;
for (uint j = 0; j < wo->trains; j++) {
if (wo->train_id[j] == overriding_engine) return wo->group;
}
for (const WagonOverride &wo : e->overrides) {
if (wo.cargo != cargo && wo.cargo != CT_DEFAULT) continue;
if (std::find(wo.engines.begin(), wo.engines.end(), overriding_engine) != wo.engines.end()) return wo.group;
}
return nullptr;
}
/**
* Unload all wagon override sprite groups.
*/
void UnloadWagonOverrides(Engine *e)
{
for (uint i = 0; i < e->overrides_count; i++) {
WagonOverride *wo = &e->overrides[i];
free(wo->train_id);
}
free(e->overrides);
e->overrides_count = 0;
e->overrides = nullptr;
}
void SetCustomEngineSprites(EngineID engine, byte cargo, const SpriteGroup *group)
{
Engine *e = Engine::Get(engine);
@ -1623,8 +1590,8 @@ void AnalyseEngineCallbacks()
for (uint i = 0; i < NUM_CARGO + 2; i++) {
process_sg(e->grf_prop.spritegroup[i]);
}
for (uint i = 0; i < e->overrides_count; i++) {
process_sg(e->overrides[i].group);
for (const WagonOverride &wo : e->overrides) {
process_sg(wo.group);
}
e->callbacks_used = callbacks_used;
e->cb36_properties_used = cb36_properties_used;

@ -116,8 +116,6 @@ enum VehicleTrigger {
};
void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger);
void UnloadWagonOverrides(Engine *e);
void AlterVehicleListOrder(EngineID engine, uint target);
void CommitVehicleListOrderChanges();

@ -623,29 +623,10 @@ struct AfterNewGRFScan : NewGRFScanCallback {
if (_switch_mode != SM_NONE) MakeNewgameSettingsLive();
if (_network_available && network_conn != nullptr) {
const char *port = nullptr;
const char *company = nullptr;
uint16 rport = NETWORK_DEFAULT_PORT;
CompanyID join_as = COMPANY_NEW_COMPANY;
ParseGameConnectionString(&company, &port, network_conn);
if (company != nullptr) {
join_as = (CompanyID)atoi(company);
if (join_as != COMPANY_SPECTATOR) {
join_as--;
if (join_as >= MAX_COMPANIES) {
delete this;
return;
}
}
}
if (port != nullptr) rport = atoi(port);
LoadIntroGame();
_switch_mode = SM_NONE;
NetworkClientConnectGame(network_conn, rport, join_as, join_server_password, join_company_password);
NetworkClientConnectGame(network_conn, COMPANY_NEW_COMPANY, join_server_password, join_company_password);
}
/* After the scan we're not used anymore. */
@ -740,7 +721,7 @@ int openttd_main(int argc, char *argv[])
SetDebugString("net=3");
if (mgo.opt != nullptr) {
const char *port = nullptr;
ParseConnectionString(&port, mgo.opt);
ParseFullConnectionString(nullptr, &port, mgo.opt);
if (!StrEmpty(mgo.opt)) scanner->dedicated_host = mgo.opt;
if (port != nullptr) scanner->dedicated_port = atoi(port);
}
@ -939,15 +920,7 @@ int openttd_main(int argc, char *argv[])
NetworkStartUp(); // initialize network-core
if (debuglog_conn != nullptr && _network_available) {
const char *port = nullptr;
uint16 rport;
rport = NETWORK_DEFAULT_DEBUGLOG_PORT;
ParseConnectionString(&port, debuglog_conn);
if (port != nullptr) rport = atoi(port);
NetworkStartDebugLog(debuglog_conn, rport);
NetworkStartDebugLog(debuglog_conn);
}
if (!HandleBootstrap()) {
@ -1298,6 +1271,11 @@ void SwitchToMode(SwitchMode new_mode)
break;
}
case SM_JOIN_GAME: // Join a multiplayer game
LoadIntroGame();
NetworkClientJoinGame();
break;
case SM_MENU: // Switch to game intro menu
LoadIntroGame();
if (BaseSounds::ini_set.empty() && BaseSounds::GetUsedSet()->fallback && SoundDriver::GetInstance()->HasOutput()) {
@ -1975,7 +1953,7 @@ void GameLoop()
if (_network_reconnect > 0 && --_network_reconnect == 0) {
/* This means that we want to reconnect to the last host
* We do this here, because it means that the network is really closed */
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_SPECTATOR);
NetworkClientConnectGame(_settings_client.network.last_joined, COMPANY_SPECTATOR);
}
/* Singleplayer */
StateGameLoop();

@ -36,6 +36,7 @@ enum SwitchMode {
SM_START_HEIGHTMAP, ///< Load a heightmap and start a new game from it.
SM_LOAD_HEIGHTMAP, ///< Load heightmap from scenario editor.
SM_RESTART_HEIGHTMAP, ///< Load a heightmap and start a new game from it with current settings.
SM_JOIN_GAME, ///< Join a network game.
};
/** Display Options */

@ -70,15 +70,15 @@
#endif
#if defined(NETWORK_CORE_OS_ABSTRACTION_H) && defined(_WIN32)
/* Use NetworkGetLastError() instead of errno, or do not (indirectly) include network/core/os_abstraction.h.
* Winsock does not set errno, but one should rather call WSAGetLastError. NetworkGetLastError abstracts that away. */
/* Use NetworkError::GetLast() instead of errno, or do not (indirectly) include network/core/os_abstraction.h.
* Winsock does not set errno, but one should rather call WSAGetLastError. NetworkError::GetLast abstracts that away. */
#ifdef errno
#undef errno
#endif
#define errno SAFEGUARD_DO_NOT_USE_THIS_METHOD
/* Use NetworkGetLastErrorString() instead of strerror, or do not (indirectly) include network/core/os_abstraction.h.
* Winsock errors are not handled by strerror, but one should rather call FormatMessage. NetworkGetLastErrorString abstracts that away. */
/* Use NetworkError::AsString() instead of strerror, or do not (indirectly) include network/core/os_abstraction.h.
* Winsock errors are not handled by strerror, but one should rather call FormatMessage. NetworkError::AsString abstracts that away. */
#define strerror SAFEGUARD_DO_NOT_USE_THIS_METHOD
#endif /* defined(NETWORK_CORE_OS_ABSTRACTION_H) && defined(_WIN32) */

@ -14,6 +14,8 @@
#include <time.h>
#include <time.h>
#include "../../safeguards.h"
/* static */ bool ScriptDate::IsValidDate(Date date)

@ -337,7 +337,7 @@ struct NetworkSettings {
bool server_advertise; ///< advertise the server to the masterserver
char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< name of the player (as client)
char default_company_pass[NETWORK_PASSWORD_LENGTH]; ///< default password for new companies in encrypted form
char connect_to_ip[NETWORK_HOSTNAME_LENGTH]; ///< default for the "Add server" query
char connect_to_ip[NETWORK_HOSTNAME_PORT_LENGTH]; ///< default for the "Add server" query
char network_id[NETWORK_SERVER_ID_LENGTH]; ///< network ID for servers
bool autoclean_companies; ///< automatically remove companies that are not in use
uint8 autoclean_unprotected; ///< remove passwordless companies after this many months
@ -349,8 +349,7 @@ struct NetworkSettings {
Year restart_game_year; ///< year the server restarts
uint8 min_active_clients; ///< minimum amount of active clients to unpause the game
bool reload_cfg; ///< reload the config file before restarting
char last_host[NETWORK_HOSTNAME_LENGTH]; ///< IP address of the last joined server
uint16 last_port; ///< port of the last joined server
char last_joined[NETWORK_HOSTNAME_PORT_LENGTH]; ///< Last joined server
bool no_http_content_downloads; ///< do not do content downloads over HTTP
};

@ -144,6 +144,12 @@
# endif
#endif /* __GNUC__ || __clang__ */
#if __GNUC__ > 11 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 1)
# define NOACCESS(args) __attribute__ ((access (none, args)))
#else
# define NOACCESS(args)
#endif
#if defined(__WATCOMC__)
# define NORETURN
# define CDECL

@ -30,30 +30,30 @@
#include "core/bitmath_func.hpp"
#include "string_type.h"
char *strecat(char *dst, const char *src, const char *last);
char *strecpy(char *dst, const char *src, const char *last, bool quiet_mode = false);
char *stredup(const char *src, const char *last = nullptr);
char *strecat(char *dst, const char *src, const char *last) NOACCESS(3);
char *strecpy(char *dst, const char *src, const char *last, bool quiet_mode = false) NOACCESS(3);
char *stredup(const char *src, const char *last = nullptr) NOACCESS(2);
int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4);
int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) WARN_FORMAT(3, 0);
int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4) NOACCESS(2);
int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) WARN_FORMAT(3, 0) NOACCESS(2);
char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2);
char *str_vfmt(const char *str, va_list ap) WARN_FORMAT(1, 0);
std::string CDECL stdstr_fmt(const char *str, ...) WARN_FORMAT(1, 2);
std::string stdstr_vfmt(const char *str, va_list va) WARN_FORMAT(1, 0);
char *str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
char *str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2);
std::string str_validate(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
void ValidateString(const char *str);
const char *str_fix_scc_encoded(char *str, const char *last);
const char *str_fix_scc_encoded(char *str, const char *last) NOACCESS(2);
void str_strip_colours(char *str);
std::string str_strip_all_scc(const char *str);
char *str_replace_wchar(char *str, const char *last, WChar find, WChar replace);
bool strtolower(char *str);
bool strtolower(std::string &str, std::string::size_type offs = 0);
bool StrValid(const char *str, const char *last);
bool StrValid(const char *str, const char *last) NOACCESS(2);
void StrTrimInPlace(char *str);
/**

@ -6340,21 +6340,12 @@ def = false
cat = SC_EXPERT
[SDTC_STR]
var = network.last_host
var = network.last_joined
type = SLE_STRB
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
def = """"
cat = SC_EXPERT
[SDTC_VAR]
var = network.last_port
type = SLE_UINT16
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
def = 0
min = 0
max = UINT16_MAX
cat = SC_EXPERT
[SDTC_BOOL]
var = network.no_http_content_downloads
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC

Loading…
Cancel
Save