--- a/Makefile Tue Jan 02 18:40:37 2007 +0000
+++ b/Makefile Wed Jan 03 08:32:17 2007 +0000
@@ -733,13 +733,16 @@
SRCS += music.c
SRCS += music_gui.c
SRCS += namegen.c
-SRCS += network.c
-SRCS += network_client.c
-SRCS += network_data.c
-SRCS += network_gamelist.c
-SRCS += network_gui.c
-SRCS += network_server.c
-SRCS += network_udp.c
+SRCS += network/core/packet.c
+SRCS += network/core/tcp.c
+SRCS += network/core/udp.c
+SRCS += network/network.c
+SRCS += network/network_client.c
+SRCS += network/network_data.c
+SRCS += network/network_gamelist.c
+SRCS += network/network_gui.c
+SRCS += network/network_server.c
+SRCS += network/network_udp.c
SRCS += newgrf.c
SRCS += newgrf_cargo.c
SRCS += newgrf_config.c
--- a/ai/ai.c Tue Jan 02 18:40:37 2007 +0000
+++ b/ai/ai.c Wed Jan 03 08:32:17 2007 +0000
@@ -4,7 +4,7 @@
#include "../openttd.h"
#include "../variables.h"
#include "../command.h"
-#include "../network.h"
+#include "../network/network.h"
#include "ai.h"
#include "default/default.h"
--- a/ai/ai.h Tue Jan 02 18:40:37 2007 +0000
+++ b/ai/ai.h Wed Jan 03 08:32:17 2007 +0000
@@ -2,7 +2,7 @@
#define AI_H
#include "../functions.h"
-#include "../network.h"
+#include "../network/network.h"
#include "../player.h"
#include "../command.h"
--- a/command.c Tue Jan 02 18:40:37 2007 +0000
+++ b/command.c Wed Jan 03 08:32:17 2007 +0000
@@ -8,7 +8,7 @@
#include "gui.h"
#include "command.h"
#include "player.h"
-#include "network.h"
+#include "network/network.h"
#include "variables.h"
#include "genworld.h"
--- a/console.c Tue Jan 02 18:40:37 2007 +0000
+++ b/console.c Wed Jan 03 08:32:17 2007 +0000
@@ -13,9 +13,9 @@
#include <stdarg.h>
#include <string.h>
#include "console.h"
-#include "network.h"
-#include "network_data.h"
-#include "network_server.h"
+#include "network/network.h"
+#include "network/network_data.h"
+#include "network/network_server.h"
#define ICON_BUFFER 79
#define ICON_HISTORY_SIZE 20
--- a/console_cmds.c Tue Jan 02 18:40:37 2007 +0000
+++ b/console_cmds.c Wed Jan 03 08:32:17 2007 +0000
@@ -9,10 +9,10 @@
#include "saveload.h"
#include "string.h"
#include "variables.h"
-#include "network_data.h"
-#include "network_client.h"
-#include "network_server.h"
-#include "network_udp.h"
+#include "network/network_data.h"
+#include "network/network_client.h"
+#include "network/network_server.h"
+#include "network/network_udp.h"
#include "command.h"
#include "settings.h"
#include "fios.h"
@@ -22,7 +22,7 @@
#include "screenshot.h"
#include "genworld.h"
#include "date.h"
-#include "network.h"
+#include "network/network.h"
// ** scriptfile handling ** //
static FILE *_script_file;
--- a/date.c Tue Jan 02 18:40:37 2007 +0000
+++ b/date.c Wed Jan 03 08:32:17 2007 +0000
@@ -6,9 +6,9 @@
#include "variables.h"
#include "macros.h"
#include "vehicle.h"
-#include "network.h"
-#include "network_data.h"
-#include "network_server.h"
+#include "network/network.h"
+#include "network/network_data.h"
+#include "network/network_server.h"
#include "functions.h"
#include "currency.h"
@@ -92,9 +92,22 @@
int rem = date % (365 * 400 + 97);
uint16 x;
- /* There are 24 leap years in 100 years */
- yr += 100 * (rem / (365 * 100 + 24));
- rem = rem % (365 * 100 + 24);
+ if (rem >= 365 * 100 + 25) {
+ /* There are 25 leap years in the first 100 years after
+ * every 400th year, as every 400th year is a leap year */
+ yr += 100;
+ rem -= 365 * 100 + 25;
+
+ /* There are 24 leap years in the next couple of 100 years */
+ yr += 100 * (rem / (365 * 100 + 24));
+ rem = (rem % (365 * 100 + 24));
+ }
+
+ if (!IsLeapYear(yr) && rem >= 365 * 4) {
+ /* The first 4 year of the century are not always a leap year */
+ yr += 4;
+ rem -= 365 * 4;
+ }
/* There is 1 leap year every 4 years */
yr += 4 * (rem / (365 * 4 + 1));
--- a/date.h Tue Jan 02 18:40:37 2007 +0000
+++ b/date.h Wed Jan 03 08:32:17 2007 +0000
@@ -3,6 +3,8 @@
#ifndef DATE_H
#define DATE_H
+#include "openttd.h"
+
/**
* 1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885. On
* an overflow the new day begun and 65535 / 885 = 74.
--- a/depot_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/depot_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -779,11 +779,11 @@
STR_A002_AIRCRAFT_HANGAR
};
TileIndex tile = w->window_number;
- byte vehtype = WP(w, depot_d).type - VEH_Train;
+ byte vehtype = WP(w, depot_d).type;
SetDParam(0, (vehtype == VEH_Aircraft) ? GetStationIndex(tile) : GetDepotByTile(tile)->town_index);
ShowQuery(
- confirm_captions[vehtype],
+ confirm_captions[vehtype - VEH_Train],
STR_DEPOT_SELL_CONFIRMATION_TEXT,
w,
DepotSellAllConfirmationCallback
--- a/economy.c Tue Jan 02 18:40:37 2007 +0000
+++ b/economy.c Wed Jan 03 08:32:17 2007 +0000
@@ -19,10 +19,10 @@
#include "economy.h"
#include "industry.h"
#include "town.h"
-#include "network.h"
+#include "network/network.h"
#include "sound.h"
#include "engine.h"
-#include "network_data.h"
+#include "network/network_data.h"
#include "variables.h"
#include "vehicle_gui.h"
#include "ai/ai.h"
--- a/genworld.c Tue Jan 02 18:40:37 2007 +0000
+++ b/genworld.c Wed Jan 03 08:32:17 2007 +0000
@@ -11,7 +11,7 @@
#include "gfx.h"
#include "gfxinit.h"
#include "gui.h"
-#include "network.h"
+#include "network/network.h"
#include "debug.h"
#include "settings.h"
#include "heightmap.h"
--- a/genworld_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/genworld_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -19,7 +19,7 @@
#include "settings.h"
#include "debug.h"
#include "genworld.h"
-#include "network.h"
+#include "network/network.h"
#include "thread.h"
#include "date.h"
#include "newgrf_config.h"
@@ -43,7 +43,6 @@
GLWP_END
} glwp_modes;
-static char _edit_str_buf[LEN_RND_SEED];
static uint _heightmap_x = 0;
static uint _heightmap_y = 0;
static StringID _heightmap_str = STR_NULL;
@@ -193,11 +192,22 @@
static const StringID num_towns[] = {STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
static const StringID num_inds[] = {STR_26816_NONE, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
+ /* Data used for the generate seed edit box */
+ static querystr_d _genseed_query;
+ static char _genseed_buffer[LEN_RND_SEED];
+
uint mode = w->window_number;
uint y;
switch (e->event) {
- case WE_CREATE: LowerWindowWidget(w, _opt_newgame.landscape + 3); break;
+ case WE_CREATE:
+ LowerWindowWidget(w, _opt_newgame.landscape + 3);
+
+ snprintf(_genseed_buffer, sizeof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
+ InitializeTextBuffer(&_genseed_query.text, _genseed_buffer, lengthof(_genseed_buffer), 120);
+ _genseed_query.caption = STR_NULL;
+ _genseed_query.afilter = CS_NUMERAL;
+ break;
case WE_PAINT:
/* You can't select smoothness if not terragenesis */
@@ -244,7 +254,7 @@
}
DrawString( 12, 153 + y, STR_RANDOM_SEED, 0);
- DrawEditBox(w, &WP(w, querystr_d), SEED_EDIT);
+ DrawEditBox(w, &_genseed_query, SEED_EDIT);
DrawString(182, 113 + y, STR_DATE, 0);
SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
@@ -315,8 +325,8 @@
break;
case 16: // Random seed
_patches_newgame.generation_seed = InteractiveRandom();
- snprintf(_edit_str_buf, lengthof(_edit_str_buf), "%u", _patches_newgame.generation_seed);
- UpdateTextBufferSize(&WP(w, querystr_d).text);
+ snprintf(_genseed_buffer, lengthof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
+ UpdateTextBufferSize(&_genseed_query.text);
SetWindowDirty(w);
break;
case 17: // Generate
@@ -385,17 +395,17 @@
break;
case WE_MOUSELOOP:
- HandleEditBox(w, &WP(w, querystr_d), SEED_EDIT);
+ HandleEditBox(w, &_genseed_query, SEED_EDIT);
break;
case WE_KEYPRESS:
- HandleEditBoxKey(w, &WP(w, querystr_d), SEED_EDIT, e);
+ HandleEditBoxKey(w, &_genseed_query, SEED_EDIT, e);
/* the seed is unsigned, therefore atoi cannot be used.
* As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value
* (use random seed) it should not be possible to be
* entered into the input field; the generate seed
* button can be used instead. */
- _patches_newgame.generation_seed = minu(strtoul(_edit_str_buf, NULL, 10), MAX_UVALUE(uint32) - 1);
+ _patches_newgame.generation_seed = minu(strtoul(_genseed_buffer, NULL, sizeof(_genseed_buffer) - 1), MAX_UVALUE(uint32) - 1);
break;
case WE_DROPDOWN_SELECT:
@@ -503,13 +513,6 @@
w = AllocateWindowDescFront((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
if (w != NULL) {
- querystr_d *querystr = &WP(w, querystr_d);
-
- snprintf(_edit_str_buf, lengthof(_edit_str_buf), "%u", _patches_newgame.generation_seed);
-
- InitializeTextBuffer(&querystr->text, _edit_str_buf, lengthof(_edit_str_buf), 120);
- querystr->caption = STR_NULL;
- querystr->afilter = CS_NUMERAL;
InvalidateWindow(WC_GENERATE_LANDSCAPE, mode);
}
--- a/intro_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/intro_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -9,12 +9,12 @@
#include "gui.h"
#include "gfx.h"
#include "player.h"
-#include "network.h"
+#include "network/network.h"
#include "variables.h"
#include "settings.h"
#include "heightmap.h"
#include "genworld.h"
-#include "network_gui.h"
+#include "network/network_gui.h"
#include "newgrf.h"
static const Widget _select_game_widgets[] = {
--- a/lang/danish.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/danish.txt Wed Jan 03 08:32:17 2007 +0000
@@ -154,6 +154,7 @@
STR_00B1_GAME_OPTIONS :{WHITE}Spilindstillinger
STR_00B2_MESSAGE :{YELLOW}Besked
STR_00B3_MESSAGE_FROM :{YELLOW}Besked fra {STRING}
+STR_POPUP_CAUTION_CAPTION :{WHITE}Advarsel!
STR_00B4_CAN_T_DO_THIS :{WHITE}Det kan du ikke....
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Kan ikke rydde området....
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Original copyright {COPYRIGHT} 1995 Chris Sawyer, Alle rettigheder reserveret
@@ -235,7 +236,7 @@
STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Gummiplantage
STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Vandværk
STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vandtårn
-STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Tømmerfabrik
+STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Træfabrik
STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Candyfloss-skov
STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Slikfabrik
STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Batterigård
@@ -353,7 +354,7 @@
STR_PERFORMANCE_DETAIL_MENU :Præstations oversigt
############ range for menu ends
-STR_015B_OPENTTD :{WHITE}OpenTTD
+STR_015B_OPENTTD :{WHITE}Om OpenTTD
STR_015C_SAVE_GAME :Gem Spil
STR_015D_LOAD_GAME :Hent Spil
STR_015E_QUIT_GAME :Afslut Spil
@@ -396,7 +397,7 @@
STR_AVAILABLE_ENGINES_TIP :{BLACK}Se liste over tilgængelige designs for denne køretøjstype.
STR_MANAGE_LIST :{BLACK}Administrer liste
STR_MANAGE_LIST_TIP :{BLACK}Send instruktioner til alle køretøjer in denne liste
-STR_REPLACE_VEHICLES :Udskift Køretøjer
+STR_REPLACE_VEHICLES :Udskift køretøjer
STR_SEND_TRAIN_TO_DEPOT :Send til remise
STR_SEND_ROAD_VEHICLE_TO_DEPOT :Send til værksted
STR_SEND_SHIP_TO_DEPOT :Send til dok
@@ -463,8 +464,8 @@
STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Vis transportruter på kortet
STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Vis vegetation på kortet
STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Vis landejere på kortet
-STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Tænd/sluk bynavne
-STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Dette års overskud: {CURRENCY} (sidste år: {CURRENCY})
+STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Vis/skjul bynavne på kort
+STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Overskud i år: {CURRENCY} (sidste år: {CURRENCY})
############ range for service numbers starts
STR_AGE :{COMMA} år ({COMMA})
@@ -567,8 +568,8 @@
STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select 'Custom 2' (brugerdefineret) programmet
STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Ryd det valgte program (Gælder kun Custom1/Custom2)
STR_01F9_SAVE_MUSIC_SETTINGS :{BLACK}Gem opsætning for musik
-STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klik på et musiknummer for at tilføje det til programlisten (Kun for Custom1/Custom2)
-STR_CLICK_ON_TRACK_TO_REMOVE :{BLACK}Klik på et musiknummer for at fjerne det fra programlisten (kun Custom1 eller Custom2)
+STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klik på et musiknummer for at tilføje det til programlisten (kun for Custom1/Custom2)
+STR_CLICK_ON_TRACK_TO_REMOVE :{BLACK}Klik på et musiknummer for at fjerne det fra programlisten (kun for Custom1/Custom2)
STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Tilfældig afspilning til/fra
STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Vis vinduet med musiknummervalg
STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klik på servicen for at centrere skærmen over industrien/byen
@@ -590,7 +591,7 @@
STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Ændring i accepteret last
STR_020E_SUBSIDIES :{YELLOW}Statsstøttede aftaler
STR_020F_GENERAL_INFORMATION :{YELLOW}Generel information
-STR_MESSAGES_ALL :{YELLOW}Opsætning for all beskeder (on/off/refereret)
+STR_MESSAGES_ALL :{YELLOW}Sæt alle beskedtyper til: Fra / Kortfattet / Fuld
STR_MESSAGE_SOUND :{YELLOW}Afspil lyd for refererede nyheder
STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...for langt fra forrige destination
STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Bedste virksomheder, som har nået {NUM}{}({STRING} Niveau)
@@ -694,7 +695,7 @@
STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Byg Trykkeri
STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Byg Guldmine
STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Byg Bank (Kan kun bygges i en by)
-STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Byg Tømmerfabrik (for at rydde regnskoven og producere træ)
+STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Byg Træfabrik (for at rydde regnskoven og producere træ)
STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Plant Frugtplantage
STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Plant Gummiplantage
STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Byg Vandværk
@@ -769,7 +770,7 @@
STR_02C3_GAME_OPTIONS :Spilindstillinger
STR_02C5_DIFFICULTY_SETTINGS :Sværhedsgrad
STR_02C7_CONFIG_PATCHES :Konfigurér patches
-STR_NEWGRF_SETTINGS :Newgrf indstillinger
+STR_NEWGRF_SETTINGS :NewGRF indstillinger
STR_GAMEOPTMENU_0A :
STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Bynavne vist
STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Stationsnavne vist
@@ -785,8 +786,8 @@
STR_02D5_LAND_BLOCK_INFO :Landområde information
STR_02D6 :
STR_CONSOLE_SETTING :Tænd/Sluk konsol
-STR_02D7_SCREENSHOT_CTRL_S :Screenshot (Ctrl-S)
-STR_02D8_GIANT_SCREENSHOT_CTRL_G :Kæmpe Screenshot (Ctrl-G)
+STR_02D7_SCREENSHOT_CTRL_S :Skærmbillede (Ctrl-S)
+STR_02D8_GIANT_SCREENSHOT_CTRL_G :Kæmpe skærmbillede (Ctrl-G)
STR_02D9_ABOUT_OPENTTD :Om 'OpenTTD'
############ range ends here
@@ -857,8 +858,8 @@
STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...kan kun bygges i ørkenområder
STR_0319_PAUSED :{YELLOW}* * PAUSE * *
-STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot gemt '{STRING}'
-STR_031C_SCREENSHOT_FAILED :{WHITE}Fejl under tagning af screenshot!
+STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Skærmbilledet blev gemt som '{STRING}'
+STR_031C_SCREENSHOT_FAILED :{WHITE}Fejl under tagning af skærmbillede!
STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Køb land til senere brug
STR_032F_AUTOSAVE :{RED}AUTOSAVE
@@ -934,9 +935,9 @@
STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
STR_OPTIONS_RES_TIP :{BLACK}Vælg skørmopløsning
-STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Screenshot format
+STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Skærmbillede format
STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
-STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Vælg det format til screenshots
+STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Vælg skærmbillede format
STR_AUTOSAVE_1_MONTH :Hver måned
STR_AUTOSAVE_FAILED :{WHITE}Fejl under autogem
@@ -976,7 +977,7 @@
STR_TRAIN_IS_LOST :{WHITE}Tog {COMMA} er faret vild.
STR_TRAIN_IS_UNPROFITABLE :{WHITE}Tog {COMMA}'s profit sidste år var {CURRENCY}
-STR_EURO_INTRODUCE :{BLACK}{BIGFONT}Europæisk fællesvaluta!{}{}Euroen er introduceret som eneste betalingsmiddel it dit land!
+STR_EURO_INTRODUCE :{BLACK}{BIGFONT}Europæisk fællesvaluta!{}{}Euroen er introduceret som eneste betalingsmiddel i dit land!
# Start of order review system.
# DON'T ADD OR REMOVE LINES HERE
@@ -995,7 +996,7 @@
STR_AIRCRAFT_HAS_TOO_FEW_ORDERS :{WHITE}Fly {COMMA} har for få ordre i sin flyveplan
STR_AIRCRAFT_HAS_VOID_ORDER :{WHITE}Fly {COMMA} har en ugyldig ordre
STR_AIRCRAFT_HAS_DUPLICATE_ENTRY :{WHITE}Fly {COMMA} har dobbelt ordre
-STR_AIRCRAFT_HAS_INVALID_ENTRY :{WHITE}Fly {COMMA} har en ugyldig station i sin flyveplan
+STR_AIRCRAFT_HAS_INVALID_ENTRY :{WHITE}Fly {COMMA} har en ugyldig lufthavn i sin flyveplan
# end of order system
STR_TRAIN_AUTORENEW_FAILED :{WHITE}Automatisk fornyelse af tog mislykkedes {COMMA} (ikke penge nok)
@@ -1074,7 +1075,7 @@
STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE :Med uret
STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT :{LTBLUE}Den højde et flat scenariekort får: {ORANGE}{STRING}
-STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Max station udbreddelse: {ORANGE}{STRING} {RED}Advarsel: Høj værdi gør spillet langsomt
+STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maks. station udbreddelse: {ORANGE}{STRING} {RED}Advarsel: Høj værdi gør spillet langsomt
STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Automatisk service på helikopterlandingspladser: {ORANGE}{STRING}
STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR :{LTBLUE}Link landskabs værktøjsbaren til skinne/vej/vand/lufthavn værktøjsbaren: {ORANGE}{STRING}
STR_CONFIG_PATCHES_REVERSE_SCROLLING :{LTBLUE}Når der scrolles med musen, flyt viewet i den modsatte retning: {ORANGE}{STRING}
@@ -1185,7 +1186,7 @@
STR_NO_TOWN_IN_SCENARIO :{WHITE}...der er ingen byer i dette scenarie
-STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}Er du sikker på, at ud vil have lavet et tilfældigt landskab?
+STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}Er du sikker på, at du vil lave et tilfældigt landskab?
STR_MANY_RANDOM_TOWNS :{BLACK}Mange tilfældige byer
STR_RANDOM_TOWNS_TIP :{BLACK}Dæk kortet med tilfældigt placerede byer
STR_MANY_RANDOM_INDUSTRIES :{BLACK}Mange tilfældige industrier
@@ -1264,7 +1265,7 @@
STR_CONFIG_PATCHES_SERVINT_ISPERCENT :{LTBLUE}Service intervaller er i procent: {ORANGE}{STRING}
STR_CONFIG_GAME_PRODUCTION :{WHITE}Skift produktion
-TEMP_AI_IN_PROGRESS :{WHITE}Velkommen til den nye kunstige intelligents, der er under udarbejdelse. Du kan forvente problemer. Når det sker, så lav et screenshot og sæt det på forummet.
+TEMP_AI_IN_PROGRESS :{WHITE}Velkommen til den nye kunstige intelligents, der er under udarbejdelse. Du kan forvente problemer. Når det sker, så lav et skærmbillede og sæt det på forummet.
TEMP_AI_ACTIVATED :{WHITE}Advarsel: den nye kunstige intelligents er i et tidligt stadie! Lige nu virker den kun med busser og lastbiler!
TEMP_AI_MULTIPLAYER :{WHITE}Advarsel: denne funktion er stadig eksperimentel. Rapporter venligst problemer til truelight@openttd.org.
@@ -1308,6 +1309,7 @@
STR_NETWORK_SERVER_OFFLINE :{SILVER}SERVEREN ER OFFLINE
STR_NETWORK_SERVER_FULL :{SILVER}SERVEREN ER FULD
STR_NETWORK_VERSION_MISMATCH :{SILVER}Din og serverens version passer ikke sammen
+STR_NETWORK_GRF_MISMATCH :{SILVER}NEWGRF MATCHER IKKE
STR_NETWORK_JOIN_GAME :{BLACK}Tilslut dig et spil
@@ -1339,10 +1341,10 @@
STR_NETWORK_8_PLAYERS :8 spillere
STR_NETWORK_9_PLAYERS :9 spillere
STR_NETWORK_10_PLAYERS :10 spillere
-STR_NETWORK_NUMBER_OF_COMPANIES :{BLACK}Max firmaer:
+STR_NETWORK_NUMBER_OF_COMPANIES :{BLACK}Maks. firmaer:
STR_NETWORK_NUMBER_OF_COMPANIES_TIP :{BLACK}Begræns serveren to et bestemt antal firmaer
STR_NETWORK_COMBO3 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
-STR_NETWORK_NUMBER_OF_SPECTATORS :{BLACK}Max tilskuere:
+STR_NETWORK_NUMBER_OF_SPECTATORS :{BLACK}Maks. tilskuere:
STR_NETWORK_NUMBER_OF_SPECTATORS_TIP :{BLACK}Begræns serveren til et bestemt antal tilskurere
STR_NETWORK_COMBO4 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
STR_NETWORK_LANGUAGE_SPOKEN :{BLACK}Talt sprog:
@@ -1613,7 +1615,7 @@
STR_201D_OFFICE_BLOCK :Kontorbygning
STR_201E_STADIUM :Stadion
STR_201F_OLD_HOUSES :Gamle huse
-STR_2020_LOCAL_AUTHORITY :{BLACK}Lokale myndigheder
+STR_2020_LOCAL_AUTHORITY :{BLACK}Myndigheder
STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Vis information om de lokale myndigheder
STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} lokal myndighed
STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Transportselskabsbedømmelse:
@@ -1840,7 +1842,7 @@
STR_4818_WATER_TOWER :Vandtårn
STR_4819_FACTORY :Fabrik
STR_481A_FARM :Bondegård
-STR_481B_LUMBER_MILL :Tømmerfabrik
+STR_481B_LUMBER_MILL :Træfabrik
STR_481C_COTTON_CANDY_FOREST :Candyfloss Skov
STR_481D_CANDY_FACTORY :Slikfabrik
STR_481E_BATTERY_FARM :Batterigård
@@ -2067,7 +2069,7 @@
STR_700F_EXPENDITURE_INCOME :{WHITE}Udgifter/Indkomst
STR_7010 :{WHITE}{NUM}
STR_7011_CONSTRUCTION :{GOLD}Konstruktion
-STR_7012_NEW_VEHICLES :{GOLD}Nye Køretøjer
+STR_7012_NEW_VEHICLES :{GOLD}Nye køretøjer
STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Togdriftsomkostning
STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Køretøjsdriftsomkostning
STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Flydriftsomkostning
@@ -2087,9 +2089,9 @@
STR_CURRCOMPACT :{CURRCOMPACT64}
STR_7024 :{COMMA}
STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Profit Garf
-STR_7026_BANK_BALANCE :{WHITE}Bank Balance
+STR_7026_BANK_BALANCE :{WHITE}Bank balance
STR_7027_LOAN :{WHITE}Lån
-STR_MAX_LOAN :{WHITE}Max Lån: {BLACK}{CURRENCY64}
+STR_MAX_LOAN :{WHITE}Maks. Lån: {BLACK}{CURRENCY64}
STR_7028 :{BLACK}{CURRENCY64}
STR_7029_BORROW :{BLACK}Lån {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
STR_702A_REPAY :{BLACK}Tilbagebetal {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
@@ -2503,8 +2505,8 @@
STR_HEADING_FOR_TRAIN_DEPOT :{ORANGE}Kører til {TOWN} Remise
STR_HEADING_FOR_TRAIN_DEPOT_VEL :{ORANGE}Kører til {TOWN} Remise, {VELOCITY}
-STR_HEADING_FOR_TRAIN_DEPOT_SERVICE :{LTBLUE}Eftersyn på {TOWN} Remise
-STR_HEADING_FOR_TRAIN_DEPOT_SERVICE_VEL :{LTBLUE}Eftersyn i {TOWN} Remise, {VELOCITY}
+STR_HEADING_FOR_TRAIN_DEPOT_SERVICE :{LTBLUE}Eftersyn i {TOWN} remise
+STR_HEADING_FOR_TRAIN_DEPOT_SERVICE_VEL :{LTBLUE}Eftersyn i {TOWN} remise, {VELOCITY}
STR_INVALID_ORDER :{RED} (Ugyldig Order)
@@ -2526,10 +2528,10 @@
STR_ALL_AVAIL_RAIL_VEHICLES :{WHITE}Jernbanekøretøjer
STR_881F_BUILD_VEHICLE :{BLACK}Byg Køretøj
-STR_CLONE_ROAD_VEHICLE :{BLACK}Klon Køretøj
+STR_CLONE_ROAD_VEHICLE :{BLACK}Klon køretøj
STR_CLONE_ROAD_VEHICLE_INFO :{BLACK}Dette vil bygge en kopi af køretøjet. Control-click vil dele ordre
STR_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}Dette vil bygge en kopi af køretøjet. Klik på denne knap, så på et køretøj indeni eller udenfor værkstedet. Control-click vil dele ordre
-STR_CLONE_TRAIN :{BLACK}Klon Tog
+STR_CLONE_TRAIN :{BLACK}Klon tog
STR_CLONE_TRAIN_INFO :{BLACK}Dette vil bygge en kopi af toget inklusiv alle vogne. Control-click vil dele ordre
STR_CLONE_TRAIN_DEPOT_INFO :{BLACK}Dette vil bygge en kopi af toget inklusiv alle vogne. Klik på denne knap, så på et tog indeni eller udenfor remisen. Control-click vil dele ordre
STR_8820_RENAME :{BLACK}Omdøb
@@ -2601,7 +2603,8 @@
STR_VEHICLE_INFO_COST_WEIGHT_SPEED_POWER :{BLACK}Pris: {CURRENCY} Vægt: {WEIGHT_S}{}Hastighed: {VELOCITY} Styrke: {POWER}{}Driftsomkostninger: {CURRENCY}/år{}Kapacitet: {CARGO}
STR_885C_BROKEN_DOWN :{RED}Gået i stykker
STR_885D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år
-STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Vægt: {LTBLUE}{WEIGHT_S} {BLACK}Styrke: {LTBLUE}{POWER}{BLACK} Maks hastighed: {LTBLUE}{VELOCITY}
+STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Vægt: {LTBLUE}{WEIGHT_S} {BLACK}Styrke: {LTBLUE}{POWER}{BLACK} Maks. hastighed: {LTBLUE}{VELOCITY}
+STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Vægt: {LTBLUE}{WEIGHT_S} {BLACK}Kraft: {LTBLUE}{POWER}{BLACK} Maks. hastighed: {LTBLUE}{VELOCITY} {BLACK}Maks. trækkraft: {LTBLUE}{FORCE}
STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY})
STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed {LTBLUE}{COMMA}% {BLACK}nedbrud siden sidste service: {LTBLUE}{COMMA}
STR_8861_STOPPED :{RED}Stoppet
@@ -2635,7 +2638,7 @@
STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan ikke bygge køretøj...
STR_900C_DETAILS :{WHITE}{VEHICLE} (Detaljer)
STR_900D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år
-STR_900E_MAX_SPEED :{BLACK}Maks hastighed: {LTBLUE}{VELOCITY}
+STR_900E_MAX_SPEED :{BLACK}Maks. hastighed: {LTBLUE}{VELOCITY}
STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY})
STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed: {LTBLUE}{COMMA}% {BLACK}Nedbrud siden sidste service: {LTBLUE}{COMMA}
STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUM}{BLACK} Værdi: {LTBLUE}{CURRENCY}
@@ -2646,8 +2649,8 @@
STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Køretøj {COMMA} venter i værksted
STR_HEADING_FOR_ROAD_DEPOT :{ORANGE}Kører til {TOWN} Værksted
STR_HEADING_FOR_ROAD_DEPOT_VEL :{ORANGE}Kører til {TOWN} Værksted, {VELOCITY}
-STR_HEADING_FOR_ROAD_DEPOT_SERVICE :{LTBLUE}Eftersyn på {TOWN} Værksted
-STR_HEADING_FOR_ROAD_DEPOT_SERVICE_VEL :{LTBLUE}Eftersyn på {TOWN} Værksted, {VELOCITY}
+STR_HEADING_FOR_ROAD_DEPOT_SERVICE :{LTBLUE}Eftersyn på {TOWN} værksted
+STR_HEADING_FOR_ROAD_DEPOT_SERVICE_VEL :{LTBLUE}Eftersyn på {TOWN} værksted, {VELOCITY}
STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Kan ikke sende køretøj til værksted...
STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan ikke finde lokalt værksted
STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Køretøjer - klik på et køretøj for information
@@ -2699,7 +2702,7 @@
STR_9805_SHIPS :{WHITE}{COMPANY} - {COMMA} Skibe
STR_9808_NEW_SHIPS :{WHITE}Nye skibe
STR_9809_BUILD_SHIP :{BLACK}Byg skib
-STR_CLONE_SHIP :{BLACK}Klon Skib
+STR_CLONE_SHIP :{BLACK}Klon skib
STR_CLONE_SHIP_INFO :{BLACK}Dette vil bygge en kopi af skibet. Control-click vil dele ordre
STR_CLONE_SHIP_DEPOT_INFO :{BLACK}Dette vil bygge en kopi af skibet. Klik på denne knap så, på et skib indeni eller udenfor dokken. Control-click vil dele ordre
STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Skibet skal være stoppet i dok
@@ -2709,7 +2712,7 @@
STR_980F :{WHITE}{VEHICLE}
STR_9811_DETAILS :{WHITE}{VEHICLE} (Detaljer)
STR_9812_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år
-STR_9813_MAX_SPEED :{BLACK}Maks hastighed: {LTBLUE}{VELOCITY}
+STR_9813_MAX_SPEED :{BLACK}Maks. hastighed: {LTBLUE}{VELOCITY}
STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY})
STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed: {LTBLUE}{COMMA}% {BLACK}Nedbrud siden sidste service: {LTBLUE}{COMMA}
STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUM}{BLACK} Værdi: {LTBLUE}{CURRENCY}
@@ -2719,8 +2722,8 @@
STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan ikke finde lokal dok
STR_HEADING_FOR_SHIP_DEPOT :{ORANGE}Sejler til {TOWN} Dok
STR_HEADING_FOR_SHIP_DEPOT_VEL :{ORANGE}Sejler til {TOWN} Dok, {VELOCITY}
-STR_HEADING_FOR_SHIP_DEPOT_SERVICE :{LTBLUE}Eftersyn i {TOWN} Dok
-STR_HEADING_FOR_SHIP_DEPOT_SERVICE_VEL :{LTBLUE}Eftersyn i {TOWN} Dok, {VELOCITY}
+STR_HEADING_FOR_SHIP_DEPOT_SERVICE :{LTBLUE}Eftersyn i {TOWN} skibsdok
+STR_HEADING_FOR_SHIP_DEPOT_SERVICE_VEL :{LTBLUE}Eftersyn i {TOWN} skibsdok, {VELOCITY}
STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Skib {COMMA} venter i dok
STR_981D_BUILD_SHIP_DOCK :{BLACK}Byg havn
STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Byg skibsdok (til bygning og servicering af skibe)
@@ -2739,7 +2742,7 @@
STR_982B_SHOW_SHIP_DETAILS :{BLACK}Vis detaljer omkring skibet
STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nyt skib er tilgængeligt!
STR_982D :{BLACK}{BIGFONT}{STRING}
-STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Pris: {CURRENCY} Maks Hastighed: {VELOCITY}{}Kapacitet: {CARGO}{}Kørselsomkostning: {CURRENCY}/år
+STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Pris: {CURRENCY} Maks. hastighed: {VELOCITY}{}Kapacitet: {CARGO}{}Kørselsomkostning: {CURRENCY}/år
STR_982F_NAME_SHIP :{BLACK}Giv skibet et navn
STR_9831_NAME_SHIP :{WHITE}Giv skibet et navn
@@ -2779,15 +2782,15 @@
STR_A00B_ORDERS :{WHITE}{VEHICLE} (Ordre)
STR_A00C_DETAILS :{WHITE}{VEHICLE} (Detaljer)
STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år
-STR_A00E_MAX_SPEED :{BLACK}Maks hastighed: {LTBLUE}{VELOCITY}
+STR_A00E_MAX_SPEED :{BLACK}Maks. hastighed: {LTBLUE}{VELOCITY}
STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY})
STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed: {LTBLUE}{COMMA}% {BLACK}Nedbrud siden sidste service: {LTBLUE}{COMMA}
STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUM}{BLACK} Værdi: {LTBLUE}{CURRENCY}
STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Kan ikke sende flyet til en hangar...
STR_HEADING_FOR_HANGAR :{ORANGE}Flyver til {STATION} Hangar
STR_HEADING_FOR_HANGAR_VEL :{ORANGE}Flyver til {STATION} Hangar, {VELOCITY}
-STR_HEADING_FOR_HANGAR_SERVICE :{LTBLUE}Eftersyn i {STATION} Hangar
-STR_HEADING_FOR_HANGAR_SERVICE_VEL :{LTBLUE}Eftersyn i {STATION} Hangar, {VELOCITY}
+STR_HEADING_FOR_HANGAR_SERVICE :{LTBLUE}Eftersyn i {STATION} hangar
+STR_HEADING_FOR_HANGAR_SERVICE_VEL :{LTBLUE}Eftersyn i {STATION} hangar, {VELOCITY}
STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Fly {COMMA} venter i flyhangar
STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Fly i vejen
STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Kan ikke stoppe/starte fly...
@@ -2813,7 +2816,7 @@
STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Vis detaljet omkring flyet
STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nyt fly tilgængeligt!
STR_A02D :{BLACK}{BIGFONT}{STRING}
-STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Pris: {CURRENCY} Maks hastighed: {VELOCITY}{}Kapacitet: {COMMA} passagerer, {COMMA} sække post{}Kørselsomkostning: {CURRENCY}/år
+STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Pris: {CURRENCY} Maks. hastighed: {VELOCITY}{}Kapacitet: {COMMA} passagerer, {COMMA} sække post{}Kørselsomkostning: {CURRENCY}/år
STR_A030_NAME_AIRCRAFT :{WHITE}Navngiv flyet
STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Kan ikke navngive flyet...
@@ -2861,7 +2864,7 @@
STR_PERFORMANCE_DETAIL_STATIONS :{BLACK}Stationer:
STR_PERFORMANCE_DETAIL_MIN_PROFIT :{BLACK}Minimum profit:
STR_PERFORMANCE_DETAIL_MIN_INCOME :{BLACK}Minimum indkomst:
-STR_PERFORMANCE_DETAIL_MAX_INCOME :{BLACK}Max. indtægt:
+STR_PERFORMANCE_DETAIL_MAX_INCOME :{BLACK}Maks. indtægt:
STR_PERFORMANCE_DETAIL_DELIVERED :{BLACK}Afleveret:
STR_PERFORMANCE_DETAIL_CARGO :{BLACK}Last:
STR_PERFORMANCE_DETAIL_MONEY :{BLACK}Penge:
@@ -2880,17 +2883,38 @@
STR_PERFORMANCE_DETAIL_TOTAL_TIP :{BLACK}Samlet point af max point
STR_NEWGRF_SETTINGS_BUTTON :{BLACK}NewGRF indstillinger
-STR_NEWGRF_SETTINGS_CAPTION :{WHITE}Newgrf indstillinger
+STR_NEWGRF_SETTINGS_CAPTION :{WHITE}NewGRF indstillinger
STR_NEWGRF_APPLY_CHANGES :{BLACK}Anvend ændringer
-STR_NEWGRF_SET_PARAMETERS :{BLACK}Indstil parametre
+STR_NEWGRF_SET_PARAMETERS :{BLACK}Indstil parameter
STR_NEWGRF_TIP :{BLACK}Liste med alle Newgrf sæt du har installeret. Marker et sæt for at ændre indstilliger.
-STR_NEWGRF_NO_FILES_INSTALLED :{BLACK}Der er ingen newgrf filer installeret! Du kan læse i manualen hvordan man installerer newgrf sæt.
+STR_NEWGRF_NO_FILES_INSTALLED :{BLACK}Der er ingen newgrf filer installeret! Læs venligst om installation af nye grafiksæt i manualen
STR_NEWGRF_FILENAME :{BLACK}Filnavn: {SILVER}{STRING}
STR_NEWGRF_GRF_ID :{BLACK}GRF ID: {SILVER}{STRING}
STR_NEWGRF_MD5SUM :{BLACK}MD5sum: {SILVER}{STRING}
+STR_NEWGRF_CONFIRMATION_TEXT :{YELLOW}Du er ved at lave ændringer i et igangværende spil; dette kan få OpenTTD til at gå ned.{}Er du helt sikker på at du vil fortsætte?
+STR_NEWGRF_ADD :{BLACK}Tilføj
+STR_NEWGRF_ADD_TIP :{BLACK}Tilføj et NewGRF sæt til listen
+STR_NEWGRF_REMOVE :{BLACK}Fjern
+STR_NEWGRF_REMOVE_TIP :{BLACK}Fjern det valgte NewGRF sæt fra listen
+STR_NEWGRF_MOVEUP :{BLACK}Flyt op
+STR_NEWGRF_MOVEUP_TIP :{BLACK}Flyt det valgte NewGRF sæt op i listen
+STR_NEWGRF_MOVEDOWN :{BLACK}Flyt ned
+STR_NEWGRF_MOVEDOWN_TIP :{BLACK}Flyt det valgte NewGRF sæt ned i listen
+STR_NEWGRF_FILE_TIP :{BLACK}En liste over de NewGRF sæt der er installeret. Klik på et sæt for at ændre dets parameter
+STR_NEWGRF_PARAMETER :{BLACK}Parameter: {SILVER}{STRING}
+STR_NEWGRF_PARAMETER_QUERY :{BLACK}Indtast NewGRF-parameter
+STR_NEWGRF_NO_INFO :{BLACK}Ingen information tilgængelig
+STR_NEWGRF_ADD_CAPTION :{WHITE}Tilgængelige NewGRF sæt
+STR_NEWGRF_ADD_FILE :{BLACK}Tilføj til udvalg
+STR_NEWGRF_ADD_FILE_TIP :{BLACK}Tilføj det valgte NewGRF sæt til din konfiguration
+STR_NEWGRF_RESCAN_FILES :{BLACK}Genfind filer
+STR_NEWGRF_RESCAN_FILES_TIP :{BLACK}Opdater listen over tilgængelige NewGRF sæt
+STR_NEWGRF_DUPLICATE_GRFID :{WHITE}Kan ikke tilføje sæt: dobbelt GRF ID
+STR_NEWGRF_NOT_FOUND :{RED}Tilsvarende fil blev ikke fundet
+STR_NEWGRF_DISABLED :{RED}Deaktiveret
STR_CURRENCY_WINDOW :{WHITE}Brugerdefineret møntfod
STR_CURRENCY_EXCHANGE_RATE :{LTBLUE}Kurs: {ORANGE}{CURRENCY} = £ {COMMA}
@@ -2922,6 +2946,8 @@
STR_VEH_WITH_SHARED_ORDERS_LIST_TIP :{BLACK}Vis alle transportmidler, som har den samme rute
### depot strings
+STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}Du er ved at sælge alle køretøjer i depotet. Er du sikker?
+
STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TIP :{BLACK}Sælg alle toge i remisen
STR_DEPOT_SELL_ALL_BUTTON_ROADVEH_TIP :{BLACK}Sælg alle køretøjer i værkstedet
STR_DEPOT_SELL_ALL_BUTTON_SHIP_TIP :{BLACK}Sælg alle skibe i dokken
@@ -2997,8 +3023,8 @@
STR_PURCHASE_INFO_SPEED :{BLACK}Hastighed: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_RUNNINGCOST :{BLACK}Kørselsudgift: {GOLD}{CURRENCY}/år
STR_PURCHASE_INFO_CAPACITY :{BLACK}Lasteevne: {GOLD}{CARGO} {STRING}
-STR_PURCHASE_INFO_DESIGNED_LIFE :{BLACK}Designet: {GOLD}{NUM}{BLACK} Liv: {GOLD}{COMMA} år
-STR_PURCHASE_INFO_RELIABILITY :{BLACK}Max. Pålidelighed: {GOLD}{COMMA}%
+STR_PURCHASE_INFO_DESIGNED_LIFE :{BLACK}Designet: {GOLD}{NUM}{BLACK} Levealder: {GOLD}{COMMA} år
+STR_PURCHASE_INFO_RELIABILITY :{BLACK}Maks. pålidelighed: {GOLD}{COMMA}%
STR_PURCHASE_INFO_COST :{BLACK}Pris: {GOLD}{CURRENCY}
STR_PURCHASE_INFO_WEIGHT_CWEIGHT :{BLACK}Vægt: {GOLD}{WEIGHT_S} ({WEIGHT_S})
STR_PURCHASE_INFO_COST_SPEED :{BLACK}Pris: {GOLD}{CURRENCY}{BLACK} Hastighed: {GOLD}{VELOCITY}
@@ -3007,6 +3033,7 @@
STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Kan ombygges til: {GOLD}
STR_PURCHASE_INFO_ALL_TYPES :Alle lasttyper
STR_PURCHASE_INFO_ALL_BUT :Alle undtagen {GOLD}
+STR_PURCHASE_INFO_MAX_TE :{BLACK}Maks. trækkraft: {GOLD}{FORCE}
########### String for New Landscape Generator
@@ -3036,10 +3063,10 @@
STR_SNOW_LINE_HEIGHT_NUM :{NUM}
STR_HEIGHTMAP_NAME :{BLACK}Højdekortets navn:
STR_HEIGHTMAP_SIZE :{BLACK}Størrelse: {ORANGE}{NUM} x {NUM}
-STR_GENERATION_WORLD :{WHITE}Generere verden...
+STR_GENERATION_WORLD :{WHITE}Genererer verden...
STR_GENERATION_ABORT :{BLACK}Afbryd
-STR_GENERATION_ABORT_CAPTION :{WHITE}Afbryd Kort Genereringen
-STR_GENERATION_ABORT_MESSAGE :{YELLOW}Vil du virkelig afbryde kort genereringen?
+STR_GENERATION_ABORT_CAPTION :{WHITE}Afbryd Kortgenereringen
+STR_GENERATION_ABORT_MESSAGE :{YELLOW}Vil du virkelig afbryde kortgenereringen?
STR_PROGRESS :{WHITE}{NUM}% færdig
STR_GENERATION_PROGRESS :{BLACK}{NUM} / {NUM}
STR_WORLD_GENERATION :{BLACK}Verdensgenerering
@@ -3055,10 +3082,10 @@
STR_SE_RANDOM_LAND :{WHITE}Tilfældigt land
STR_SE_NEW_WORLD :{BLACK}Opret nyt scenarie
STR_SE_CAPTION :{WHITE}Scenarietype
-STR_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Flyt højden af flat land en ned
-STR_FLAT_WORLD_HEIGHT_UP :{BLACK}Flyt højden af flat land en up
-STR_FLAT_WORLD_HEIGHT_QUERY_CAPT :{WHITE}Ændre højden af flat land
-STR_FLAT_WORLD_HEIGHT :{BLACK}Højde af flat land:
+STR_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Flyt højden af fladt land en ned
+STR_FLAT_WORLD_HEIGHT_UP :{BLACK}Flyt højden af fladt land en op
+STR_FLAT_WORLD_HEIGHT_QUERY_CAPT :{WHITE}Ændre højden af fladt land
+STR_FLAT_WORLD_HEIGHT :{BLACK}Højde af fladt land:
STR_FLAT_WORLD_HEIGHT_NUM :{NUM}
STR_SMALLMAP_CENTER :{BLACK}Centrer det lille kort ved den nuværende position
--- a/lang/esperanto.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/esperanto.txt Wed Jan 03 08:32:17 2007 +0000
@@ -14,7 +14,7 @@
STR_EMPTY :
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Necesas ebena lando
STR_0008_WAITING :{BLACK}Atendas: {WHITE}{STRING}
-STR_0009 :{WHITE}{CARGO}
+STR_0009 :{WHITE} {CARGO}
STR_000A_EN_ROUTE_FROM :{WHITE}{CARGO}{YELLOW} (survoje de
STR_000B :{YELLOW}{STATION})
STR_000C_ACCEPTS :{BLACK}Akceptas: {WHITE}
@@ -1024,6 +1024,7 @@
STR_CONFIG_PATCHES_IMPROVEDLOAD :{LTBLUE}Uzu plibonigitan ŝarĝalgoritmon: {ORANGE}{STRING}
STR_CONFIG_PATCHES_GRADUAL_LOADING :{LTBLUE}Laŭgrade ŝarĝu veturilojn: {ORANGE}{STRING}
STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Inflacio: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Nur liveru ŝarĝon al stacio se estas peto: {ORANGE}{STRING}
STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Permesu konstruadon de tre longaj pontoj: {ORANGE}{STRING}
STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Permesu ordenojn por iri al deponejo: {ORANGE}{STRING}
STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Permesu konstruadon de fontmalerialaj industrioj: {ORANGE}{STRING}
@@ -1309,6 +1310,7 @@
STR_NETWORK_SERVER_OFFLINE :{SILVER}SERVILO NE SURRETAS
STR_NETWORK_SERVER_FULL :{SILVER}SERVILO PLENAS
STR_NETWORK_VERSION_MISMATCH :{SILVER}VERSIOJ NE KONGRUAS
+STR_NETWORK_GRF_MISMATCH :{SILVER}MISO PRI NEWGRF
STR_NETWORK_JOIN_GAME :{BLACK}Aliĝu al la ludo
@@ -1502,6 +1504,8 @@
STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Ne povas altigi landon ĉi tie...
STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Ne povas malaltigi landon ĉi tie...
STR_080A_ROCKS :Rokoj
+STR_080B_ROUGH_LAND :Malglata lando
+STR_080C_BARE_LAND :Nuda lando
STR_080D_GRASS :Herbo
STR_080E_FIELDS :Kampoj
STR_080F_SNOW_COVERED_LAND :Neĝkovrita lando
@@ -1579,6 +1583,10 @@
##id 0x2000
STR_2000_TOWNS :{WHITE}Urboj
+STR_TOWN_LABEL_POP :{WHITE}{TOWN} ({COMMA})
+STR_TOWN_LABEL :{WHITE}{TOWN}
+STR_TOWN_LABEL_TINY_BLACK :{TINYFONT}{BLACK}{TOWN}
+STR_TOWN_LABEL_TINY_WHITE :{TINYFONT}{WHITE}{TOWN}
STR_2002 :{TINYFONT}{BLACK}{STRING}
STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Antaŭe forigu konstruaĵon
STR_2005 :{WHITE}{TOWN}
@@ -1652,6 +1660,7 @@
STR_204A_BUILD_STATUE_OF_COMPANY :Konstruu statuon de la kompaniestro
STR_204B_FUND_NEW_BUILDINGS :Fondu novajn konstruaĵojn
STR_204C_BUY_EXCLUSIVE_TRANSPORT :Aĉetu ekskluzivan transportrajton
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Subaĉetu la lokajn estrojn
STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Komencu malgrandan lokan reklamadon, por altiri pli da pasaĝeroj kaj ŝarĝoj al viaj transportservoj.{} Kosto: {CURRENCY}
STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Komencu mezgrandan lokan reklamadon, por altiri pli da pasaĝeroj kaj ŝarĝoj al viaj transportservoj.{} Kosto: {CURRENCY}
STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Komencu grandan lokan reklamadon, por altiri pli da pasaĝeroj kaj ŝarĝoj al viaj transportservoj.{} Kosto: {CURRENCY}
@@ -1659,6 +1668,7 @@
STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Konstruu statuon honore al via kompanio.{} Kosto: {CURRENCY}
STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Fondu la konstruadon de novaj komercaj konstruaĵoj en la urbo.{} Kosto: {CURRENCY}
STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Aĉetu ekskluzivan transportrajton en la urbo por 1 jaro. La urbo nur permesos pasaĝerojn kaj ŝarĝojn uzi viajn staciojn {} Cost: {CURRENCY}
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Subaĉetu la lokajn estrojn por pliigi vian rendimenton, riskante grandan punon je kapto.{} Kosto: {CURRENCY}
STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING :{BIGFONT}{BLACK}Trafika ĥaoso en {TOWN}!{}{}Vojrekonstruada programo komencita de {COMPANY} alportas 6-monatan mizeron al vojuzantoj!
STR_2056 :{TINYFONT}{WHITE}{TOWN}
STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA})
@@ -1669,7 +1679,9 @@
STR_205C_PIGGY_BANK :Porko-Banko
STR_INDUSTRY :{INDUSTRY}
+STR_TOWN :{TOWN}
STR_INDUSTRY_FORMAT :{TOWN} {STRING}
+STR_STATION :{STATION}
##id 0x2800
STR_LANDSCAPING :Landaspektigi
@@ -1734,6 +1746,7 @@
STR_3043_TRUCK_STATION_ORIENT :{WHITE}Ŝarĝstacia Direkto
STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Antaŭe forigu bushaltejon
STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Antaŭe forigu ŝarĝstacion
+STR_3048_STATIONS :{WHITE}{COMPANY} - {COMMA} Stacio{P "" j}
STR_3049_0 :{YELLOW}{STATION} {STATIONFEATURES}
STR_304A_NONE :{YELLOW}- Neniu -
STR_304B_SITE_UNSUITABLE :{WHITE}...loko ne uzeblas
@@ -1751,6 +1764,7 @@
STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Staciaj nomoj - alklaku nomon por centre de la ĉefvido vidi ĝin
STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Elektu grandecon/tipon de flughaveno
STR_305C_0 :{STATION} {STATIONFEATURES}
+STR_STATION_SIGN_TINY :{TINYFONT}{STATION}
STR_305E_RAILROAD_STATION :Stacidomo
STR_305F_AIRCRAFT_HANGAR :Aviadila hangaro
STR_3060_AIRPORT :Flughaveno
@@ -1765,7 +1779,11 @@
STR_306A_BUOY_IN_THE_WAY :{WHITE}...buo okupas la lokon
STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stacio tro vastas
STR_306D_NONUNIFORM_STATIONS_DISALLOWED :{WHITE}...nekonformaj stacioj neebligitaj
+STR_USE_CTRL_TO_SELECT_MORE :{BLACK}Tenu la CTRL-klavon por elekti pliajn erojn
+STR_UNDEFINED :(nedifinita tekstero)
+STR_STAT_CLASS_DFLT :Defaŭlta stacio
+STR_STAT_CLASS_WAYP :Transirejoj
##id 0x3800
STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Ŝipdeponeja Direkto
@@ -1783,6 +1801,7 @@
STR_4002_SAVE :{BLACK}Konservu
STR_4003_DELETE :{BLACK}Forviŝu
STR_4004 :{COMPANY} je {DATE_LONG}
+STR_4005_BYTES_FREE :{BLACK}{COMMA} megabitoko{P "" j} libera{P "" j}
STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Ne eblas legi diskon
STR_4007_GAME_SAVE_FAILED :{WHITE}Ludkonservado Fiaskis
STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Ne eblas forviŝi dosieron
@@ -1917,6 +1936,12 @@
############ WARNING, using range 0x6000 for strings that are stored in the savegame
############ These strings may never get a new id, or savegames will break!
##id 0x6000
+STR_SV_EMPTY :
+STR_SV_UNNAMED :Sennome
+STR_SV_TRAIN_NAME :Trajno {COMMA}
+STR_SV_ROADVEH_NAME :Vojveturilo {COMMA}
+STR_SV_SHIP_NAME :Ŝipo {COMMA}
+STR_SV_AIRCRAFT_NAME :Aviadilo {COMMA}
STR_SV_STNAME :{STRING}
STR_SV_STNAME_NORTH :Norda {STRING}
@@ -2031,12 +2056,12 @@
STR_7000 :
STR_7001 :{WHITE}{COMPANY} {BLACK}{PLAYERNAME}
STR_7002_PLAYER :(Ludanto {COMMA})
-STR_7004_NEW_FACE :{BLACK}Novan Vizaĝon
+STR_7004_NEW_FACE :{BLACK}Nova Vizaĝo
STR_7005_COLOR_SCHEME :{BLACK}Kolorskemo
STR_7006_COLOR_SCHEME :{GOLD}Kolorskemo:
-STR_7007_NEW_COLOR_SCHEME :{WHITE}Novan Kolorskemon
-STR_7008_COMPANY_NAME :{BLACK}Kompania Nomo
-STR_7009_PRESIDENT_NAME :{BLACK}Manaĝanta Nomo
+STR_7007_NEW_COLOR_SCHEME :{WHITE}Nova Kolorskemo
+STR_7008_COMPANY_NAME :{BLACK}Kompaninomo
+STR_7009_PRESIDENT_NAME :{BLACK}Manaĝantnomo
STR_700A_COMPANY_NAME :Kompania Nomo
STR_700B_PRESIDENT_S_NAME :Nomo de la Manaĝanto
STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Ne povas ŝanĝi kompaninomon...
@@ -2095,7 +2120,7 @@
STR_7043_FACE_SELECTION :{WHITE}Vizaĝelekto
STR_7044_MALE :{BLACK}Vira
STR_7045_FEMALE :{BLACK}Virina
-STR_7046_NEW_FACE :{BLACK}Novan Vizaĝon
+STR_7046_NEW_FACE :{BLACK}Nova Vizaĝo
STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Nuligu elekton de nova vizaĝo
STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Akceptu elekton de nova vizaĝo
STR_7049_SELECT_MALE_FACES :{BLACK}Elektu virajn vizaĝojn
@@ -2149,12 +2174,12 @@
STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Recesio finiĝis!{}{}Komerca pliboniĝos donas konfidon al industrioj! Ekonomio pliboniĝas!
STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Ŝaltu inter granda kaj malgranda fenestro
STR_7076_COMPANY_VALUE :{GOLD}Kompania valoro: {WHITE}{CURRENCY64}
-STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Aĉetu 25%-an dividaĵon en kompanio
-STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Vendu 25%-an dividaĵon en kompanio
+STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Aĉetu 25%-an dividaĵon
+STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Vendu 25%-an dividaĵon
STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Aĉetu 25%-an dividaĵon en ĉi tiu kompanio
STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Vendu 25%-an dividaĵon en ĉi tiu kompanio
-STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Ne povas aĉeti 25%-an dividaĵon en ĉi tiu kompanio...
-STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Ne povas vendi 25%-an dividaĵon en ĉi tiu kompanio...
+STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Ne povas aĉeti 25%-an dividaĵon...
+STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Ne povas vendi 25%-an dividaĵon...
STR_707D_OWNED_BY :{WHITE}({COMMA}% posedataj de {COMPANY})
STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA}% posedataj de {COMPANY}{} {COMMA}% posedataj de {COMPANY})
STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{COMPANY} estas transprenita de {COMPANY}!
@@ -2322,9 +2347,9 @@
STR_8081_MIGHTYMOVER_MAIL_TRUCK :Poŝtaŭto "MightyMover"
STR_8082_POWERNAUGHT_MAIL_TRUCK :Poŝtaŭto "Powernaught"
STR_8083_WIZZOWOW_MAIL_TRUCK :Poŝtaŭto "Wizzowow"
-STR_8084_WITCOMBE_OIL_TANKER :Oleŝipo "Witcombe"
-STR_8085_FOSTER_OIL_TANKER :Oleŝipo "Foster"
-STR_8086_PERRY_OIL_TANKER :Oleŝipo "Perry"
+STR_8084_WITCOMBE_OIL_TANKER :Oleŝarĝaŭto "Witcombe"
+STR_8085_FOSTER_OIL_TANKER :Oleŝarĝaŭto "Foster"
+STR_8086_PERRY_OIL_TANKER :Oleŝarĝaŭto "Perry"
STR_8087_TALBOTT_LIVESTOCK_VAN :Brutŝarĝaŭto "Talbott"
STR_8088_UHL_LIVESTOCK_VAN :Brutŝarĝaŭto "Uhl"
STR_8089_FOSTER_LIVESTOCK_VAN :Brutŝarĝaŭto "Foster"
@@ -2580,7 +2605,7 @@
STR_885C_BROKEN_DOWN :{RED}Rompite
STR_885D_AGE_RUNNING_COST_YR :{BLACK}Aĝo: {LTBLUE}{STRING}{BLACK} Irkosto: {LTBLUE}po {CURRENCY} jare
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Pezo: {LTBLUE}{WEIGHT_S} {BLACK}Forto: {LTBLUE}{POWER}{BLACK} Pleja rapideco: {LTBLUE}{VELOCITY}
-STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Pezo: {LTBLUE}{WEIGHT_S} {BLACK}Forto: {LTBLUE}{POWER}{BLACK} Pleja rapideco: {LTBLUE}{VELOCITY} {BLACK}Pleja T.E.: {LTBLUE}{FORCE}
+STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Pezo: {LTBLUE}{WEIGHT_S} {BLACK}Forto: {LTBLUE}{POWER}{BLACK} Pleja rapido: {LTBLUE}{VELOCITY} {BLACK}Pleja tiro: {LTBLUE}{FORCE}
STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Ĉi-jara gajno: {LTBLUE}{CURRENCY} (lastjara: {CURRENCY})
STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Fidebleco: {LTBLUE}{COMMA}% {BLACK}Rompiĝoj post lasta prizorgo: {LTBLUE}{COMMA}
STR_8861_STOPPED :{RED}Haltis
@@ -2605,6 +2630,7 @@
##id 0x9000
STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Vojveturilo okupas la lokon
+STR_9001_ROAD_VEHICLES :{WHITE}{COMPANY} - {COMMA} Vojveturilo{P "" j}
STR_9002 :{WHITE}{VEHICLE}
STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Vojveturila Deponejo
STR_9004_NEW_VEHICLES :{BLACK}Novaj Veturiloj
@@ -2660,7 +2686,13 @@
STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Renomu vojveturilan tipon
STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Ne povas renomi vojveturilan tipon...
STR_9038_GO_TO_ROADVEH_DEPOT :Iru al {TOWN} Vojveturila Deponejo
+STR_SERVICE_AT_ROADVEH_DEPOT :Prizorgo ĉe {TOWN} Vojveturila Deponejo
+STR_REFIT_ROAD_VEHICLE_TO_CARRY :{BLACK}Transformu vojveturilon por porti alian ŝarĝon
+STR_REFIT_ROAD_VEHICLE :{BLACK}Transformu vojveturilon
+STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED :{BLACK}Transformu vojveturilon por porti elektitan ŝarĝon
+STR_REFIT_ROAD_VEHICLE_CAN_T :{WHITE}Ne povas transformi vojveturilon...
+STR_ROAD_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Elektu portotan ŝarĝon de la vojveturilo
##id 0x9800
STR_9800_DOCK_CONSTRUCTION :Havenkonstruado
@@ -2668,6 +2700,7 @@
STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Ne povas konstrui havenon ĉi tie...
STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Ŝipdeponejo
STR_9804_NEW_SHIPS :{BLACK}Novaj Ŝipoj
+STR_9805_SHIPS :{WHITE}{COMPANY} - {COMMA} Ŝipo{P "" j}
STR_9808_NEW_SHIPS :{WHITE}Novaj Ŝipoj
STR_9809_BUILD_SHIP :{BLACK}Kreu Ŝipon
STR_CLONE_SHIP :{BLACK}Klonu Ŝipon
@@ -2791,6 +2824,7 @@
STR_A032_NAME_AIRCRAFT :{BLACK}Nomu aviadilon
STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Enloĝantoj festas . . .{}Unua aviadilo alvenas en {STATION}!
STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Aviadilo Kraŝas!{}{COMMA} mortas pro fajro en {STATION}
+STR_PLANE_CRASH_OUT_OF_FUEL :{BLACK}{BIGFONT}Aviadila Kraŝo!{}Aviadilo ne havis sufiĉan brulaĵon, {COMMA} mortas pro fajro!
STR_A036 :{TINYFONT}{BLACK}{STATION}
STR_A037_RENAME :{BLACK}Renomu
STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Renomu aviadiltipon
@@ -2824,23 +2858,33 @@
STR_PERFORMANCE_DETAIL_KEY :{BLACK}Detaloj
STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY :{BLACK}({CURRCOMPACT}/{CURRCOMPACT})
STR_PERFORMANCE_DETAIL_AMOUNT_INT :{BLACK}({COMMA}/{COMMA})
+STR_PERFORMANCE_DETAIL_PERCENT :{WHITE}{NUM}%
SET_PERFORMANCE_DETAIL_INT :{BLACK}{NUM}
############ Those following lines need to be in this order!!
STR_PERFORMANCE_DETAIL_VEHICLES :{BLACK}Veturiloj:
+STR_PERFORMANCE_DETAIL_STATIONS :{BLACK}Stacioj:
STR_PERFORMANCE_DETAIL_MIN_PROFIT :{BLACK}Malpleja gajno:
STR_PERFORMANCE_DETAIL_MIN_INCOME :{BLACK}Malpleja enspezo:
STR_PERFORMANCE_DETAIL_MAX_INCOME :{BLACK}Pleja enspezo:
STR_PERFORMANCE_DETAIL_DELIVERED :{BLACK}Liverite:
STR_PERFORMANCE_DETAIL_CARGO :{BLACK}Ŝarĝo:
+STR_PERFORMANCE_DETAIL_MONEY :{BLACK}Mono:
STR_PERFORMANCE_DETAIL_LOAN :{BLACK}Prunto:
+STR_PERFORMANCE_DETAIL_TOTAL :{BLACK}Entute:
############ End of order list
+STR_PERFORMANCE_DETAIL_VEHICLES_TIP :{BLACK}Nombro da veturiloj; tio enkalkulas vojveturilojn, trajnojn, ŝipojn kaj aviadilojn
+STR_PERFORMANCE_DETAIL_STATIONS_TIP :{BLACK}Nombro da staciaj eroj. Ĉiu parto de stacio (ekz. stacidomo, bushaltejo, flughaveno) kalkuliĝas, eĉ se konektite kiel unu stacio
+STR_PERFORMANCE_DETAIL_MIN_PROFIT_TIP :{BLACK}La gajno de la malplejenspeza veturilo (de ĉiuj veturiloj pli aĝaj ol 2 jaroj)
STR_PERFORMANCE_DETAIL_MIN_INCOME_TIP :{BLACK}Enspezite en la plej malaltenspeza monato de la lasta 12 kvaronoj
STR_PERFORMANCE_DETAIL_MAX_INCOME_TIP :{BLACK}Enspezite en la plej altenspeza monato de la lasta 12 kvaronoj
STR_PERFORMANCE_DETAIL_DELIVERED_TIP :{BLACK}Ŝarĝunuoj liveritaj en la lastaj 4 kvaronoj
STR_PERFORMANCE_DETAIL_CARGO_TIP :{BLACK}Nombro da ŝarĝtipoj liveritaj en la lasta kvarono
+STR_PERFORMANCE_DETAIL_MONEY_TIP :{BLACK}Monkvanto de ĉi tiu kompanio en la banko
STR_PERFORMANCE_DETAIL_LOAN_TIP :{BLACK}La monkvanto pruntita de ĉi tiu kompanio
+STR_PERFORMANCE_DETAIL_TOTAL_TIP :{BLACK}Entuta poentaro el eblaj poentoj
STR_NEWGRF_SETTINGS_BUTTON :{BLACK}Agordoj de NewGRF
+STR_NEWGRF_SETTINGS_CAPTION :{WHITE}Agordoj de NewGRF
STR_NEWGRF_APPLY_CHANGES :{BLACK}Apliku ŝanĝojn
STR_NEWGRF_SET_PARAMETERS :{BLACK}Agordu parametrojn
STR_NEWGRF_TIP :{BLACK}Listo da ĉiuj instalitaj Newgrf-aj aroj. Alklaku aron por ŝanĝi la agordojn
@@ -2848,14 +2892,15 @@
STR_NEWGRF_FILENAME :{BLACK}Dosiernomo: {SILVER}{STRING}
STR_NEWGRF_GRF_ID :{BLACK}GRF ID: {SILVER}{STRING}
STR_NEWGRF_MD5SUM :{BLACK}MD5sum: {SILVER}{STRING}
+STR_NEWGRF_CONFIRMATION_TEXT :{YELLOW}Vi ĉi tiel ŝanĝos al kuranta ludo; tio povas kraŝigi la ludon.{}Ĉu vi nepre volas fari tion?
STR_NEWGRF_ADD :{BLACK}Aldonu
STR_NEWGRF_ADD_TIP :{BLACK}Aldonu NewGRF-dosieron al la listo
STR_NEWGRF_REMOVE :{BLACK}Forviŝu
STR_NEWGRF_REMOVE_TIP :{BLACK}Remove the selected NewGRF file from the list
-STR_NEWGRF_MOVEUP :{BLACK}Movu Supren
+STR_NEWGRF_MOVEUP :{BLACK}Supren
STR_NEWGRF_MOVEUP_TIP :{BLACK}Movu la elektitan NewGRF-dosieron supren en la listo
-STR_NEWGRF_MOVEDOWN :{BLACK}Movu Malsupren
+STR_NEWGRF_MOVEDOWN :{BLACK}Malsupren
STR_NEWGRF_MOVEDOWN_TIP :{BLACK}Movu la elektitan NewGRF-dosieron malsupren en la listo
STR_NEWGRF_FILE_TIP :{BLACK}Listo da instalitaj NewGRF-dosieroj. Alklaku dosieron por ŝanĝi la parametrojn
STR_NEWGRF_PARAMETER :{BLACK}Parametroj: {SILVER}{STRING}
@@ -2882,13 +2927,27 @@
STR_CURRENCY_PREVIEW :{LTBLUE}Antaŭvido: {ORANGE}{CURRENCY}
STR_CURRENCY_CHANGE_PARAMETER :{BLACK}Ŝanĝu parametron por alia monunuo
+STR_TRAIN :{BLACK}{TRAIN}
STR_BUS :{BLACK}{BUS}
STR_LORRY :{BLACK}{LORRY}
+STR_PLANE :{BLACK}{PLANE}
+STR_SHIP :{BLACK}{SHIP}
+STR_SCHEDULED_TRAINS :{WHITE}{STATION} - {COMMA} Trajno{P "" j}
+STR_SCHEDULED_ROAD_VEHICLES :{WHITE}{STATION} - {COMMA} Vojveturilo{P "" j}
+STR_SCHEDULED_AIRCRAFT :{WHITE}{STATION} - {COMMA} Aviadilo{P "" j}
+STR_SCHEDULED_SHIPS :{WHITE}{STATION} - {COMMA} Ŝipo{P "" j}
+STR_SCHEDULED_TRAINS_TIP :{BLACK}Montru ĉiujn trajnojn kun ĉi tiu stacio en la plano
+STR_SCHEDULED_ROAD_VEHICLES_TIP :{BLACK}Montru ĉiujnvojveturilojn kun ĉi tiu stacio en la plano
+STR_SCHEDULED_AIRCRAFT_TIP :{BLACK}Montru ĉiujn aviadilojn kun ĉi tiu stacio en la plano
+STR_SCHEDULED_SHIPS_TIP :{BLACK}Montru ĉiujn ŝipojn kun ĉi tiu stacio en la plano
+STR_VEH_WITH_SHARED_ORDERS_LIST :{WHITE}Dividitaj ordenoj de {COMMA} Veturilo{P "" j}
+STR_VEH_WITH_SHARED_ORDERS_LIST_TIP :{BLACK}Montru ĉiujn veturilojn kiuj dividas ĉi tiun planon
### depot strings
+STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}Vi volas vendi ĉiujn veturilojn en la deponejo. Ĉu vi certas?
STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TIP :{BLACK}Vendu ĉiujn trajnojn en la deponejo
STR_DEPOT_SELL_ALL_BUTTON_ROADVEH_TIP :{BLACK}Vendu ĉiujn vojveturilojn en la deponejo
@@ -2905,12 +2964,30 @@
STR_DEPOT_AUTOREPLACE_SHIP_TIP :{BLACK}Aŭtomate anstataŭu ĉiujn ŝipojn en la deponejo
STR_DEPOT_AUTOREPLACE_AIRCRAFT_TIP :{BLACK}Aŭtomate anstataŭu ĉiujn aviadilojn en la hangaro
+STR_VEHICLE_LIST_ROADVEH_DEPOT :{BLACK}{STRING} - {COMMA} Vojveturilo{P "" j}
+STR_VEHICLE_LIST_SHIP_DEPOT :{BLACK}{STRING} - {COMMA} Ŝipo{P "" j}
+STR_VEHICLE_LIST_AIRCRAFT_DEPOT :{BLACK}{STRING} - {COMMA} Aviadilo{P "" j}
+STR_REPLACE_VEHICLES_WHITE :{WHITE}Anstataŭu {STRING.n}
+STR_REPLACE_VEHICLES_START :{BLACK}Komencu Anstataŭi
+STR_REPLACE_VEHICLES_STOP :{BLACK}Ĉesu Anstataŭi
STR_NOT_REPLACING :{BLACK}Ne anstataŭante
STR_NOT_REPLACING_VEHICLE_SELECTED :{BLACK}Ne elektiĝis veturilo
+STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}Elektu maŝinon por anstataŭi
+STR_REPLACE_HELP_RIGHT_ARRAY :{BLACK}Elektu novan maŝinon por uzi anstataŭ la maldekstre elektitan
+STR_REPLACE_HELP_STOP_BUTTON :{BLACK}Premu por ĉesi anstataŭi la maldekstre elektitan maŝinon
+STR_REPLACE_HELP_START_BUTTON :{BLACK}Premu por komenci anstataŭi la maldekstre elektitan maŝinon per la dekstre elektitan
+STR_REPLACE_HELP_RAILTYPE :{BLACK}Elektu fervojtipon por kiu vi volas anstataŭigi maŝinojn
+STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Montras ontan maŝinecon de la maldekstra maŝino, se anstataŭote
+STR_REPLACE_HELP :{BLACK}Ĉi tio permesas vin anstataŭi maŝinojn de unu al alia tipo, kiam trajnoj de la unu tipo eniras la deponejon
+STR_REPLACE_REMOVE_WAGON :{BLACK}Vagonforigo: {ORANGE}{SKIP}{STRING}
+STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Ĉe aŭtomata anstataŭigo tenu saman longecon de la trajno per forigo de vagonoj (defronte), se per nova maŝino la trajno plilongiĝas
+STR_REPLACE_ENGINE_WAGON_SELECT :{BLACK}Anstataŭante: {ORANGE}{SKIP}{SKIP}{STRING}
+STR_REPLACE_ENGINE_WAGON_SELECT_HELP :{BLACK} EKSPERIMENTA AĴO {}Ŝaltu inter maŝina kaj vagona anstataŭigo.{}Vagona anstataŭigo nur okazos se la nova vagono povas transformiĝi por porti saman ŝarĝon kiel la malnova. Por ĉiu vagono tio kontroliĝos dum anstataŭado.
STR_ENGINE_NOT_BUILDABLE :{WHITE}Maŝino ne kreeblas
STR_ENGINES :Maŝinoj
+STR_WAGONS :Vagonoj
STR_MASS_STOP_DEPOT_TRAIN_TIP :{BLACK}Alklaku por haltigi ĉiujn trajnojn en la deponejo
STR_MASS_STOP_DEPOT_ROADVEH_TIP :{BLACK}Alklaku por haltigi ĉiujn vojveturilojn en la deponejo
@@ -2925,6 +3002,8 @@
STR_MASS_STOP_LIST_TIP :{BLACK}Alklaku por haltigi ĉiujn veturilojn en la listo
STR_MASS_START_LIST_TIP :{BLACK}Alklaku por starti ĉiujn veturilojn en la listo
+STR_SHORT_DATE :{WHITE}{DATE_TINY}
+STR_SIGN_LIST_CAPTION :{WHITE}Signolisto - {COMMA} Signo{P "" j}
STR_ORDER_REFIT_FAILED :{WHITE}Fiasko de ordeno transformi haltigis {STRING.n} {COMMA}
@@ -2937,35 +3016,82 @@
############ End of list of rail types
+STR_TINY_BLACK :{BLACK}{TINYFONT}{COMMA}
+STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}Kosto: {GOLD}{CURRENCY}{BLACK} Pezo: {GOLD}{WEIGHT_S}
+STR_PURCHASE_INFO_SPEED_POWER :{BLACK}Rapido: {GOLD}{VELOCITY}{BLACK} Forto: {GOLD}{POWER}
+STR_PURCHASE_INFO_SPEED :{BLACK}Rapido: {GOLD}{VELOCITY}
+STR_PURCHASE_INFO_RUNNINGCOST :{BLACK}Irkosto: {GOLD}po {CURRENCY} jare
+STR_PURCHASE_INFO_CAPACITY :{BLACK}Kapablo: {GOLD}{CARGO} {STRING}
+STR_PURCHASE_INFO_DESIGNED_LIFE :{BLACK}Pripensite: {GOLD}{NUM}{BLACK} Vivlongo: {GOLD}{COMMA} jaroj
+STR_PURCHASE_INFO_RELIABILITY :{BLACK}Pleja Fidebleco: {GOLD}{COMMA}%
+STR_PURCHASE_INFO_COST :{BLACK}Kosto: {GOLD}{CURRENCY}
+STR_PURCHASE_INFO_WEIGHT_CWEIGHT :{BLACK}Pezo: {GOLD}{WEIGHT_S} ({WEIGHT_S})
+STR_PURCHASE_INFO_COST_SPEED :{BLACK}Kosto: {GOLD}{CURRENCY}{BLACK} Rapido: {GOLD}{VELOCITY}
+STR_PURCHASE_INFO_AIRCRAFT_CAPACITY :{BLACK}Kapablo: {GOLD}{COMMA} pasaĝeroj, {COMMA} sakoj da poŝto
+STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Vagonfortoj: {GOLD}+{POWER}{BLACK} Weight: {GOLD}+{WEIGHT_S}
+STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Transformebla al: {GOLD}
+STR_PURCHASE_INFO_ALL_TYPES :Ĉiaj ŝarĝoj
+STR_PURCHASE_INFO_ALL_BUT :Ĉio krom {GOLD}
+STR_PURCHASE_INFO_MAX_TE :{BLACK}Maksimuma Tiro: {GOLD}{FORCE}
########### String for New Landscape Generator
STR_GENERATE :{WHITE}Generu
+STR_RANDOM :{BLACK}Hazardigu
+STR_RANDOM_HELP :{BLACK}Ŝanĝo la hazardan enigon uzatan de la terengenerilo
+STR_WORLD_GENERATION_CAPTION :{WHITE}Mondgenerado
+STR_RANDOM_SEED :{BLACK}Hazarda Enigo:
+STR_RANDOM_SEED_HELP :{BLACK}Klaku por enigi hazardan enigon
STR_LAND_GENERATOR :{BLACK}Landgenerilo:
+STR_TREE_PLACER :{BLACK}Arba algoritmo:
STR_HEIGHTMAP_ROTATION :{BLACK}Altecmapa turniĝo:
+STR_TERRAIN_TYPE :{BLACK}Terentipo:
+STR_QUANTITY_OF_SEA_LAKES :{BLACK}Marnivelo:
+STR_SMOOTHNESS :{BLACK}Ebeneco:
+STR_SNOW_LINE_HEIGHT :{BLACK}Neĝlinia alteco:
STR_DATE :{BLACK}Dato:
STR_NUMBER_OF_TOWNS :{BLACK}Kiom da urboj:
STR_NUMBER_OF_INDUSTRIES :{BLACK}Kiom da industrioj:
STR_GENERATE_DATE :{BLACK}{DATE_LONG}
+STR_SNOW_LINE_UP :{BLACK}Altigu la neĝlinion per unu
+STR_SNOW_LINE_DOWN :{BLACK}Malaltigu la neĝlinion per unu
+STR_SNOW_LINE_QUERY_CAPT :{WHITE}Ŝanĝu altecon de la neĝlinio
+STR_START_DATE_QUERY_CAPT :{WHITE}Ŝanĝu komencjaron
STR_HEIGHTMAP_SCALE_WARNING_CAPTION :{WHITE}Skala averto
STR_HEIGHTMAP_SCALE_WARNING_MESSAGE :{YELLOW}Ne rekomendindas tro ŝanĝi la grandecon de la mapo. Ĉu daŭrigi la generadon?
+STR_SNOW_LINE_HEIGHT_NUM :{NUM}
STR_HEIGHTMAP_NAME :{BLACK}Altecmapa nomo:
STR_HEIGHTMAP_SIZE :{BLACK}Grandeco: {ORANGE}{NUM} x {NUM}
STR_GENERATION_WORLD :{WHITE}Generante mondon...
STR_GENERATION_ABORT :{BLACK}Ĉesu
STR_GENERATION_ABORT_CAPTION :{WHITE}Ĉesu generi mondon
STR_GENERATION_ABORT_MESSAGE :{YELLOW}Ĉu vi vere volas ĉesi generi mondon?
+STR_PROGRESS :{WHITE}{NUM}% komplete
STR_GENERATION_PROGRESS :{BLACK}{NUM} / {NUM}
+STR_WORLD_GENERATION :{BLACK}Mondgenerado
+STR_TREE_GENERATION :{BLACK}Arba generado
+STR_UNMOVABLE_GENERATION :{BLACK}Nemoveblaĵa generado
+STR_CLEARING_TILES :{BLACK}Generado de malglataj kaj rokaj regionoj
+STR_SETTINGUP_GAME :{BLACK}Agordante ludon
+STR_PREPARING_TILELOOP :{BLACK}Trakurante kvadratojn
+STR_PREPARING_GAME :{BLACK}Preparante ludon
STR_DIFFICULTY_TO_CUSTOM :{WHITE}Ĉi tiu ago ŝanĝis la malfacilec-nivelon al 'ŝanĝite'
+STR_SE_FLAT_WORLD :{WHITE}Ebena lando
+STR_SE_FLAT_WORLD_TIP :{BLACK}Generu ebenan landon
+STR_SE_RANDOM_LAND :{WHITE}Hazarda lando
+STR_SE_NEW_WORLD :{BLACK}Kreu novan scenaron
+STR_SE_CAPTION :{WHITE}Scenara tipo
STR_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Malaltigu la altecon de ebena lando per unu
STR_FLAT_WORLD_HEIGHT_UP :{BLACK}Altigu la altecon de ebena lando per unu
STR_FLAT_WORLD_HEIGHT_QUERY_CAPT :{WHITE}Ŝanĝu altecon de ebena lando
STR_FLAT_WORLD_HEIGHT :{BLACK}Alteco de ebena lando:
STR_FLAT_WORLD_HEIGHT_NUM :{NUM}
+STR_SMALLMAP_CENTER :{BLACK}Centrigu la mapeton al la nuna loko
########### String for new airports
+STR_SMALL_AIRPORT :{BLACK}Malgranda
STR_CITY_AIRPORT :{BLACK}Urbo
STR_METRO_AIRPORT :{BLACK}Ĉefurba Flughaveno
STR_INTERNATIONAL_AIRPORT :{BLACK}Internacia flughaveno
@@ -2975,6 +3101,7 @@
STR_HELIDEPOT :{BLACK}Helikopterdeponejo
STR_HELISTATION :{BLACK}Helikopterstacio
+STR_SMALL_AIRPORTS :{BLACK}Malgrandaj flughavenoj
STR_LARGE_AIRPORTS :{BLACK}Grandaj flughavenoj
STR_HUB_AIRPORTS :{BLACK}Nabaj flughavenoj
STR_HELIPORTS :{BLACK}Helikopterhaveno
--- a/lang/estonian.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/estonian.txt Wed Jan 03 08:32:17 2007 +0000
@@ -113,6 +113,7 @@
STR_0032_OIL.genitiiv :Nafta
STR_0033_LIVESTOCK :Kariloom
STR_0033_LIVESTOCK.g :Kariloomade
+STR_0033_LIVESTOCK.genitiiv :Kariloomade
STR_0034_GOODS :Kaubad
STR_0034_GOODS.g :Kaupade
STR_0034_GOODS.genitiiv :Kaupade
@@ -368,7 +369,7 @@
STR_012D :{WHITE}{STRING}
STR_012E_CANCEL :{BLACK}Loobu
STR_012F_OK :{BLACK}OK
-STR_0130_RENAME :{BLACK}Nime muutmine
+STR_0130_RENAME :{BLACK}Muuda nime
STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Liiga palju määratletud nimesid
STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Valitud nimi on juba kasutusel
@@ -386,7 +387,7 @@
STR_013E_CAPACITIES :{BLACK}Mahutavused
STR_013E_TOTAL_CARGO :{BLACK}Laadungit kokku
STR_013F_CAPACITY :{BLACK}Mahutavus: {LTBLUE}{CARGO}
-STR_CAPACITY_MULT :{BLACK}Mahutuvus: {LTBLUE}{CARGO} (x{NUM})
+STR_CAPACITY_MULT :{BLACK}Mahutavus: {LTBLUE}{CARGO} (x{NUM})
STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Rongi kogumahutavus:
STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO})
STR_TOTAL_CAPACITY_MULT :{LTBLUE}- {CARGO} ({SHORTCARGO}) (x{NUM})
@@ -415,7 +416,7 @@
STR_UNITS_SI :SI
STR_UNITS_VELOCITY_IMPERIAL :{COMMA} miili tunnis
-STR_UNITS_VELOCITY_METRIC :{COMMA} km tunnis
+STR_UNITS_VELOCITY_METRIC :{COMMA} km/h
STR_UNITS_VELOCITY_SI :{COMMA} m/s
STR_UNITS_POWER_IMPERIAL :{COMMA}hj
@@ -1098,10 +1099,10 @@
STR_AIRCRAFT_HAS_INVALID_ENTRY :{WHITE}Õhusõiduki {COMMA} plaanis on kehtetud jaam
# end of order system
-STR_TRAIN_AUTORENEW_FAILED :{WHITE}Rongi automaatne uuendamine {COMMA} ebaõnnestus (money limit)
-STR_ROADVEHICLE_AUTORENEW_FAILED :{WHITE}Maanteesõiduki automaatne uuendus ebaõnnestus {COMMA} (money limit)
-STR_SHIP_AUTORENEW_FAILED :{WHITE}Laeva automaatne uuendus ebaõnnestus {COMMA} (money limit)
-STR_AIRCRAFT_AUTORENEW_FAILED :{WHITE}Õhusõiduki automaatne uuendus ebaõnnestus{COMMA} (money limit)
+STR_TRAIN_AUTORENEW_FAILED :{WHITE}Rongi automaatne uuendamine {COMMA} ebaõnnestus (rahalimiit)
+STR_ROADVEHICLE_AUTORENEW_FAILED :{WHITE}Maanteesõiduki automaatne uuendus ebaõnnestus {COMMA} (rahalimiit)
+STR_SHIP_AUTORENEW_FAILED :{WHITE}Laeva automaatne uuendus ebaõnnestus {COMMA} (rahalimiit)
+STR_AIRCRAFT_AUTORENEW_FAILED :{WHITE}Õhusõiduki automaatne uuendus ebaõnnestus{COMMA} (rahalimiit)
STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}Rong {COMMA} on peale asendust liiga pikk
STR_CONFIG_PATCHES :{BLACK}Paranduste seaded
@@ -1174,7 +1175,7 @@
STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE :Päevapidi
STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT :{LTBLUE}Kõrguse level kui kõrgele lapik kaart läheb: {ORANGE}{STRING}
-STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maksimaalne jaama ala: {ORANGE}{STRING} {RED}Hoiatus: Kõrged seaded aeglustavad mängu
+STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maksimaalne jaama ala: {ORANGE}{STRING} {RED}Hoiatus: kõrged seaded aeglustavad mängu
STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Kopteri jaamades helikopterite automaatne teenindus: {ORANGE}{STRING}
STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR :{LTBLUE}Lingi maastiku riba raudtee/tee/vee/lennujaama tööriistaribaga: {ORANGE}{STRING}
STR_CONFIG_PATCHES_REVERSE_SCROLLING :{LTBLUE}Kui kerid hiirega, liiguta vaade vastassuunda: {ORANGE}{STRING}
@@ -1247,7 +1248,7 @@
STR_CHEATS :{WHITE}Petmine
STR_CHEATS_TIP :{BLACK}Märgistatud kastid näitavad et, kas sa oled varem seda pettust kasutanud
-STR_CHEATS_WARNING :{BLACK}Hoiatus! Sa kavatsed oma konkurente reeta. Pea meeles, et sellest häbist ei saa sa enam kunagi lahti.
+STR_CHEATS_WARNING :{BLACK}Hoiatus! Sa kavatsed oma konkurente reeta. Pea meeles, et sellisest häbist ei saa sa enam kunagi lahti.
STR_CHEAT_MONEY :{LTBLUE}Suurenda raha hulka {CURRENCY64} võrra
STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Mängi, kui mängija: {ORANGE}{COMMA}
STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Maagiline buldooser(eemaldamatute objektide eemaldamine): {ORANGE}{STRING}
@@ -1365,7 +1366,7 @@
STR_CONFIG_GAME_PRODUCTION :{WHITE}Tootlikuse muutmine
TEMP_AI_IN_PROGRESS :{WHITE}Tervitused uuele TI'le(AI). Töö selle kallal veel käib. Peaksite eeldama, et esineb probleeme. Kui juhtud tegema kuvatõmmise, siis postita see ka foorumisse. Edu!
-TEMP_AI_ACTIVATED :{WHITE}Hoiatus: uus TI(AI) on veel alfa staadiumis! Ainult maanteesõidukid töötavad!
+TEMP_AI_ACTIVATED :{WHITE}Hoiatus: uus tehisintelligents on veel katsetamisel! Hetkel töötavad ainult maanteesõidukid!
TEMP_AI_MULTIPLAYER :{WHITE}TÄHELEPANU! Seda funksiooni veel teistitakse. Palun teata kõik probleemid sellega truelight@openttd.org.
############ network gui strings
@@ -1629,7 +1630,7 @@
STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Siia ei saa raudteed ehitada...
STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Siit ei saa raudteed eemaldada...
STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Siit ei saa signaaltulesid eemaldada...
-STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Depoo orientatsioon
+STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Depoo suuna
STR_1015_RAILROAD_CONSTRUCTION :Raudtee ehitus
STR_TOOLB_ELRAIL_CONSTRUCTION :Elektriraudtee ehitus
STR_1016_MONORAIL_CONSTRUCTION :Monorelsi ehitus
@@ -1642,7 +1643,7 @@
STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Ehita rongitunnel
STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Rööbaste ja signaaltulede ehitamine/eemaldamine
STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Silla valik - klõpsa sobivale sillale, et seda ehitada
-STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}Depoo orientatsiooni valimine
+STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}Depoole suuna valimine
STR_1021_RAILROAD_TRACK :Raudtee
STR_1023_RAILROAD_TRAIN_DEPOT :Rongidepoo
STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...ala kuulub teisele ettevõttele
@@ -1660,7 +1661,7 @@
STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Vali sillatüüp
STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Siia ei saa maanteed ehitada...
STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Siit ei saa maanteed eemaldada...
-STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Depoo orientatsioon
+STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Depoo suund
STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Siia ei saa depood ehitada...
STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Siia ei saa bussijaama ehitada...
STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Siia ei saa laadimisplatsi ehitada...
@@ -1672,7 +1673,7 @@
STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Ehita sild
STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Ehita tunnel
STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Teeehituse ja -eemaldamise vahetamine
-STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Vali depoo orientatsioon
+STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Vali depoole suund
STR_1814_ROAD :Maantee
STR_1815_ROAD_WITH_STREETLIGHTS :Valgustatud maantee
STR_1816_TREE_LINED_ROAD :Kolmerajaline tee
@@ -1840,8 +1841,8 @@
STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}Jaam {STATION} ei võta enam vastu veoseid {STRING}, ega {STRING}
STR_3040_NOW_ACCEPTS :{WHITE}Jaam {STATION} võtab nüüd vastu veost {STRING}
STR_3041_NOW_ACCEPTS_AND :{WHITE}Jaam {STATION} võtab nüüd vastu veoseid {STRING} ja {STRING}
-STR_3042_BUS_STATION_ORIENTATION :{WHITE}Bussijaama orientatsioon
-STR_3043_TRUCK_STATION_ORIENT :{WHITE}Laadimisplatsi orientatsioon
+STR_3042_BUS_STATION_ORIENTATION :{WHITE}Bussijaama suund
+STR_3043_TRUCK_STATION_ORIENT :{WHITE}Laadimisplatsi suund
STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Bussijaam tuleb enne hävitada
STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Enne pead laadimisplatsi hävitama
STR_3048_STATIONS :{WHITE}{COMPANY} - {COMMA} Jaam{P "" ad}
@@ -1850,11 +1851,11 @@
STR_304B_SITE_UNSUITABLE :{WHITE}...ebasobiv koht
STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Liiga lähedal teisele sadamale
STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Enne pead sadama hävitama
-STR_304E_SELECT_RAILROAD_STATION :{BLACK}Raudteejaama orientatsiooni valimine
+STR_304E_SELECT_RAILROAD_STATION :{BLACK}Raudteejaamale suuna valimine
STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Vali raudteejaama platvormide arv
STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Vali raudteejaama pikkus
-STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Vali bussijaama orientatsioon
-STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Vali laadimisplatsi orientatsioon
+STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Vali bussijaamale suund
+STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Vali laadimisplatsile suund
STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Vaate viimine jaama juurde
STR_3054_SHOW_STATION_RATINGS :{BLACK}Näita jaama reitinguid
STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Muuda jaama nime
@@ -1887,7 +1888,7 @@
STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Paadikuuri Orientatsioon
STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...peab ehitama vette
STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Siia ei saa laevaangaari ehitada...
-STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Laevaangaari orientatsiooni valimine
+STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Laevaangaarile suuna valimine
STR_3804_WATER :Vesi
STR_3805_COAST_OR_RIVERBANK :Kallas
STR_3806_SHIP_DEPOT :Laevaangaar
@@ -1911,7 +1912,7 @@
STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Vali uue mängu tüüp
STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Vali valmis kaart (roheline), eelseadistatud mäng (sinine), või juhusliku kaardiga uus mäng
STR_4010_GENERATE_RANDOM_NEW_GAME :Tekita juhuslik kaart
-STR_4011_LOAD_HEIGHTMAP :{WHITE}Lae kõrgustekaart
+STR_4011_LOAD_HEIGHTMAP :{WHITE}Laadi kõrguskaart
##id 0x4800
STR_4800_IN_THE_WAY :{WHITE}{STRING} on ees
@@ -2037,43 +2038,43 @@
STR_SV_EMPTY :
STR_SV_UNNAMED :Nimetu
STR_SV_TRAIN_NAME :Rong {COMMA}
-STR_SV_ROADVEH_NAME :Maantee sõiduk {COMMA}
+STR_SV_ROADVEH_NAME :Maanteesõiduk {COMMA}
STR_SV_SHIP_NAME :Laev {COMMA}
STR_SV_AIRCRAFT_NAME :Õhusõiduk {COMMA}
STR_SV_STNAME :{STRING}
-STR_SV_STNAME_NORTH :{STRING} Põhi
-STR_SV_STNAME_SOUTH :{STRING} Lõuna
-STR_SV_STNAME_EAST :{STRING} Ida
-STR_SV_STNAME_WEST :{STRING} Lääs
-STR_SV_STNAME_CENTRAL :{STRING} Keskus
-STR_SV_STNAME_TRANSFER :{STRING} Transport
-STR_SV_STNAME_HALT :{STRING} Peatus
-STR_SV_STNAME_VALLEY :{STRING} Org
-STR_SV_STNAME_HEIGHTS :{STRING} Kõrgendikud
-STR_SV_STNAME_WOODS :{STRING} Metsad
-STR_SV_STNAME_LAKESIDE :{STRING} Järveäärne
-STR_SV_STNAME_EXCHANGE :{STRING} Vahetus
-STR_SV_STNAME_AIRPORT :{STRING} Lennujaam
-STR_SV_STNAME_OILFIELD :{STRING} Naftaväli
-STR_SV_STNAME_MINES :{STRING} Kaevandus
-STR_SV_STNAME_DOCKS :{STRING} Sadam
-STR_SV_STNAME_BUOY_1 :{STRING} Poi 1
-STR_SV_STNAME_BUOY_2 :{STRING} Poi 2
-STR_SV_STNAME_BUOY_3 :{STRING} Poi 3
-STR_SV_STNAME_BUOY_4 :{STRING} Poi 4
-STR_SV_STNAME_BUOY_5 :{STRING} Poi 5
-STR_SV_STNAME_BUOY_6 :{STRING} Poi 6
-STR_SV_STNAME_BUOY_7 :{STRING} Poi 7
-STR_SV_STNAME_BUOY_8 :{STRING} Poi 8
-STR_SV_STNAME_BUOY_9 :{STRING} Poi 9
-STR_SV_STNAME_ANNEXE :{STRING} Juurdeehitis
-STR_SV_STNAME_SIDINGS :{STRING} Hargnemine
-STR_SV_STNAME_BRANCH :{STRING} Filiaal
+STR_SV_STNAME_NORTH :Põhja {STRING}
+STR_SV_STNAME_SOUTH : Lõuna {STRING}
+STR_SV_STNAME_EAST : Ida {STRING}
+STR_SV_STNAME_WEST : Lääne {STRING}
+STR_SV_STNAME_CENTRAL :{STRING} keskus
+STR_SV_STNAME_TRANSFER :{STRING} ülekanne
+STR_SV_STNAME_HALT :{STRING} peatus
+STR_SV_STNAME_VALLEY :{STRING} org
+STR_SV_STNAME_HEIGHTS :{STRING} kõrgendikud
+STR_SV_STNAME_WOODS :{STRING} metsad
+STR_SV_STNAME_LAKESIDE :{STRING} järveäärne
+STR_SV_STNAME_EXCHANGE :{STRING} vahetus
+STR_SV_STNAME_AIRPORT :{STRING} lennujaam
+STR_SV_STNAME_OILFIELD :{STRING} naftaväli
+STR_SV_STNAME_MINES :{STRING} kaevandused
+STR_SV_STNAME_DOCKS :{STRING} sadam
+STR_SV_STNAME_BUOY_1 :{STRING} poi #1
+STR_SV_STNAME_BUOY_2 :{STRING} poi #2
+STR_SV_STNAME_BUOY_3 :{STRING} poi #3
+STR_SV_STNAME_BUOY_4 :{STRING} poi #4
+STR_SV_STNAME_BUOY_5 :{STRING} poi #5
+STR_SV_STNAME_BUOY_6 :{STRING} poi #6
+STR_SV_STNAME_BUOY_7 :{STRING} poi #7
+STR_SV_STNAME_BUOY_8 :{STRING} poi #8
+STR_SV_STNAME_BUOY_9 :{STRING} poi #9
+STR_SV_STNAME_ANNEXE :{STRING} juurdeehitis
+STR_SV_STNAME_SIDINGS :{STRING} hargnemine
+STR_SV_STNAME_BRANCH :{STRING} filiaal
STR_SV_STNAME_UPPER :Ülemine {STRING}
STR_SV_STNAME_LOWER :Alumine {STRING}
-STR_SV_STNAME_HELIPORT :{STRING} Helikopteri plats
-STR_SV_STNAME_FOREST :{STRING} Mets
+STR_SV_STNAME_HELIPORT :{STRING} helikopteri maandumisplats
+STR_SV_STNAME_FOREST :{STRING} mets
############ end of savegame specific region!
@@ -2190,7 +2191,7 @@
STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Opereerimiskasumi graafik
STR_7026_BANK_BALANCE :{WHITE}Kontojääk
STR_7027_LOAN :{WHITE}Laen
-STR_MAX_LOAN :{WHITE}Maksimaalne laen: {BLACK}{CURRENCY64}
+STR_MAX_LOAN :{WHITE}Suurim võimalik laen: {BLACK}{CURRENCY64}
STR_7028 :{BLACK}{CURRENCY64}
STR_7029_BORROW :{BLACK}Laena {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
STR_702A_REPAY :{BLACK}Maksa tagasi {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
@@ -2276,8 +2277,8 @@
STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Müü 25% ettevõtte aktsiatest
STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Osta 25% ettevõtte aktsiatest
STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Müü 25% ettevõtte aktsiatest
-STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Ei saa 25% selle ettevõtte aktsiatest osta...
-STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Ei saa 25% selle ettevõtte aktsiatest müüa...
+STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Selle ettevõtte aktsiatest ei saa 25% osta...
+STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Selle ettevõtte aktsiatest ei saa 25% müüa...
STR_707D_OWNED_BY :{WHITE}({COMMA}% on ettevõtte {COMPANY} käes)
STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA}% on ettevõtte {COMPANY} käes{} {COMMA}% on ettevõtte {COMPANY} käes)
STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{COMPANY} võeti üle ettevõtte {COMPANY} poolt!
@@ -2313,52 +2314,52 @@
STR_LIVERY_PANEL_TIP :{BLACK}Vali värviskeem mida muuta, või mitu tükki vajutades CTRL+Kõps. Vajuta kastil et valida värviskeemi kaustamise vahel.
##id 0x8000
-STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Auruvedur)
-STR_8001_MJS_250_DIESEL :MJS 250 (Diisel)
+STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (auruvedur)
+STR_8001_MJS_250_DIESEL :MJS 250 (diisel)
STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphuti tšuhh-tšuhh
STR_8003_POWERNAUT_CHOO_CHOO :Powernauti tšuhh-tšuhh
-STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo
-STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel
-STR_8006_POWERNAUT_DIESEL :Powernaut Diesel
-STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Auruvedur)
-STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Auruvedur)
-STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Auruvedur)
-STR_800A_SH_8P_STEAM :SH '8P' (Auruvedur)
-STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diisel)
-STR_800C_DASH_DIESEL :'Dash' (Diisel)
-STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diisel)
-STR_800E_UU_37_DIESEL :UU '37' (Diisel)
-STR_800F_FLOSS_47_DIESEL :Floss '47' (Diisel)
-STR_8010_CS_4000_DIESEL :CS 4000 (Diisel)
-STR_8011_CS_2400_DIESEL :CS 2400 (Diisel)
-STR_8012_CENTENNIAL_DIESEL :Centennial (Diisel)
-STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diisel)
-STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diisel)
-STR_8015_MJS_1000_DIESEL :MJS 1000 (Diisel)
-STR_8016_SH_125_DIESEL :SH '125' (Diisel)
-STR_8017_SH_30_ELECTRIC :SH '30' (Elektrivedur)
-STR_8018_SH_40_ELECTRIC :SH '40' (Elektrivedur)
-STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektrivedur)
-STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektrivedur)
+STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymoveri tšuhh-tšuhh
+STR_8005_PLODDYPHUT_DIESEL :Ploddyphut diisel
+STR_8006_POWERNAUT_DIESEL :Powernaut diisel
+STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (auruvedur)
+STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (auruvedur)
+STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (auruvedur)
+STR_800A_SH_8P_STEAM :SH '8P' (auruvedur)
+STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (diisel)
+STR_800C_DASH_DIESEL :'Dash' (diisel)
+STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (diisel)
+STR_800E_UU_37_DIESEL :UU '37' (diisel)
+STR_800F_FLOSS_47_DIESEL :Floss '47' (diisel)
+STR_8010_CS_4000_DIESEL :CS 4000 (diisel)
+STR_8011_CS_2400_DIESEL :CS 2400 (diisel)
+STR_8012_CENTENNIAL_DIESEL :Centennial (diisel)
+STR_8013_KELLING_3100_DIESEL :Kelling 3100 (diisel)
+STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (diisel)
+STR_8015_MJS_1000_DIESEL :MJS 1000 (diisel)
+STR_8016_SH_125_DIESEL :SH '125' (diisel)
+STR_8017_SH_30_ELECTRIC :SH '30' (elektrivedur)
+STR_8018_SH_40_ELECTRIC :SH '40' (elektrivedur)
+STR_8019_T_I_M_ELECTRIC :'T.I.M.' (elektrivedur)
+STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (elektrivedur)
STR_801B_PASSENGER_CAR :Reisivagun
STR_801C_MAIL_VAN :Postivagun
-STR_801D_COAL_CAR :Söevagun
+STR_801D_COAL_CAR :Kivisöevagun
STR_801E_OIL_TANKER :Naftatanker
-STR_801F_LIVESTOCK_VAN :Kariloomade veok
+STR_801F_LIVESTOCK_VAN :Loomavagun
STR_8020_GOODS_VAN :Kaubavagun
STR_8021_GRAIN_HOPPER :Teraviljavagun
-STR_8022_WOOD_TRUCK :Puiduveok
-STR_8023_IRON_ORE_HOPPER :Rauamaagi vagun
-STR_8024_STEEL_TRUCK :Teraseveok
+STR_8022_WOOD_TRUCK :Palgivagun
+STR_8023_IRON_ORE_HOPPER :Rauamaagivagun
+STR_8024_STEEL_TRUCK :Terasevagun
STR_8025_ARMORED_VAN :Soomusvagun
STR_8026_FOOD_VAN :Toiduvagun
STR_8027_PAPER_TRUCK :Paberivagun
-STR_8028_COPPER_ORE_HOPPER :Vasemaagi vagun
-STR_8029_WATER_TANKER :Vee Tanker
+STR_8028_COPPER_ORE_HOPPER :Vasemaagivagun
+STR_8029_WATER_TANKER :Veetanker
STR_802A_FRUIT_TRUCK :Puuviljavagun
STR_802B_RUBBER_TRUCK :Kummivagun
STR_802C_SUGAR_TRUCK :Suhkruvagun
-STR_802D_COTTON_CANDY_HOPPER :Suhkruvati vagun
+STR_802D_COTTON_CANDY_HOPPER :Suhkruvativagun
STR_802E_TOFFEE_HOPPER :Iirisevagun
STR_802F_BUBBLE_VAN :Mullivagun
STR_8030_COLA_TANKER :Koolavagun
@@ -2366,167 +2367,167 @@
STR_8032_TOY_VAN :Mänguasjavagun
STR_8033_BATTERY_TRUCK :Patareivagun
STR_8034_FIZZY_DRINK_TRUCK :Kihisevate jookide vagun
-STR_8035_PLASTIC_TRUCK :Plastiku vagun
-STR_8036_X2001_ELECTRIC :'X2001' (Elektri)
-STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektri)
+STR_8035_PLASTIC_TRUCK :Plastikuvagun
+STR_8036_X2001_ELECTRIC :'X2001' (elektri)
+STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (elektri)
STR_8038_WIZZOWOW_Z99 :Wizzowow Z99
STR_8039_PASSENGER_CAR :Reisivagun
STR_803A_MAIL_VAN :Postivagun
-STR_803B_COAL_CAR :Kivisöe vagun
+STR_803B_COAL_CAR :Kivisöevagun
STR_803C_OIL_TANKER :Naftatanker
-STR_803D_LIVESTOCK_VAN :Kariloomade vagun
+STR_803D_LIVESTOCK_VAN :Loomavagun
STR_803E_GOODS_VAN :Kaubavagun
-STR_803F_GRAIN_HOPPER :Teravilja vagun
-STR_8040_WOOD_TRUCK :Puidu vagun
-STR_8041_IRON_ORE_HOPPER :Rauamaagi vagun
-STR_8042_STEEL_TRUCK :Terase vagun
+STR_803F_GRAIN_HOPPER :Teraviljavagun
+STR_8040_WOOD_TRUCK :Palgivagun
+STR_8041_IRON_ORE_HOPPER :Rauamaagivagun
+STR_8042_STEEL_TRUCK :Terasevagun
STR_8043_ARMORED_VAN :Soomusvagun
-STR_8044_FOOD_VAN :Toidu vagun
-STR_8045_PAPER_TRUCK :Paberi vagun
-STR_8046_COPPER_ORE_HOPPER :Vasemaagi vagun
-STR_8047_WATER_TANKER :Vee Tanker
-STR_8048_FRUIT_TRUCK :Puuvilja vagun
-STR_8049_RUBBER_TRUCK :Kummi vagun
+STR_8044_FOOD_VAN :Toiduvagun
+STR_8045_PAPER_TRUCK :Paberivagun
+STR_8046_COPPER_ORE_HOPPER :Vasemaagivagun
+STR_8047_WATER_TANKER :Veetanker
+STR_8048_FRUIT_TRUCK :Puuviljavagun
+STR_8049_RUBBER_TRUCK :Kummivagun
STR_804A_SUGAR_TRUCK :Suhkruvagun
-STR_804B_COTTON_CANDY_HOPPER :Suhkruvati vagun
-STR_804C_TOFFEE_HOPPER :Iirise vagun
+STR_804B_COTTON_CANDY_HOPPER :Suhkruvativagun
+STR_804C_TOFFEE_HOPPER :Iirisevagun
STR_804D_BUBBLE_VAN :Mullivagun
STR_804E_COLA_TANKER :Koolatanker
-STR_804F_CANDY_VAN :Maiustuste vagun
-STR_8050_TOY_VAN :Mänguasjade vagun
+STR_804F_CANDY_VAN :Maiustustevagun
+STR_8050_TOY_VAN :Mänguasjavagun
STR_8051_BATTERY_TRUCK :Patareivagun
STR_8052_FIZZY_DRINK_TRUCK :Kihisevate jookide vagun
-STR_8053_PLASTIC_TRUCK :Plastiku vagun
-STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektri)
-STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektri)
-STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektri)
-STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektri)
+STR_8053_PLASTIC_TRUCK :Plastikuvagun
+STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (elektri)
+STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (elektri)
+STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (elektri)
+STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (elektri)
STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer
STR_8059_PASSENGER_CAR :Reisivagun
STR_805A_MAIL_VAN :Postivagun
-STR_805B_COAL_CAR :Kivisöe vagun
+STR_805B_COAL_CAR :Kivisöevagun
STR_805C_OIL_TANKER :Naftatanker
-STR_805D_LIVESTOCK_VAN :Kariloomade vagun
+STR_805D_LIVESTOCK_VAN :Loomavagun
STR_805E_GOODS_VAN :Kaubavagun
-STR_805F_GRAIN_HOPPER :Teravilja vagun
-STR_8060_WOOD_TRUCK :Puidu vagun
-STR_8061_IRON_ORE_HOPPER :Rauamaagi vagun
-STR_8062_STEEL_TRUCK :Terase vagun
+STR_805F_GRAIN_HOPPER :Teraviljavagun
+STR_8060_WOOD_TRUCK :Palgivagun
+STR_8061_IRON_ORE_HOPPER :Rauamaagivagun
+STR_8062_STEEL_TRUCK :Terasevagun
STR_8063_ARMORED_VAN :Soomusvagun
STR_8064_FOOD_VAN :Toiduvagun
STR_8065_PAPER_TRUCK :Paberivagun
-STR_8066_COPPER_ORE_HOPPER :Vasemaagi vagun
+STR_8066_COPPER_ORE_HOPPER :Vasemaagivagun
STR_8067_WATER_TANKER :Veetanker
-STR_8068_FRUIT_TRUCK :Puuvilja vagun
+STR_8068_FRUIT_TRUCK :Puuviljavagun
STR_8069_RUBBER_TRUCK :Kummivagun
STR_806A_SUGAR_TRUCK :Suhkruvagun
-STR_806B_COTTON_CANDY_HOPPER :Suhkruvati vagun
-STR_806C_TOFFEE_HOPPER :Iirise vagun
+STR_806B_COTTON_CANDY_HOPPER :Suhkruvativagun
+STR_806C_TOFFEE_HOPPER :Iirisevagun
STR_806D_BUBBLE_VAN :Mullivagun
-STR_806E_COLA_TANKER :Koola Tanker
-STR_806F_CANDY_VAN :Maiustuste vagun
+STR_806E_COLA_TANKER :Koolatanker
+STR_806F_CANDY_VAN :Maiustustevagun
STR_8070_TOY_VAN :Mänguasjavagun
-STR_8071_BATTERY_TRUCK :Patareide vagun
+STR_8071_BATTERY_TRUCK :Patareivagun
STR_8072_FIZZY_DRINK_TRUCK :Kihisevate jookide vagun
-STR_8073_PLASTIC_TRUCK :Plastiku vagun
-STR_8074_MPS_REGAL_BUS :MPS Kuninglik Buss
-STR_8075_HEREFORD_LEOPARD_BUS :Herefordi Leopardi Buss
-STR_8076_FOSTER_BUS :Foster Buss
-STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbuss
-STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Buss
-STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Buss
-STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Buss
-STR_807B_BALOGH_COAL_TRUCK :Balogh Söe Veok
-STR_807C_UHL_COAL_TRUCK :Uhl Söe Veok
-STR_807D_DW_COAL_TRUCK :DW Söe Veok
-STR_807E_MPS_MAIL_TRUCK :MPS Postiauto
-STR_807F_REYNARD_MAIL_TRUCK :Reynard Postiauto
-STR_8080_PERRY_MAIL_TRUCK :Perry Postiauto
-STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Postiauto
-STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Postiauto
-STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Postiauto
+STR_8073_PLASTIC_TRUCK :Plastikuvagun
+STR_8074_MPS_REGAL_BUS :Kuninglik MPS buss
+STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard buss
+STR_8076_FOSTER_BUS :Foster buss
+STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII superbuss
+STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI buss
+STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII buss
+STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII buss
+STR_807B_BALOGH_COAL_TRUCK :Balogh kivisöeveok
+STR_807C_UHL_COAL_TRUCK :Uhl kivisõeveok
+STR_807D_DW_COAL_TRUCK :DW kivisõeveok
+STR_807E_MPS_MAIL_TRUCK :MPS postiauto
+STR_807F_REYNARD_MAIL_TRUCK :Reynard postiauto
+STR_8080_PERRY_MAIL_TRUCK :Perry postiauto
+STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover postiauto
+STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught postiauto
+STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow postiauto
STR_8084_WITCOMBE_OIL_TANKER :Witcombe naftaveok
STR_8085_FOSTER_OIL_TANKER :Foster naftaveok
STR_8086_PERRY_OIL_TANKER :Perry naftaveok
-STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Karjaveoauto
-STR_8088_UHL_LIVESTOCK_VAN :Uhl Karjaveoauto
-STR_8089_FOSTER_LIVESTOCK_VAN :Foster Karjaveoauto
-STR_808A_BALOGH_GOODS_TRUCK :Balogh Kaubaveoauto
-STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Kaubaveoauto
-STR_808C_GOSS_GOODS_TRUCK :Goss Kaubaveoauto
-STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Viljaveoauto
-STR_808E_THOMAS_GRAIN_TRUCK :Thomas Viljaveoauto
-STR_808F_GOSS_GRAIN_TRUCK :Goss Viljaveoauto
-STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Puiduveoauto
-STR_8091_FOSTER_WOOD_TRUCK :Foster Puiduveoauto
-STR_8092_MORELAND_WOOD_TRUCK :Moreland Puiduveoauto
-STR_8093_MPS_IRON_ORE_TRUCK :MPS Rauamaagiveoauto
-STR_8094_UHL_IRON_ORE_TRUCK :Uhl Rauamaagiveoauto
-STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Rauamaagiveoauto
-STR_8096_BALOGH_STEEL_TRUCK :Balogh Teraseveoauto
-STR_8097_UHL_STEEL_TRUCK :Uhl Teraseveoauto
-STR_8098_KELLING_STEEL_TRUCK :Kelling Teraseveoauto
-STR_8099_BALOGH_ARMORED_TRUCK :Balogh Soomusauto
-STR_809A_UHL_ARMORED_TRUCK :Uhl Soomusauto
-STR_809B_FOSTER_ARMORED_TRUCK :Foster Soomusauto
-STR_809C_FOSTER_FOOD_VAN :Foster Toiduveoauto
-STR_809D_PERRY_FOOD_VAN :Perry Toiduveoauto
-STR_809E_CHIPPY_FOOD_VAN :Chippy Toiduveoauto
-STR_809F_UHL_PAPER_TRUCK :Uhl Paberiveoauto
-STR_80A0_BALOGH_PAPER_TRUCK :Balogh Paberiveoauto
-STR_80A1_MPS_PAPER_TRUCK :MPS Paberiveoauto
-STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Vasemaagiveoauto
-STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Vasemaagiveoauto
-STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Vasemaagiveoauto
-STR_80A5_UHL_WATER_TANKER :Uhl Veeveoauto
-STR_80A6_BALOGH_WATER_TANKER :Balogh Veeveoauto
-STR_80A7_MPS_WATER_TANKER :MPS Veeveoauto
-STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Veeveoauto
-STR_80A9_UHL_FRUIT_TRUCK :Uhl Puuviljaveoauto
-STR_80AA_KELLING_FRUIT_TRUCK :Kelling Puuviljaveoauto
+STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott loomaveok
+STR_8088_UHL_LIVESTOCK_VAN :Uhl loomaveok
+STR_8089_FOSTER_LIVESTOCK_VAN :Foster loomaveok
+STR_808A_BALOGH_GOODS_TRUCK :Balogh kaubaveok
+STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead kaubaveok
+STR_808C_GOSS_GOODS_TRUCK :Goss kaubaveok
+STR_808D_HEREFORD_GRAIN_TRUCK :Hereford viljaveok
+STR_808E_THOMAS_GRAIN_TRUCK :Thomas viljaveok
+STR_808F_GOSS_GRAIN_TRUCK :Goss viljaveok
+STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe palgiveok
+STR_8091_FOSTER_WOOD_TRUCK :Foster palgiveok
+STR_8092_MORELAND_WOOD_TRUCK :Moreland palgiveok
+STR_8093_MPS_IRON_ORE_TRUCK :MPS rauamaagiveok
+STR_8094_UHL_IRON_ORE_TRUCK :Uhl rauamaagiveok
+STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy rauamaagiveok
+STR_8096_BALOGH_STEEL_TRUCK :Balogh teraseveok
+STR_8097_UHL_STEEL_TRUCK :Uhl teraseveok
+STR_8098_KELLING_STEEL_TRUCK :Kelling teraseveok
+STR_8099_BALOGH_ARMORED_TRUCK :Balogh soomusauto
+STR_809A_UHL_ARMORED_TRUCK :Uhl soomusauto
+STR_809B_FOSTER_ARMORED_TRUCK :Foster soomusauto
+STR_809C_FOSTER_FOOD_VAN :Foster toiduveok
+STR_809D_PERRY_FOOD_VAN :Perry toiduveok
+STR_809E_CHIPPY_FOOD_VAN :Chippy toiduveok
+STR_809F_UHL_PAPER_TRUCK :Uhl paberiveok
+STR_80A0_BALOGH_PAPER_TRUCK :Balogh paberiveok
+STR_80A1_MPS_PAPER_TRUCK :MPS paberiveok
+STR_80A2_MPS_COPPER_ORE_TRUCK :MPS vasemaagiveok
+STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl vasemaagiveok
+STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss vasemaagiveok
+STR_80A5_UHL_WATER_TANKER :Uhl veeveok
+STR_80A6_BALOGH_WATER_TANKER :Balogh veeveok
+STR_80A7_MPS_WATER_TANKER :MPS veeveok
+STR_80A8_BALOGH_FRUIT_TRUCK :Balogh veeveok
+STR_80A9_UHL_FRUIT_TRUCK :Uhl puuviljaveok
+STR_80AA_KELLING_FRUIT_TRUCK :Kelling puuviljaveok
STR_80AB_BALOGH_RUBBER_TRUCK :Balogh kummiveok
STR_80AC_UHL_RUBBER_TRUCK :Uhl kummiveok
STR_80AD_RMT_RUBBER_TRUCK :RMT kummiveok
-STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Suhkruveoauto
-STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Suhkruveoauto
-STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Suhkruveoauto
-STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Koolaveoauto
-STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Koolaveoauto
-STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Koolaveoauto
-STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Suhkruvativeoauto
-STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Suhkruvativeoauto
-STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Suhkruvativeoauto
-STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Iiriseveoauto
-STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Iiriseveoauto
-STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Iiriseveoauto
-STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Mänguasjaveoauto
-STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Mänguasjaveoauto
-STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Mänguasjaveoauto
-STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Maiustusteveoauto
-STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Maiustusteveoauto
-STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Maiustusteveoauto
-STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Patareiveoauto
-STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Patareiveoauto
-STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Patareiveoauto
-STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Limonaadiveoauto
-STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Limonaadiveoauto
-STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Limonaadiveoauto
-STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Plastikuveoauto
-STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Plastikuveoauto
-STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Plastikuveoauto
-STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Mulliveoauto
-STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Mulliveoauto
-STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Mulliveoauto
+STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover suhkruveok
+STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught suhkruveok
+STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow suhkruveok
+STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover koolaveok
+STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught koolaveok
+STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow koolaveok
+STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover suhkruvativeok
+STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught suhkruvativeok
+STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow suhkruvativeok
+STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover iiriseveok
+STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught iiriseveok
+STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow iiriseveok
+STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover mänguasjaveok
+STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught mänguasjaveok
+STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow mänguasjaveok
+STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover maiustusteveok
+STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught maiustusteveok
+STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow maiustusteveok
+STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover patareiveok
+STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught patareiveok
+STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow patareiveok
+STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover limonaadiveok
+STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught limonaadiveok
+STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow limonaadiveok
+STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover plastikuveok
+STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught plastikuveok
+STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow plastikuveok
+STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover mulliveok
+STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught mulliveok
+STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow mulliveok
STR_80CC_MPS_OIL_TANKER :MPS naftatanker
STR_80CD_CS_INC_OIL_TANKER :CS-Inc. naftatanker
-STR_80CE_MPS_PASSENGER_FERRY :MPS Praam
-STR_80CF_FFP_PASSENGER_FERRY :FFP Praam
-STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Hõljuk
-STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Praam
-STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Praam
-STR_80D3_YATE_CARGO_SHIP :Yate Kaubalaev
-STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Kaubalaev
-STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Kaubalaev
+STR_80CE_MPS_PASSENGER_FERRY :MPS reisipraam
+STR_80CF_FFP_PASSENGER_FERRY :FFP reisipraam
+STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 hõljuklaev
+STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug reisipraam
+STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake reisipraam
+STR_80D3_YATE_CARGO_SHIP :Yate kaubalaev
+STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell kaubalaev
+STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover kaubalaev
STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Kaubalaev
STR_80D7_SAMPSON_U52 :Sampson U52
STR_80D8_COLEMAN_COUNT :Coleman Count
@@ -2580,7 +2581,7 @@
##id 0x8800
STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Rongi Depoo
-STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab. . .{}Esimene rong saabus {STATION} jaama!
+STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab. . .{}{STATION} jaama saabus esimene rong!
STR_8802_DETAILS :{WHITE}{STRING} (Detailid)
STR_8803_TRAIN_IN_THE_WAY :{WHITE}Rong on ees
STR_8804 :{SETX 10}{COMMA}: {STRING} {STRING}
@@ -2595,15 +2596,15 @@
STR_880D_GO_TO_NON_STOP_TRANSFER :Sõida läbi {STATION} (Vea ja oota täislaadingut)
STR_880E_GO_NON_STOP_TO_UNLOAD :Sõida läbi {STATION} (Laadi maha)
STR_880F_GO_TO_NON_STOP_TRANSFER_UNLOAD :Sõida läbi {STATION} (Vea ja jäta tühjaks)
-STR_8810_GO_NON_STOP_TO_LOAD :Sõida läbi {STATION} (Lae)
+STR_8810_GO_NON_STOP_TO_LOAD :Sõida läbi {STATION} (laadi)
STR_8811_GO_TO_NON_STOP_TRANSFER_LOAD :Sõida läbi {STATION} (Vea ja oota täislaadingut)
-STR_GO_TO_TRAIN_DEPOT :Mine {TOWN} Rongidepoosse
+STR_GO_TO_TRAIN_DEPOT :Mine linna {TOWN} rongidepoosse
STR_SERVICE_AT_TRAIN_DEPOT :Hooldus linna {TOWN} rongidepoos
-STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Sõida läbi {TOWN} Rongidepoo
-STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Hooldus Läbisõidul läbi {TOWN} Rongidepoo
+STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Sõida läbi linna {TOWN} rongidepoo
+STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Hooldus Läbisõidul läbi linna {TOWN} rongidepoo
-STR_HEADING_FOR_TRAIN_DEPOT :{ORANGE}Suundub {TOWN} Rongidepoosse
-STR_HEADING_FOR_TRAIN_DEPOT_VEL :{ORANGE}Suundub {TOWN} Rongidepoosse, {VELOCITY}
+STR_HEADING_FOR_TRAIN_DEPOT :{ORANGE}Suundub linna {TOWN} rongidepoosse
+STR_HEADING_FOR_TRAIN_DEPOT_VEL :{ORANGE}Suundub linna {TOWN} rongidepoosse, {VELOCITY}
STR_HEADING_FOR_TRAIN_DEPOT_SERVICE :{LTBLUE}Parandus{TOWN} Rongijaamas
STR_HEADING_FOR_TRAIN_DEPOT_SERVICE_VEL :{LTBLUE}Parandus {TOWN} Rongijaamas, {VELOCITY}
@@ -2633,13 +2634,13 @@
STR_CLONE_TRAIN :{BLACK}Klooni rong
STR_CLONE_TRAIN_INFO :{BLACK}See ehitab koopia rongist koos kõikide vagunitega. CTRL-klikk jagab sihtpunkte
STR_CLONE_TRAIN_DEPOT_INFO :{BLACK}See ehitab koopia rongist koos kõikide vagunitega. Vajuta sellele nuppule, ning seejärel rongile depoo sees või väljas. CTRL-klikk jagab sihtpunkte
-STR_8820_RENAME :{BLACK}Nimeta ümber
+STR_8820_RENAME :{BLACK}Muuda nime
STR_8823_SKIP :{BLACK}Jäta vahele
STR_8824_DELETE :{BLACK}Kustuta
STR_8825_NON_STOP :{BLACK}Peatuseta
STR_8826_GO_TO :{BLACK}Mine
-STR_8827_FULL_LOAD :{BLACK}Täis laadung
-STR_8828_UNLOAD :{BLACK}Lae maha
+STR_8827_FULL_LOAD :{BLACK}Laadi täis
+STR_8828_UNLOAD :{BLACK}Laadi maha
STR_REFIT :{BLACK}Taasseadista
STR_REFIT_TIP :{BLACK}Vali, millist laadungit ümber seadistada selles järjestuses. Ümberseadistuse käsu eemaldamiseks hoia klõpsamise ajal all Control nuppu
STR_REFIT_ORDER :(Taasseadista {STRING})
@@ -2651,8 +2652,8 @@
STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Ehitatud: {LTBLUE}{NUM}{BLACK} Väärtus: {LTBLUE}{CURRENCY}
STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Väärtus: {LTBLUE}{CURRENCY}
STR_882E :{WHITE}{VEHICLE}
-STR_882F_LOADING_UNLOADING :{LTBLUE}Laen / Laen maha
-STR_TRAIN_MUST_BE_STOPPED :{WHITE}Rong peab olema depoos peatutud
+STR_882F_LOADING_UNLOADING :{LTBLUE}Laadin / Laadin maha
+STR_TRAIN_MUST_BE_STOPPED :{WHITE}Rong peab olema depoos peatatud
STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Ei saa saata rongi depoosse...
STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Pole ruumi käskudeks
STR_8832_TOO_MANY_ORDERS :{WHITE}Liiga palju käske
@@ -2675,7 +2676,7 @@
STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Keskenda põhivaade rongidepoo kohale
STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Rongivagunite nimekiri - vajuta sõidukile info jaoks
STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Ehita valitud rongi sõiduk
-STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Nimeta ümber rongisõiduki tüüp
+STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Muuda rongisõiduki tüübi nime
STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Praegune rongi tegevus - vajuta siia et peatada/käivitada rong
STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Näita rongi käske
STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Vaate viimine rongi asukohale
@@ -2715,7 +2716,7 @@
STR_8867_NAME_TRAIN :{BLACK}Rongi nimi
STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}RONGIKOKKUPÕRGE!{}{COMMA} surid tules peale kokkusõitmist
STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Ei saa rongi ümber pöörata.
-STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Nimeta ümber rongisõiduki tüüp
+STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Muuda rongisõiduki tüübi nime
STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Ei saa nimetada ümber rongisõiduki tüüpi...
STR_886D_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Sunni valitud käsul visata maha laadung
STR_886F_TRANSFER :{BLACK}Transpordi
@@ -2730,7 +2731,7 @@
STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Maanteesõiduk on ees
STR_9001_ROAD_VEHICLES :{WHITE}{COMPANY} - {COMMA} Maanteesõiduk{P "" s}
STR_9002 :{WHITE}{VEHICLE}
-STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Maanteesõiduki depoo
+STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}Linna {TOWN} maanteesõidukite depoo
STR_9004_NEW_VEHICLES :{BLACK}Uued sõidukid
STR_9006_NEW_ROAD_VEHICLES :{WHITE}Uued maanteesõidukid
STR_9007_BUILD_VEHICLE :{BLACK}Ehita sõidukeid
@@ -2773,13 +2774,13 @@
STR_902C_NAME_ROAD_VEHICLE :{WHITE}Nimeta maanteeveok ümber
STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Ei saa maanteveokit ümber nimetada...
STR_902E_NAME_ROAD_VEHICLE :{BLACK}Nimeta maanteeveok ümber
-STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}Esimene buss saabus {STATION} jaama!
-STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}Esimene maanteesõiduk saabus {STATION} jaama!
+STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}{STATION} jaama saabus esimene buss!
+STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}{STATION} jaama saabus esimene maanteesõiduk!
STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Rongikokkupõrge!{}Juht suri peale õnnetust tules
STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Maanteesõiduki kokkupõrge rongiga!{}{COMMA} suri tules peale kokkupõrget rongiga
STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Maanteesõidukit ei saa ringi pöörata...
STR_ONLY_TURN_SINGLE_UNIT :{WHITE}Sa ei saa pöörata sõidukeid millel on mitu üksust
-STR_9034_RENAME :{BLACK}Nimeta ümber
+STR_9034_RENAME :{BLACK}Muuda nime
STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Nimeta maanteesõiduki tüüp ümber
STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Nimeta maanteesõiduki tüüp ümber
STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Ei saa nimetada ümber maanteesõiduki tüüpi...
@@ -2787,9 +2788,9 @@
STR_SERVICE_AT_ROADVEH_DEPOT :Hoolda {TOWN} Garaaþis
STR_REFIT_ROAD_VEHICLE_TO_CARRY :{BLACK}Seadista maanteesõidukit kandma teist tüüpi laadungit
-STR_REFIT_ROAD_VEHICLE :{BLACK}Seadista maantee sõiduk ümber
+STR_REFIT_ROAD_VEHICLE :{BLACK}Muuda maanteesõiduki seadistust
STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED :{BLACK}Seadista maanteesõiduk kandma valitud laadungitüüpi
-STR_REFIT_ROAD_VEHICLE_CAN_T :{WHITE}Ei saa seadistada maantee sõidukit ümber
+STR_REFIT_ROAD_VEHICLE_CAN_T :{WHITE}Maanteesõiduki seadistust ei saa ümber muuta
STR_ROAD_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Vali, millist tüüpi laadungit sõiduk veab
##id 0x9800
@@ -2832,7 +2833,7 @@
STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Vii pea vaade paadikuuri juurde
STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Laevad - info saamiseks vajuta laevale
STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Ehita uus laev (vajad paadikuuri)
-STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Laeva valimisnimekiri - info saamiseks vajuta laevale
+STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Laevade nimekiri - info saamiseks vajuta laevale
STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Ehita valitud laev
STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Praegune laeva tegevus - vajuta siia, et peatada/käivitada laeva
STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Näita laeva sihtpunkte
@@ -2846,10 +2847,10 @@
STR_9831_NAME_SHIP :{WHITE}Anna laevale nimi
STR_9832_CAN_T_NAME_SHIP :{WHITE}Ei saa laeva ümber nimetada...
-STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}Esimene laev saabus {STATION} sadamasse!
+STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}{STATION} sadamasse saabus esimene laev!
STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Aseta teemärgisena kasutatav poi
STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Poid ei saa siia asetada...
-STR_9836_RENAME :{BLACK}Nimeta ümber
+STR_9836_RENAME :{BLACK}Muuda nime
STR_9837_RENAME_SHIP_TYPE :{BLACK}Nimeta laeva tüüp ümber
STR_9838_RENAME_SHIP_TYPE :{WHITE}Nimeta laeva tüüp ümber
STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Ei saa laeva tüüpi ümber nimetada...
@@ -2878,7 +2879,7 @@
STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Ei saa ehitada lennukit...
STR_A009_AIRCRAFT :{WHITE}{COMPANY} - {COMMA} Lennuk
STR_A00A :{WHITE}{VEHICLE}
-STR_A00B_ORDERS :{WHITE}{VEHICLE} (Sihtpunktid)
+STR_A00B_ORDERS :{WHITE}{VEHICLE} (sihtpunktid)
STR_A00C_DETAILS :{WHITE}{VEHICLE} (Detailid)
STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Vanus: {LTBLUE}{STRING}{BLACK} Hoolduskulud: {LTBLUE}{CURRENCY}/aastas
STR_A00E_MAX_SPEED :{BLACK}Maks. kiirus: {LTBLUE}{VELOCITY}
@@ -2920,11 +2921,11 @@
STR_A030_NAME_AIRCRAFT :{WHITE}Anna lennukile nimi
STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Ei saa lennukile nime anda
STR_A032_NAME_AIRCRAFT :{BLACK}Nimeta lennuk ümber
-STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}Esimene lennuk saabub {STATION}i!
+STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Rahvas rõõmustab . . .{}{STATION} lennujaama saabus esimene lennuk!
STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Lennuõnnetus!{}{COMMA} surid tules {STATION}s
STR_PLANE_CRASH_OUT_OF_FUEL :{BLACK}{BIGFONT}Lennuõnnetus!{}Lennukil lõppes kütus, {COMMA} surid tules!
STR_A036 :{TINYFONT}{BLACK}{STATION}
-STR_A037_RENAME :{BLACK}Nimeta ümber
+STR_A037_RENAME :{BLACK}Muuda nime
STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Nimeta lennuki tüüp ümber
STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Nimeta lennuki tüüp ümber
STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Ei saa lennuki tüüpi ümber nimetada...
@@ -3090,7 +3091,7 @@
STR_MASS_STOP_DEPOT_TRAIN_TIP :{BLACK}Vajuta, kui tahad seisata kõiki ronge jaamas
STR_MASS_STOP_DEPOT_ROADVEH_TIP :{BLACK}Vajuta, kui tahad seisata kõiki masinaid garaažis
-STR_MASS_STOP_DEPOT_SHIP_TIP :{BLACK}Vajuta, kui tahad seisata kõiki laevu sadamas
+STR_MASS_STOP_DEPOT_SHIP_TIP :{BLACK}Klõpsa, et peatada kõik sadamas olevad laevad.
STR_MASS_STOP_HANGAR_TIP :{BLACK}Vajuta, kui tahad seisata kõiki lennukeid angaaris
STR_MASS_START_DEPOT_TRAIN_TIP :{BLACK}Klõpsa kõikide depoos asuvate rongide käivitamiseks
@@ -3120,14 +3121,14 @@
STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}Maksuvus: {GOLD}{CURRENCY}{BLACK} Kaal: {GOLD}{WEIGHT_S}
STR_PURCHASE_INFO_SPEED_POWER :{BLACK}Kiirus: {GOLD}{VELOCITY}{BLACK} Võimsus: {GOLD}{POWER}
STR_PURCHASE_INFO_SPEED :{BLACK}Kiirus: {GOLD}{VELOCITY}
-STR_PURCHASE_INFO_RUNNINGCOST :{BLACK}Hoodluskulud: {GOLD}{CURRENCY}/aasta
-STR_PURCHASE_INFO_CAPACITY :{BLACK}Mahutuvus: {GOLD}{CARGO} {STRING}
+STR_PURCHASE_INFO_RUNNINGCOST :{BLACK}Hoolduskulud: {GOLD}{CURRENCY}/aasta
+STR_PURCHASE_INFO_CAPACITY :{BLACK}Mahutavus: {GOLD}{CARGO} {STRING}
STR_PURCHASE_INFO_DESIGNED_LIFE :{BLACK}Kujundatud: {GOLD}{NUM}{BLACK} Vanus: {GOLD}{COMMA} aastat
STR_PURCHASE_INFO_RELIABILITY :{BLACK}Suurim töökindlus: {GOLD}{COMMA}%
STR_PURCHASE_INFO_COST :{BLACK}Maksuvus: {GOLD}{CURRENCY}
STR_PURCHASE_INFO_WEIGHT_CWEIGHT :{BLACK}Kaal: {GOLD}{WEIGHT_S} ({WEIGHT_S})
STR_PURCHASE_INFO_COST_SPEED :{BLACK}Maksumus: {GOLD}{CURRENCY}{BLACK} Kiirus: {GOLD}{VELOCITY}
-STR_PURCHASE_INFO_AIRCRAFT_CAPACITY :{BLACK}Mahutuvusy: {GOLD}{COMMA} reisjat, {COMMA} kotti kirju
+STR_PURCHASE_INFO_AIRCRAFT_CAPACITY :{BLACK}Mahutavus: {GOLD}{COMMA} reisijat, {COMMA} kotti kirju
STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Kiirendavad vagunid: {GOLD}+{POWER}{BLACK} Kaal: {GOLD}+{WEIGHT_S}
STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Ümberseadistatav: {GOLD}
STR_PURCHASE_INFO_ALL_TYPES :Kõik kaubatüübid
--- a/lang/finnish.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/finnish.txt Wed Jan 03 08:32:17 2007 +0000
@@ -154,11 +154,12 @@
STR_00B1_GAME_OPTIONS :{WHITE}Pelin asetukset
STR_00B2_MESSAGE :{YELLOW}Viesti
STR_00B3_MESSAGE_FROM :{YELLOW}Viesti: {STRING}
+STR_POPUP_CAUTION_CAPTION :{WHITE}Varoitus!
STR_00B4_CAN_T_DO_THIS :{WHITE}Ei onnistu....
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Aluetta ei voi tyhjentää....
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Alkuperäiset oikeudet {COPYRIGHT} 1995 Chris Sawyer, kaikki oikeudet pidätetään
STR_00B7_VERSION :{BLACK}OpenTTD-versio {REV}
-STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2006 OpenTTD-yhteisö
+STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2006 The OpenTTD team
STR_TRANSLATED_BY :{BLACK} Kääntäjä(t) -
STR_00C5 :{BLACK}{CROSS}
@@ -166,7 +167,7 @@
STR_00C7_QUIT :{WHITE}Sulje
STR_00C8_YES :{BLACK}Kyllä
STR_00C9_NO :{BLACK}Ei
-STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Hylätäänkö peli ja palataan {STRING}-järjestelmään?
+STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Lopetetaanko peli ja palataan {STRING}-järjestelmään?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
@@ -201,21 +202,21 @@
STR_00EA_OWNERS :Omistajat
STR_00EB_ROADS :{BLACK}{TINYFONT}Tie
STR_00EC_RAILROADS :{BLACK}{TINYFONT}Rautatie
-STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Asema/lentokenttä/satama
+STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Asemat/lentokentät/satamat
STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Rakennus
-STR_00EF_VEHICLES :{BLACK}{TINYFONT}Liikenneväline
+STR_00EF_VEHICLES :{BLACK}{TINYFONT}Liikennevälineet
STR_00F0_100M :{BLACK}{TINYFONT}100 m
STR_00F1_200M :{BLACK}{TINYFONT}200 m
STR_00F2_300M :{BLACK}{TINYFONT}300 m
STR_00F3_400M :{BLACK}{TINYFONT}400 m
STR_00F4_500M :{BLACK}{TINYFONT}500 m
-STR_00F5_TRAINS :{BLACK}{TINYFONT}Juna
-STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Ajoneuvo
-STR_00F7_SHIPS :{BLACK}{TINYFONT}Laiva
-STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Lentokone
-STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Kuljetusreitti
+STR_00F5_TRAINS :{BLACK}{TINYFONT}Junat
+STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Ajoneuvot
+STR_00F7_SHIPS :{BLACK}{TINYFONT}Laivat
+STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Lentokoneet
+STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Kuljetusreitit
STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Hiilikaivos
-STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Sähkölaitos
+STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Voimala
STR_00FC_FOREST :{BLACK}{TINYFONT}Metsä
STR_00FD_SAWMILL :{BLACK}{TINYFONT}Saha
STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Öljynjalostamo
@@ -229,7 +230,7 @@
STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Paperitehdas
STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Kultakaivos
STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Ruoanjalostamo
-STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}timanttikaivos
+STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Timanttikaivos
STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Kuparikaivos
STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Hedelmäviljelmä
STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Kumiviljelmä
@@ -242,7 +243,7 @@
STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Limsakenttä
STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Lelukauppa
STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Lelutehdas
-STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Muovikaivo
+STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Muovilähde
STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Sihijuomatehdas
STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Kuplageneraattori
STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Toffeelouhos
@@ -269,8 +270,8 @@
STR_012E_CANCEL :{BLACK}Peruuta
STR_012F_OK :{BLACK}OK
STR_0130_RENAME :{BLACK}Nimeä uud.
-STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Liian monta nimeä määritelty.
-STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Nimi on jo käytössä.
+STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Liian monta nimeä määritelty
+STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Nimi on jo käytössä
STR_0133_WINDOWS :Windows
STR_0134_UNIX :Unix
@@ -282,7 +283,7 @@
STR_013B_OWNED_BY :{WHITE}...omistaja: {STRING}
STR_013C_CARGO :{BLACK}Rahti
-STR_013D_INFORMATION :{BLACK}Tietoja
+STR_013D_INFORMATION :{BLACK}Tietoa
STR_013E_CAPACITIES :{BLACK}Kapasiteetit
STR_013E_TOTAL_CARGO :{BLACK}Rahtia yhteensä
STR_013F_CAPACITY :{BLACK}Kapaisteetti: {LTBLUE}{CARGO}
@@ -308,7 +309,7 @@
STR_0150_SOMEONE :joku{SKIP}{SKIP}
STR_0151_MAP_OF_WORLD :Maailmankartta
STR_0152_TOWN_DIRECTORY :Kaupunkihakemisto
-STR_0153_SUBSIDIES :Tukitarjoukset
+STR_0153_SUBSIDIES :Tukiaiset
STR_UNITS_IMPERIAL :Englantilainen
STR_UNITS_METRIC :Metrinen
@@ -343,17 +344,17 @@
STR_UNITS_FORCE_SI :{COMMA} kN
############ range for menu starts
-STR_0154_OPERATING_PROFIT_GRAPH :Käyttökatekuvaaja
-STR_0155_INCOME_GRAPH :Ansiotulon kuvaaja
-STR_0156_DELIVERED_CARGO_GRAPH :Kuljetetun rahdin kuvaaja
-STR_0157_PERFORMANCE_HISTORY_GRAPH :Suoritehistoriakuvaaja
-STR_0158_COMPANY_VALUE_GRAPH :Yhtiön arvon kuvaaja
+STR_0154_OPERATING_PROFIT_GRAPH :Liikevoitto
+STR_0155_INCOME_GRAPH :Tulot
+STR_0156_DELIVERED_CARGO_GRAPH :Kuljetettu rahti
+STR_0157_PERFORMANCE_HISTORY_GRAPH :Suoritehistoria
+STR_0158_COMPANY_VALUE_GRAPH :Yhtiön arvo
STR_0159_CARGO_PAYMENT_RATES :Rahtimaksutaksat
STR_015A_COMPANY_LEAGUE_TABLE :Yhtiökilpataulukko
STR_PERFORMANCE_DETAIL_MENU :Suoritearviointi
############ range for menu ends
-STR_015B_OPENTTD :{WHITE}Tietoja OpenTTD:stä
+STR_015B_OPENTTD :{WHITE}Tietoa OpenTTD:stä
STR_015C_SAVE_GAME :Tallenna peli
STR_015D_LOAD_GAME :Lataa peli
STR_015E_QUIT_GAME :Lopeta peli
@@ -393,7 +394,14 @@
STR_NO_WAITING_CARGO :{BLACK}Minkäänlaista lastia ei ole odottamassa
STR_SELECT_ALL_FACILITIES :{BLACK}Valitse kaikki laitteet
STR_SELECT_ALL_TYPES :{BLACK}Valitse kaikki lastityypit (myös odottava lasti)
+STR_MANAGE_LIST :{BLACK}Muokkaa listaa
+STR_MANAGE_LIST_TIP :{BLACK}Ohjaa kaikkia listan ajoneuvoja
STR_REPLACE_VEHICLES :Korvaa liikennevälineitä
+STR_SEND_TRAIN_TO_DEPOT :Lähetä varikolle
+STR_SEND_ROAD_VEHICLE_TO_DEPOT :Lähetä varikolle
+STR_SEND_SHIP_TO_DEPOT :Lähetä varikolle
+STR_SEND_AIRCRAFT_TO_HANGAR :Lähetä varikolle
+STR_SEND_FOR_SERVICING :Lähetä huollettavaksi
############ range for months starts
STR_0162_JAN :01.
@@ -417,7 +425,7 @@
STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Pelin tallennus, hylkääminen ja lopetus.
STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Näytä luettelo yhtiön asemista.
STR_0174_DISPLAY_MAP :{BLACK}Näytä kartta.
-STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Näytä kartta, kaupunkihakemisto
+STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Näytä kartta, kaupunkihakemisto.
STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Näytä kaupunkihakemisto.
STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Näytä yhtiön taloustiedot.
STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Näytä yhtiön yleiset tiedot.
@@ -438,7 +446,7 @@
STR_0187_OPTIONS :{BLACK}Asetukset
STR_0188 :{BLACK}{SMALLUPARROW}
STR_0189 :{BLACK}{SMALLDOWNARROW}
-STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Huoltoväliä ei voi muuttaa...
+STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Huoltoväliä ei voi muuttaa.
STR_018B_CLOSE_WINDOW :{BLACK}Sulje ikkuna
STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Ikkunan otsake - vedä tästä siirtääksesi ikkunaa
STR_STICKY_BUTTON :{BLACK}Merkitse ikkuna tahmeaksi; 'Sulje kaikki ikkunat'-nappi ei vaikuta tahmeisiin ikkunoihin.
@@ -468,11 +476,11 @@
STR_019E_SHIP :Laiva
STR_019F_TRAIN :Juna
STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA} vanhenee.
-STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA} on kohta todella vanha.
-STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} on kohta todella vanha ja pitää pikaisesti korvata.
+STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA} on todella vanha.
+STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} on todella vanha ja täytyy korvata pikaisesti.
STR_01A3_LAND_AREA_INFORMATION :{WHITE}Maa-aluetiedot
-STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Puhdistuksen kustannus: {LTBLUE}-
-STR_01A5_COST_TO_CLEAR :{BLACK}Puhdistuksen kustannus: {LTBLUE}{CURRENCY}
+STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Puhdistuksen hinta: {LTBLUE}-
+STR_01A5_COST_TO_CLEAR :{BLACK}Puhdistuksen hinta: {LTBLUE}{CURRENCY}
STR_01A6_N_A :-
STR_01A7_OWNER :{BLACK}Omistaja: {LTBLUE}{STRING}
STR_01A8_LOCAL_AUTHORITY :{BLACK}Kunta: {LTBLUE}{STRING}
@@ -521,7 +529,7 @@
STR_01D1_8 :({COMMA}/8 {STRING})
STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz-jukeboksi
STR_01D3_SOUND_MUSIC :Ääni/musiikki
-STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Näytä ääniasetukset.
+STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Näytä ääni- ja musiikkiasetukset
STR_01D5_ALL :{TINYFONT}Kaikki
STR_01D6_OLD_STYLE :{TINYFONT}Vanha tyyli
STR_01D7_NEW_STYLE :{TINYFONT}Uusi tyyli
@@ -535,7 +543,7 @@
STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Hyppää seuraavaan raitaan.
STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Pysäytä musiikki.
STR_01E1_START_PLAYING_MUSIC :{BLACK}Aloita musiikki.
-STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Aseta liukusäätimiä vetämällä sopiva äänenvoimakkuus musiikille ja äänitehosteille.
+STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Aseta liukusäätimillä sopiva äänenvoimakkuus musiikille ja tehosteille.
STR_01E3 :{DKGREEN}{TINYFONT}--
STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA}
STR_01E5 :{DKGREEN}{TINYFONT}{COMMA}
@@ -543,23 +551,23 @@
STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}"
STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Raita{SETX 88}Nimi
STR_01E9_SHUFFLE :{TINYFONT}Sekoita
-STR_01EA_PROGRAM :{TINYFONT}{BLACK}Ohjelmoi
+STR_01EA_PROGRAM :{TINYFONT}{BLACK}Soittolista
STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Soittolistan valinta
STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA} "{STRING}"
STR_01ED :{TINYFONT}{LTBLUE}{COMMA} "{STRING}"
STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Raita
STR_01EF_PROGRAM :{TINYFONT}{BLACK}Soittolista - '{STRING}'
-STR_01F0_CLEAR :{TINYFONT}{BLACK}Tyhjää
+STR_01F0_CLEAR :{TINYFONT}{BLACK}Tyhjennä
STR_01F1_SAVE :{TINYFONT}{BLACK}Tallenna
-STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Raitojen nykyinen soittolista
+STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Nykyinen soittolista
STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Valitse 'kaikki raidat'
STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Valitse 'vanhan tyylin musiikki'
STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Valitse 'uuden tyylin musiikki'
STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Valitse 'oma 1' (käyttäjän määritettävissä)
STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Valitse 'oma 2' (käyttäjän määritettävissä)
-STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Tyhjää nykyinen soittolista (vain Oma1 tai Oma2)
+STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Tyhjennä nykyinen soittolista (vain Oma1 tai Oma2)
STR_01F9_SAVE_MUSIC_SETTINGS :{BLACK}Tallenna musiikkiasetukset
-STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Napsauta musiikkiraitaa lisätäksesi sen nykyiseen soittolistaan (vain Oma1 tai Oma2).
+STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Valitse musiikkiraita lisätäksesi sen nykyiseen soittolistaan (vain Oma1 tai Oma2).
STR_CLICK_ON_TRACK_TO_REMOVE :{BLACK}Klikkaa raitaa poistaaksesi se nykyisestä ohjelmasta (ainoastaan Custom1 tai Custom2)
STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Sekoittaminen päälle/pois
STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Näytä musiikkiraitojen valintaikkuna
@@ -603,14 +611,14 @@
STR_0220_CREATE_SCENARIO :{BLACK}Luo skenaario
STR_0221_OPENTTD :{YELLOW}OpenTTD
STR_0222_SCENARIO_EDITOR :{YELLOW}Skenaariomuokkain
-STR_0223_LAND_GENERATION :{WHITE}Maan luominen
+STR_0223_LAND_GENERATION :{WHITE}Maanrakennus
STR_0224 :{BLACK}{UPARROW}
STR_0225 :{BLACK}{DOWNARROW}
STR_0226_RANDOM_LAND :{BLACK}Satunnainen maa
STR_0227_RESET_LAND :{BLACK}Nollaa maa
STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Suurenna madallettavan/korotettavan maa-alueen kokoa.
STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Pienennä madallettavan/korotettavan maa-alueen kokoa.
-STR_022A_GENERATE_RANDOM_LAND :{BLACK}Luo satunnainen maa.
+STR_022A_GENERATE_RANDOM_LAND :{BLACK}Luo satunnainen maa
STR_022B_RESET_LANDSCAPE :{BLACK}Nollaa maasto
STR_022C_RESET_LANDSCAPE :{WHITE}Nollaa maasto
STR_LOAD_GAME_HEIGHTMAP :{WHITE}Käytä korkeuskarttaa
@@ -633,10 +641,10 @@
STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Suurenna kaupunkia
STR_023C_EXPAND :{BLACK}Laajenna
STR_023D_RANDOM_TOWN :{BLACK}Satunnainen kaupunki
-STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Rakenna kaupunki satunnaiseen kohtaan
+STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Rakenna kaupunki satunnaiseen paikkaan
STR_023F_INDUSTRY_GENERATION :{WHITE}Luo teollisuutta
STR_0240_COAL_MINE :{BLACK}Hiilikaivos
-STR_0241_POWER_STATION :{BLACK}Sähkölaitos
+STR_0241_POWER_STATION :{BLACK}Voimala
STR_0242_SAWMILL :{BLACK}Saha
STR_0243_FOREST :{BLACK}Metsä
STR_0244_OIL_REFINERY :{BLACK}Öljynjalostamo
@@ -1029,6 +1037,7 @@
STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Salli viranomaisten lahjominen: {ORANGE}{STRING}
STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Epäyhtenäiset asemat: {ORANGE}{STRING}
STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL :{LTBLUE}Uusi globaali tienhakualgor. (NPF, korvaa NTP:n): {ORANGE}{STRING}
+STR_CONFIG_PATCHES_FREIGHT_TRAINS :{LTBLUE}Kerroin rahdin painolle raskaiden junien simuilointiin: {ORANGE}{STRING}
STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Salli aina pienet lentokentät: {ORANGE}{STRING}
@@ -2177,7 +2186,7 @@
STR_LIVERY_DIESEL :Dieselveturi
STR_LIVERY_ELECTRIC :Sähköveturi
STR_LIVERY_MONORAIL :Yksiraiteinen veturi
-STR_LIVERY_MAGLEV :Maglev veturi
+STR_LIVERY_MAGLEV :Maglev-veturi
STR_LIVERY_DMU :DMU
STR_LIVERY_EMU :EMU
STR_LIVERY_PASSENGER_WAGON_STEAM :Matkustajavaunu (höyry)
@@ -2199,7 +2208,7 @@
STR_LIVERY_AIRCRAFT_TIP :{BLACK}Näytä lentokoneiden väriteemat
STR_LIVERY_PRIMARY_TIP :{BLACK}Valitse valitulle teemalle ensisijainen väri
STR_LIVERY_SECONDARY_TIP :{BLACK}Valitse valitulle teemalle toissijainen väri
-STR_LIVERY_PANEL_TIP :{BLACK}Valitse muutettava väriteema, tai valitse useita CTRL+klikkaus. Klikkaa valintalaatikkoa valitaksesi teeman
+STR_LIVERY_PANEL_TIP :{BLACK}Valitse muutettava väriteema, tai valitse useita CTRL pohjassa. Paina valintalaatikkoa valitaksesi teeman
##id 0x8000
STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (höyry)
@@ -2878,16 +2887,30 @@
STR_NEWGRF_FILENAME :{BLACK}Tiedostonimi: {SILVER}{STRING}
STR_NEWGRF_GRF_ID :{BLACK}GRF ID: {SILVER}{STRING}
STR_NEWGRF_MD5SUM :{BLACK}MD5-summa: {SILVER}{STRING}
+STR_NEWGRF_CONFIRMATION_TEXT :{YELLOW}Olet tekemässä muutoksia käynnissä olevaan peliin. OpenTTD voi kaatua.{}Oletko varma?
STR_NEWGRF_ADD :{BLACK}Lisää
STR_NEWGRF_ADD_TIP :{BLACK}Lisää NewGRF-tiedosto listaan
STR_NEWGRF_REMOVE :{BLACK}Poista
STR_NEWGRF_REMOVE_TIP :{BLACK}Poista valittu NewGRF-tiedosto listalta
STR_NEWGRF_MOVEUP :{BLACK}Siirrä ylös
+STR_NEWGRF_MOVEUP_TIP :{BLACK}Siirrä valittua NewGRF-tiedostoa listassa ylöspäin
STR_NEWGRF_MOVEDOWN :{BLACK}Siirrä alas
+STR_NEWGRF_MOVEDOWN_TIP :{BLACK}Siirrä valittua NewGRF-tiedostoa listassa alaspäin
+STR_NEWGRF_FILE_TIP :{BLACK}Lista asennetuista NewGRF-tiedostoista. Valitse tiedosto muokataksesi sen parametreja.
STR_NEWGRF_PARAMETER :{BLACK}Parametrit: {SILVER}{STRING}
+STR_NEWGRF_PARAMETER_QUERY :{BLACK}Anna NewGRF-parametrit
+STR_NEWGRF_NO_INFO :{BLACK}Ei tietoa
+STR_NEWGRF_ADD_CAPTION :{WHITE}NewGRF-tiedostot
+STR_NEWGRF_ADD_FILE :{BLACK}Lisää valintaan
+STR_NEWGRF_ADD_FILE_TIP :{BLACK}Lisää valittu NewGRF-tiedosto peliin
+STR_NEWGRF_RESCAN_FILES :{BLACK}Päivitä
+STR_NEWGRF_RESCAN_FILES_TIP :{BLACK}Päivitä saatavilla olevien NewGRF-tiedostojen lista
+STR_NEWGRF_DUPLICATE_GRFID :{WHITE}Ei voi lisätä tiedostoa: duplicate GRF ID
+STR_NEWGRF_NOT_FOUND :{RED}Sopivaa tiedostoa ei löydy
+STR_NEWGRF_DISABLED :{RED}Ei käytössä
STR_CURRENCY_WINDOW :{WHITE}Oma valuutta
STR_CURRENCY_EXCHANGE_RATE :{LTBLUE}Vaihtokurssi: {ORANGE}{CURRENCY} = £ {COMMA}
@@ -2919,6 +2942,8 @@
STR_VEH_WITH_SHARED_ORDERS_LIST_TIP :{BLACK}Näytä kaikki ajoneuvot, joilla on sama aikataulu
### depot strings
+STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}Olet myymässä kaikki varikon ajoneuvot. Oletko varma?
+
STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TIP :{BLACK}Myy kaikki varikolla olevat junat
STR_DEPOT_SELL_ALL_BUTTON_ROADVEH_TIP :{BLACK}Myy kaikki varikolla olevat ajoneuvot
STR_DEPOT_SELL_ALL_BUTTON_SHIP_TIP :{BLACK}Myy kaikki telakalla olevat laivat
@@ -2982,7 +3007,7 @@
STR_RAIL_VEHICLES :Rautatiejunat
STR_ELRAIL_VEHICLES :Sähköjunat
-STR_MONORAIL_VEHICLES :Yksiraidejunat
+STR_MONORAIL_VEHICLES :Yksiraiteiset
STR_MAGLEV_VEHICLES :Maglev-junat
############ End of list of rail types
--- a/lang/slovak.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/slovak.txt Wed Jan 03 08:32:17 2007 +0000
@@ -1936,15 +1936,15 @@
STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{INDUSTRY} oznamuje skore uzavretie!
STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Zasobovacie problemy donutili {INDUSTRY} oznamit skore uzavretie!
STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Nedostatok dostupnej drevnej suroviny donutil {INDUSTRY} oznamit skore uzavretie!
-STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{INDUSTRY} zvysuje produkciu!
+STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{INDUSTRY} zvyšuje produkciu!
STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Nove nalezisko uhlia sa objavilo v {INDUSTRY}!{}Ocakava sa zdvojnasobenie produkcie!
STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nove nalezisko ropy sa objavilo na {INDUSTRY}!{}Ocakava sa zdvojnasobenie produkcie!
STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Na {INDUSTRY} zlepsili pouzivane metody!Ocakava sa zdvojnasobenie produkcie!
-STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{INDUSTRY} znizuje produkciu o 50%
+STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{INDUSTRY} znižuje produkciu o 50%
STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Premnozenie skodcov sposobilo znicenie urody na {INDUSTRY}!{}Produkcia sa znizila o 50%
STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}... moze byt umiestnene len pri okraji mapy
-STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{1:INDUSTRY} zvysuje produkciu {0:STRING.g} o {2:COMMA}%!
-STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{1:INDUSTRY} znizuje produkciu {0:STRING.g} o {2:COMMA}%!
+STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{1:INDUSTRY} zvyšuje produkciu {0:STRING.g} o {2:COMMA}%!
+STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{1:INDUSTRY} znižuje produkciu {0:STRING.g} o {2:COMMA}%!
##id 0x5000
STR_5000_TRAIN_IN_TUNNEL :{WHITE}Vlak v tuneli
@@ -2668,6 +2668,7 @@
STR_885C_BROKEN_DOWN :{RED}Pokazene
STR_885D_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Naklady na prevadzku: {LTBLUE}{CURRENCY}/rok
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Nosnost: {LTBLUE}{WEIGHT_S} {BLACK}Vykon: {LTBLUE}{POWER}{BLACK} Max. rychlost: {LTBLUE}{VELOCITY}
+STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Hmotnost: {LTBLUE}{WEIGHT_S} {BLACK}Výkon: {LTBLUE}{POWER}{BLACK} Max. rýchlost: {LTBLUE}{VELOCITY} {BLACK}Max. T.S.: {LTBLUE}{FORCE}
STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zisk tento rok: {LTBLUE}{CURRENCY} (predchadzajuci rok: {CURRENCY})
STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Spolahlivost: {LTBLUE}{COMMA}% {BLACK}Pocet poruch od posledneho servisu: {LTBLUE}{COMMA}
STR_8861_STOPPED :{RED}Zastavene
@@ -3009,6 +3010,8 @@
STR_VEH_WITH_SHARED_ORDERS_LIST_TIP :{BLACK}Zobrazit vsetky vozidla s rovnakym zoznamom prikazov
### depot strings
+STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}Chystáte sa predat všetky vozidlá v depe. Ste si isý?
+
STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TIP :{BLACK}Predat všetky vlaky v depe
STR_DEPOT_SELL_ALL_BUTTON_ROADVEH_TIP :{BLACK}Predat všetky vozidlá v garáži
STR_DEPOT_SELL_ALL_BUTTON_SHIP_TIP :{BLACK}Predat všetky lode v lodenici
@@ -3094,6 +3097,7 @@
STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Prestavatelne na: {GOLD}
STR_PURCHASE_INFO_ALL_TYPES :Všetky druhy nákladu
STR_PURCHASE_INFO_ALL_BUT :Všetko okrem {GOLD}
+STR_PURCHASE_INFO_MAX_TE :{BLACK}Max. trakcna sila: {GOLD}{FORCE}
########### String for New Landscape Generator
--- a/lang/unfinished/croatian.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/unfinished/croatian.txt Wed Jan 03 08:32:17 2007 +0000
@@ -309,7 +309,6 @@
STR_015D_LOAD_GAME :Učitaj igru
STR_015E_QUIT_GAME :Napusti igru
STR_015F_QUIT :Izlaz
-STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Sigurno želiš napustiti ovu igru?
STR_0161_QUIT_GAME :{WHITE}Napusti igru
STR_SORT_ORDER_TIP :{BLACK}Izaberi način sortiranja (silazno/uzlazno)
STR_SORT_CRITERIA_TIP :{BLACK}Izaberi kriterij za sortiranje
@@ -558,7 +557,6 @@
STR_0298_LOAD_SCENARIO :{WHITE}Učitaj scenarij
STR_0299_SAVE_SCENARIO :{WHITE}Spremi scenarij
STR_029A_PLAY_SCENARIO :{BLACK}Igraj scenarij
-STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Jesi li siguran da želiš odustati od ovog scenarija?
STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Pomakni početni datum 1 godinu unatrag
STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Pomakni početni datum 1 godinu unaprijed
STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...oba kraja mosta moraju biti na zemlji
@@ -1017,6 +1015,7 @@
STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Željeznička konstrukcija
STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Jednotračna konstrukcija
STR_100C_MAGLEV_CONSTRUCTION :{WHITE}MagLev konstrukcija
+STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Ne možeš postaviti znakove ovdje...
STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Ne možeš graditi tračnice ovdje...
STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Ne možeš ukloniti tračnice odavdje...
STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Ne možeš maknuti signale odavdje...
@@ -1027,21 +1026,87 @@
STR_1017_MAGLEV_CONSTRUCTION :Izgradnja MagLeva
STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Izgradi željezničke tračnice
STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Izgradi spremište vlakova (za gradnju i servisiranje vlakova)
+STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Izgradi željeznički tunel
+STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}Odaberi smjer željezničkog spremišta
+STR_1021_RAILROAD_TRACK :Željezničke tračnice
+STR_1023_RAILROAD_TRAIN_DEPOT :Spremište vlakova
STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...područje je u vlasništvu druge tvrke
+STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Željezničke tračnice s normalnim znakovima
+STR_RAILROAD_TRACK_WITH_PRESIGNALS :Željezničke tračnice s prethodno postavljenim znakovima
+STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Željezničke tračnice s izlaznim znakovima
+STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Željezničke tračnice s kombo znakovima
##id 0x1800
STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Moraš prvo ukloniti cestu
+STR_ROAD_WORKS_IN_PROGRESS :{WHITE}Cestovni radovi u tijeku
+STR_1802_ROAD_CONSTRUCTION :{WHITE}Rekonstrukcija ceste
+STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Izaberi cestovni most
STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Ne možeš graditi cestu ovdje...
STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Ne možep maknuti cestu odavdje...
+STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Smjer cestovnog spremišta
+STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Ne možeš izgraditi spremište cestovnih vozila ovdje...
+STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Nije moguće izgraditi autobusnu stanicu...
+STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nije moguće izgraditi kamionski terminal...
+STR_180A_ROAD_CONSTRUCTION :Rekonstrukcija ceste
+STR_180B_BUILD_ROAD_SECTION :{BLACK}Izgradi dio ceste
+STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Izgradi spremište cestovnih vozila (za izgradnju i servisiranje vozila)
+STR_180D_BUILD_BUS_STATION :{BLACK}Izgradi autobusnu stanicu
+STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Izgradi pretovarni kamionski terminal
STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Izgradi cestovni most
STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Izgradi cestovni tunel
+STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Izaberi smjer spremišta cestovnih vozila
STR_1814_ROAD :Cesta
STR_1815_ROAD_WITH_STREETLIGHTS :Cesta sa semaforima
+STR_1817_ROAD_VEHICLE_DEPOT :Spremište cestovnih vozila
##id 0x2000
STR_2000_TOWNS :{WHITE}Gradovi
+STR_TOWN_LABEL_POP :{WHITE}{TOWN} ({COMMA})
+STR_TOWN_LABEL :{WHITE}{TOWN}
+STR_TOWN_LABEL_TINY_BLACK :{TINYFONT}{BLACK}{TOWN}
+STR_TOWN_LABEL_TINY_WHITE :{TINYFONT}{WHITE}{TOWN}
+STR_2002 :{TINYFONT}{BLACK}{STRING}
+STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Građevina mora prvo biti srušena
+STR_2005 :{WHITE}{TOWN}
+STR_2006_POPULATION :{BLACK}Stanovništvo: {ORANGE}{COMMA}{BLACK} Kuće: {ORANGE}{COMMA}
+STR_2007_RENAME_TOWN :Preimenuj grad
+STR_2008_CAN_T_RENAME_TOWN :{WHITE}Grad se ne može preimenovati...
+STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} lokalna samouprava odbija dozvoliti ovo
+STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Imena gradova - klikni na ime kako bi centrirao pogled na ekran
+STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centriraj glavni pogled na lokaciju grada
+STR_200C_CHANGE_TOWN_NAME :{BLACK}Promijeni ime grada
+STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Putnika prošli mjesec: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA}
+STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Pošte prošli mjesec: {ORANGE}{COMMA}{BLACK} maks: {ORANGE}{COMMA}
+STR_200F_TALL_OFFICE_BLOCK :Visoki uredski blok
+STR_2010_OFFICE_BLOCK :Uredski blok
+STR_2011_SMALL_BLOCK_OF_FLATS :Mali stambeni blok
+STR_2012_CHURCH :Crkva
+STR_2013_LARGE_OFFICE_BLOCK :Veliki uredski blok
+STR_2014_TOWN_HOUSES :Gradske kuće
+STR_2015_HOTEL :Hotel
+STR_2016_STATUE :Kip
+STR_2017_FOUNTAIN :Fontana
+STR_2018_PARK :Park
+STR_2019_OFFICE_BLOCK :Uredski blok
+STR_201A_SHOPS_AND_OFFICES :Trgovine i uredi
+STR_201B_MODERN_OFFICE_BUILDING :Moderne uredske zgrade
+STR_201C_WAREHOUSE :Skladište
+STR_201D_OFFICE_BLOCK :Uredski blok
+STR_201E_STADIUM :Stadion
+STR_201F_OLD_HOUSES :Stare kuće
+STR_2020_LOCAL_AUTHORITY :{BLACK}Lokalna samouprava
+STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Prikaži informacije o lokalnoj samoupravi
+STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} lokalna samouprava
+STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Ocjene prijevoznih tvrtki:
+STR_2024 :{YELLOW}{COMPANY}{PLAYERNAME}: {ORANGE}{STRING}
+STR_2025_SUBSIDIES :{WHITE}Subvencije
+STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Ponuđene subvencije za pružanje usluga:
+STR_2027_FROM_TO :{ORANGE}{STRING} od {STRING} do {STRING}
+STR_2028_BY :{YELLOW} (do {DATE_SHORT})
+STR_202A_NONE :{ORANGE}Ništa
+STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Usluge već subvencionirane:
STR_202C_FROM_TO :{ORANGE}{STRING} iz {STATION} prema {STATION}{YELLOW} ({COMPANY}
STR_202D_UNTIL :{YELLOW}, do {DATE_SHORT})
STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} lokalne vlasti odbijaju dozvoliti izgradnju još jedne zračne luke u ovom gradu
@@ -1068,15 +1133,24 @@
STR_204A_BUILD_STATUE_OF_COMPANY :Izgradi kip vlasnika tvrke
STR_204B_FUND_NEW_BUILDINGS :Financiraj nove građevine
STR_204C_BUY_EXCLUSIVE_TRANSPORT :Kupi ekskluzivna prijevozna prava
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Podmiti lokalnu samoupravu
STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Iniciraj malu oglasnu kampanju, kako bi privukao više putnika i tereta za svoje prijevozne usluge.{} Trošak: {CURRENCY}
STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Iniciraj srednju oglasnu kampanju, kako bi privukao više putnika i tereta za svoje prijevozne usluge.{} Trošak: {CURRENCY}
STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Iniciraj veliku oglasnu kampanju, kako bi privukao više putnika i tereta za svoje prijevozne usluge.{} Trošak: {CURRENCY}
STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Financiraj rekonstrukciju urbane mreže prometnica. Uzrokuje značajne poremećaje u cestovnom prometu do 6 mjeseci.{} Trošak: {CURRENCY}
STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Izgradi kip u čast svoje tvrke.{} Trošak: {CURRENCY}
STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Financiraj izgradnju novih poslovnih prostora u gradu.{} Trošak: {CURRENCY}
+STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Kupi jednogodišnje ekskluzivno prijevozno pravo u gradu. Gradska vlast će dopustiti putnicima i teretu da koriste samo stanice tvoje tvrtke.{} Trošak: {CURRENCY}
STR_2056 :{TINYFONT}{WHITE}{TOWN}
STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA})
+STR_2058_UNDER_CONSTRUCTION :{STRING} (pod rekonstrukcijom)
+STR_2059_IGLOO :Iglu
+STR_205A_TEPEES :Indijanski šator
+STR_INDUSTRY :{INDUSTRY}
+STR_TOWN :{TOWN}
+STR_INDUSTRY_FORMAT :{TOWN} {STRING}
+STR_STATION :{STATION}
##id 0x2800
STR_2800_PLANT_TREES :Posadi drveće
@@ -1151,6 +1225,7 @@
STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Imena stanica - klikni na ime kako bi centrirao glavni pogled na stanicu
STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Izaberi veličinu/tip zračne luke
STR_305C_0 :{STATION} {STATIONFEATURES}
+STR_STATION_SIGN_TINY :{TINYFONT}{STATION}
STR_305E_RAILROAD_STATION :Željeznička stanica
STR_305F_AIRCRAFT_HANGAR :Zrakoplovni hangar
STR_3060_AIRPORT :Zračna luka
@@ -1162,6 +1237,7 @@
STR_306A_BUOY_IN_THE_WAY :{WHITE}...plutača na putu
STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stanica previše proširena
STR_306D_NONUNIFORM_STATIONS_DISALLOWED :{WHITE}...neuniformne stanice zabranjene
+STR_USE_CTRL_TO_SELECT_MORE :{BLACK}Drži CTRL kako bi izabrao više od jednog itema
##id 0x3800
@@ -1278,6 +1354,7 @@
STR_5012_WOODEN :Drveni
STR_5013_CONCRETE :Betonski
STR_5014_TUBULAR_STEEL :Cijevni, čelični
+STR_BRIDGE_TUBULAR_SILICON :Cjevni, silikonski
STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Ovdje se ne može graditi most...
STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Ovdje se ne može graditi tunel...
STR_5017_RAILROAD_TUNNEL :Željeznički tunel
@@ -1311,12 +1388,52 @@
############ WARNING, using range 0x6000 for strings that are stored in the savegame
############ These strings may never get a new id, or savegames will break!
##id 0x6000
+STR_SV_EMPTY :
+STR_SV_UNNAMED :Neimenovan
+STR_SV_TRAIN_NAME :Vlak {COMMA}
+STR_SV_ROADVEH_NAME :Cestovno vozilo {COMMA}
+STR_SV_SHIP_NAME :Brod {COMMA}
+STR_SV_AIRCRAFT_NAME :Zrakoplov {COMMA}
+STR_SV_STNAME :{STRING}
+STR_SV_STNAME_NORTH :{STRING} Sjever
+STR_SV_STNAME_SOUTH :{STRING} Jug
+STR_SV_STNAME_EAST :{STRING} Istok
+STR_SV_STNAME_WEST :{STRING} Zapad
+STR_SV_STNAME_CENTRAL :{STRING} Centrala
+STR_SV_STNAME_TRANSFER :{STRING} Transfer
+STR_SV_STNAME_HALT :{STRING} Zaustav
+STR_SV_STNAME_VALLEY :{STRING} Dolina
+STR_SV_STNAME_HEIGHTS :{STRING} Visine
+STR_SV_STNAME_WOODS :{STRING} Šume
+STR_SV_STNAME_LAKESIDE :{STRING} Jezero
+STR_SV_STNAME_EXCHANGE :{STRING} Burza
+STR_SV_STNAME_AIRPORT :{STRING} Zračna luka
+STR_SV_STNAME_OILFIELD :{STRING} Naftno polje
+STR_SV_STNAME_MINES :{STRING} Rudnici
+STR_SV_STNAME_DOCKS :{STRING} Pristaništa
+STR_SV_STNAME_BUOY_1 :{STRING} Plutača 1
+STR_SV_STNAME_BUOY_2 :{STRING} Plutača 2
+STR_SV_STNAME_BUOY_3 :{STRING} Plutača 3
+STR_SV_STNAME_BUOY_4 :{STRING} Plutača 4
+STR_SV_STNAME_BUOY_5 :{STRING} Plutača 5
+STR_SV_STNAME_BUOY_6 :{STRING} Plutača 6
+STR_SV_STNAME_BUOY_7 :{STRING} Plutača 7
+STR_SV_STNAME_BUOY_8 :{STRING} Plutača 8
+STR_SV_STNAME_BUOY_9 :{STRING} Plutača 9
+STR_SV_STNAME_ANNEXE :{STRING} Aneks
+STR_SV_STNAME_SIDINGS :{STRING} Krak
+STR_SV_STNAME_BRANCH :{STRING} Ogranak
+STR_SV_STNAME_UPPER :Gornji {STRING}
+STR_SV_STNAME_LOWER :Donji {STRING}
+STR_SV_STNAME_HELIPORT :{STRING} Heliodrom
+STR_SV_STNAME_FOREST :{STRING} Šuma
############ end of savegame specific region!
##id 0x6800
STR_6800_DIFFICULTY_LEVEL :{WHITE}Težina igre
+STR_OPTIONS_SAVE_CHANGES :{BLACK}Spremi
############ range for difficulty levels starts
STR_6801_EASY :{BLACK}Lagano
@@ -1343,8 +1460,10 @@
STR_6813_ECONOMY :{LTBLUE}Ekonomija: {ORANGE}{STRING}
STR_6814_TRAIN_REVERSING :{LTBLUE}Promjena smjera vlakova: {ORANGE}{STRING}
STR_6815_DISASTERS :{LTBLUE}Prirodne katastrofe: {ORANGE}{STRING}
+STR_16816_CITY_APPROVAL :{LTBLUE}Stav gradsko vijeća prema restrukturiranju područja: {ORANGE}{STRING}
############ range for difficulty settings ends
+STR_26816_NONE :Ništa
STR_6816_LOW :Nisko
STR_6817_NORMAL :Normalno
STR_6818_HIGH :Visoko
@@ -1355,6 +1474,7 @@
STR_681D_MEDIUM :Umjereno
STR_681E_FAST :Brzo
STR_681F_VERY_FAST :Vrlo brzo
+STR_VERY_LOW :Vrlo nisko
STR_6820_LOW :Nisko
STR_6821_MEDIUM :Umjereno
STR_6822_HIGH :Visoko
@@ -1419,10 +1539,12 @@
STR_7020_TOTAL :{WHITE}Ukupno:
STR_7021 :{COMPANY}{PLAYERNAME}
STR_7022_INCOME_GRAPH :{WHITE}Graf prihoda
+STR_CURRCOMPACT :{CURRCOMPACT64}
STR_7024 :{COMMA}
STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Graf operativnih prihoda
STR_7026_BANK_BALANCE :{WHITE}Bankovna bilanca
STR_7027_LOAN :{WHITE}Kredit
+STR_MAX_LOAN :{WHITE}Maks zajam: {BLACK}{CURRENCY64}
STR_7028 :{BLACK}{CURRENCY64}
STR_7029_BORROW :{BLACK}Pozajmi {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
STR_702A_REPAY :{BLACK}Otplati {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
@@ -1431,6 +1553,7 @@
STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...nemaš kredita za otplatu
STR_702E_REQUIRED :{WHITE}...{CURRENCY} potrebno
STR_702F_CAN_T_REPAY_LOAN :{WHITE}Ne možeš otplatiti kredit...
+STR_INSUFFICIENT_FUNDS :{WHITE}Ne možeš dati novac koji je pozajmljen od banke...
STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Odaberi novo lice za direktora
STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Promijeni izgled vozila tvrtke
STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Promjeni ime direktora
@@ -1441,6 +1564,7 @@
STR_7037_PRESIDENT :{WHITE}{PLAYERNAME}{}{GOLD}(Direktor)
STR_7038_INAUGURATED :{GOLD}Na poziciji od: {WHITE}{NUM}
STR_7039_VEHICLES :{GOLD}Vozila:
+STR_AIRCRAFT :{WHITE}{COMMA} zrakoplov
STR_7042_NONE :{WHITE}Ništa
STR_7043_FACE_SELECTION :{WHITE}Odabir lica
STR_7044_MALE :{BLACK}Muško
@@ -1472,7 +1596,9 @@
STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Osnovana je nova prijevozna tvrtka!
STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{COMPANY} započinje gradnju blizu grada {TOWN}!
STR_7060_CAN_T_BUY_COMPANY :{WHITE}Ne možeš kupiti tvrtku...
+STR_7061_CARGO_PAYMENT_RATES :{WHITE}Isplatne rate tereta
STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Dana u tranzitu
+STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Aktiviraj/deaktiviraj graf za vrstu tereta
STR_7065 :{BLACK}{TINYFONT}{STRING}
STR_7066_ENGINEER :Inženjer
STR_7067_TRAFFIC_MANAGER :Prijevozni upravitelj
@@ -1567,9 +1693,6 @@
-
-
-
############ Lists rail types
--- a/lang/unfinished/greek.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/unfinished/greek.txt Wed Jan 03 08:32:17 2007 +0000
@@ -255,7 +255,6 @@
STR_015D_LOAD_GAME :Φόρτωση παιχνιδιού
STR_015E_QUIT_GAME :Παραίτηση από το παιχνίδι
STR_015F_QUIT :Έξοδος
-STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Είστε βέβαιοι ότι θέλετε να παραιτηθείτε από το παιχνίδι;
STR_0161_QUIT_GAME :{WHITE}Παραίτηση από το Παιχνίδι
@@ -325,9 +324,9 @@
STR_019D_AIRCRAFT :Αεροσκάφος
STR_019E_SHIP :Πλοίο
STR_019F_TRAIN :Τρένο
-STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA} παλιώνει
-STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA} παλιώνει πολύ
-STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} παλιώνει πολύ και χρειάζεται αντικατάσταση
+STR_01A0_IS_GETTING_OLD :{WHITE}Το {STRING} {COMMA} παλιώνει
+STR_01A1_IS_GETTING_VERY_OLD :{WHITE}Το {STRING} {COMMA} παλιώνει πολύ
+STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}Το {STRING} {COMMA} παλιώνει πολύ και χρειάζεται επειγόντωςαντικατάσταση
STR_01A3_LAND_AREA_INFORMATION :{WHITE}Πληροφορίες Περιοχής Εδάφους
STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Κόστος καθαρισμού: {LTBLUE}Μ/Δ
STR_01A5_COST_TO_CLEAR :{BLACK}Κόστος καθαρισμού: {LTBLUE}{CURRENCY}
@@ -335,41 +334,41 @@
STR_01A7_OWNER :{BLACK}Ιδιοκτήτης: {LTBLUE}{STRING}
STR_01A8_LOCAL_AUTHORITY :{BLACK}Τοπική αρχή: {LTBLUE}{STRING}
STR_01A9_NONE :Κανένα
-STR_01AA_NAME :{BLACK}'Ονομα
+STR_01AA_NAME :{BLACK}Όνομα
STR_01AB :{BLACK}{TINYFONT}{STRING}
############ range for days starts
-STR_01AC_1ST :1ος
-STR_01AD_2ND :2ος
-STR_01AE_3RD :3ος
-STR_01AF_4TH :4ος
-STR_01B0_5TH :5ος
-STR_01B1_6TH :6ος
-STR_01B2_7TH :7ος
-STR_01B3_8TH :8ος
-STR_01B4_9TH :9ος
-STR_01B5_10TH :10ος
-STR_01B6_11TH :11ος
-STR_01B7_12TH :12ος
-STR_01B8_13TH :13ος
-STR_01B9_14TH :14ος
-STR_01BA_15TH :15ος
-STR_01BB_16TH :16ος
-STR_01BC_17TH :17ος
-STR_01BD_18TH :18ος
-STR_01BE_19TH :19ος
-STR_01BF_20TH :20ος
-STR_01C0_21ST :21ος
-STR_01C1_22ND :22ος
-STR_01C2_23RD :23ος
-STR_01C3_24TH :24ος
-STR_01C4_25TH :25ος
-STR_01C5_26TH :26ος
-STR_01C6_27TH :27ος
-STR_01C7_28TH :28ος
-STR_01C8_29TH :29ος
-STR_01C9_30TH :30ος
-STR_01CA_31ST :31ος
+STR_01AC_1ST :1{G ος η ο}
+STR_01AD_2ND :2{G ος η ο}
+STR_01AE_3RD :3{G ος η ο}
+STR_01AF_4TH :4{G ος η ο}
+STR_01B0_5TH :5{G ος η ο}
+STR_01B1_6TH :6{G ος η ο}
+STR_01B2_7TH :7{G ος η ο}
+STR_01B3_8TH :8{G ος η ο}
+STR_01B4_9TH :9{G ος η ο}
+STR_01B5_10TH :10{G ος η ο}
+STR_01B6_11TH :11{G ος η ο}
+STR_01B7_12TH :12{G ος η ο}
+STR_01B8_13TH :13{G ος η ο}
+STR_01B9_14TH :14{G ος η ο}
+STR_01BA_15TH :15{G ος η ο}
+STR_01BB_16TH :16{G ος η ο}
+STR_01BC_17TH :17{G ος η ο}
+STR_01BD_18TH :18{G ος η ο}
+STR_01BE_19TH :19{G ος η ο}
+STR_01BF_20TH :20{G ος η ο}
+STR_01C0_21ST :21{G ος η ο}
+STR_01C1_22ND :22{G ος η ο}
+STR_01C2_23RD :23{G ος η ο}
+STR_01C3_24TH :24{G ος η ο}
+STR_01C4_25TH :25{G ος η ο}
+STR_01C5_26TH :26{G ος η ο}
+STR_01C6_27TH :27{G ος η ο}
+STR_01C7_28TH :28{G ος η ο}
+STR_01C8_29TH :29{G ος η ο}
+STR_01C9_30TH :30{G ος η ο}
+STR_01CA_31ST :31{G ος η ο}
############ range for days ends
STR_01CB :{TINYFONT}{COMMA}
@@ -388,7 +387,7 @@
STR_01DA_CUSTOM_2 :{TINYFONT}Προσαρμοσμένο 2
STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Ένταση Μουσικής
STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Ένταση Εφφέ
-STR_01DD_MIN_MAX :{BLACK}{TINYFONT}ΕΛ ' ' ' ' ' ' ΜΕΓ
+STR_01DD_MIN_MAX :{BLACK}{TINYFONT}ΕΛΑΧ ' ' ' ' ' ' ΜΕΓ
STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Πλοήγηση στο προηγούμενο κομμάτι της συλλογής
STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Πλοήγηση στο επόμενο κομμάτι στη συλλογή
STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Σταμάτημα αναπαραγωγής
@@ -400,7 +399,7 @@
STR_01E6 :{DKGREEN}{TINYFONT}------
STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}"
STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Κομμάτι{SETX 88}Τίτλος
-STR_01E9_SHUFFLE :{TINYFONT}Shuffle
+STR_01E9_SHUFFLE :{TINYFONT}Τυχαία αναπαραγωγή
STR_01EA_PROGRAM :{TINYFONT}{BLACK}Πρόγραμμα
STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Επιλογή Μουσικού Προγράμματος
STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA} "{STRING}"
@@ -413,15 +412,15 @@
STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Επιλογή προγράμματος 'όλα τα κομμάτια'
STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Επιλογή προγράμματος 'παλιό στυλ'
STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Επιλογή προγράμματος 'νέο στυλ'
-STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Επιλογή προγράμματος 'προσαρμοσμένο 1'
-STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Επιλογή προγράμματος 'προσαρμοσμένο 2'
+STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Επιλογή προγράμματος 'Προσαρμοσμένο 1'
+STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Επιλογή προγράμματος 'Προσαρμοσμένο 2'
STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Καθαρισμός τρέχοντος προγράμματος (Προσαρμοσμένο1 ή Προσαρμοσμένο2 μόνο)
STR_01F9_SAVE_MUSIC_SETTINGS :{BLACK}Αποθήκευση επιλογών μουσικής
STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Κάντε κλίκ στο μουσικό κομμάτι για προσθήκη στο τρέχον πρόγραμμα (Προσαρμοσμένο1 ή Προσαρμοσμένο2 μόνο)
-STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Εναλλαγή shuffle on/off στο πρόγραμμα
+STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Εναλλαγή τυχαίας αναπαραγωγής on/off στο πρόγραμμα
STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Εμφάνιση παραθύρου επιλογής μουσικού κομματιού
STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Κάντε κλίκ στην υπηρεσία για κεντράρισμα στην βιομηχανία/πόλη
-STR_01FE_DIFFICULTY :{BLACK}Δυσκολία ({STRING})
+STR_01FE_DIFFICULTY :{BLACK}{G=f}Δυσκολία ({STRING})
STR_01FF :{TINYFONT}{BLACK}{DATE_LONG}
STR_0200_LAST_MESSAGE_NEWS_REPORT :Τελευταίο μήνυμα/αναφορά νέων
STR_0201_MESSAGE_SETTINGS :Ρυθμίσεις μηνυμάτων
@@ -439,7 +438,7 @@
STR_020E_SUBSIDIES :{YELLOW}Επιχορηγήσεις
STR_020F_GENERAL_INFORMATION :{YELLOW}Γενικές πληροφορίες
STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...πολύ μακριά από τον προηγούμενο προορισμό
-STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Οι καλύτερες εταιρείες που έφτασαν {NUM}{}({STRING} Επίπεδο)
+STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Οι καλύτερες εταιρείες που έφτασαν το {NUM}{}({STRING} Επίπεδο)
STR_0212 :{BIGFONT}{COMMA},
STR_0213_BUSINESSMAN :Επαγγελματίας
STR_0214_ENTREPRENEUR :Επιχειρηματίας
@@ -453,8 +452,8 @@
STR_021F :{BLUE}{COMMA}
STR_0220_CREATE_SCENARIO :{BLACK}Δημιουργία Σεναρίου
STR_0221_OPENTTD :{YELLOW}OpenTTD
-STR_0222_SCENARIO_EDITOR :{YELLOW}Συντάκτης Σεναρίου
-STR_0223_LAND_GENERATION :{WHITE}Γεννήτρια Γης
+STR_0222_SCENARIO_EDITOR :{YELLOW}Πρόγραμμα Επεξερτασίας Σεναρίου
+STR_0223_LAND_GENERATION :{WHITE}Δημιουργία Γης
STR_0224 :{BLACK}{UPARROW}
STR_0225 :{BLACK}{DOWNARROW}
STR_0226_RANDOM_LAND :{BLACK}Τυχαία Γη
@@ -482,20 +481,20 @@
STR_023D_RANDOM_TOWN :{BLACK}Τυχαία Πόλη
STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Χτίσιμο πόλης σε τυχαία τοποθεσία
STR_023F_INDUSTRY_GENERATION :{WHITE}Δημιουργία Βιομηχανίας
-STR_0240_COAL_MINE :{BLACK}Ορυχείο Άνθρακα
-STR_0241_POWER_STATION :{BLACK}Σταθμός Παραγωγής Ηλεκτρισμού
-STR_0242_SAWMILL :{BLACK}Πριονιστήριο
-STR_0243_FOREST :{BLACK}Δάσος
-STR_0244_OIL_REFINERY :{BLACK}Διυλιστήριο
-STR_0245_OIL_RIG :{BLACK}Πλατφόρμα Πετρελαίου
-STR_0246_FACTORY :{BLACK}Εργοστάσιο
-STR_0247_STEEL_MILL :{BLACK}Μύλος Χάλυβα
-STR_0248_FARM :{BLACK}Φάρμα
-STR_0249_IRON_ORE_MINE :{BLACK}Ορυχείο Μεταλλεύματος Σιδήρου
+STR_0240_COAL_MINE :{BLACK}{G=n}Ορυχείο Άνθρακα
+STR_0241_POWER_STATION :{BLACK}{G=m}Σταθμός Παραγωγής Ηλεκτρισμού
+STR_0242_SAWMILL :{BLACK}{G=n}Πριονιστήριο
+STR_0243_FOREST :{BLACK}{G=n}Δάσος
+STR_0244_OIL_REFINERY :{BLACK}{G=n}Διυλιστήριο
+STR_0245_OIL_RIG :{BLACK}{G=f}Πλατφόρμα Πετρελαίου
+STR_0246_FACTORY :{BLACK}{G=n}Εργοστάσιο
+STR_0247_STEEL_MILL :{BLACK}{G=m}Μύλος Χάλυβα
+STR_0248_FARM :{BLACK}{G=f}Φάρμα
+STR_0249_IRON_ORE_MINE :{BLACK}{G=n}Ορυχείο Μεταλλεύματος Σιδήρου
STR_024A_OIL_WELLS :{BLACK}Πηγάδια Πετρελαίου
-STR_024B_BANK :{BLACK}Τράπεζα
-STR_024C_PAPER_MILL :{BLACK}Μύλος Χαρτιού
-STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Εργοστάσιο Επεξεργασίας Τροφίμων
+STR_024B_BANK :{BLACK}{G=f}Τράπεζα
+STR_024C_PAPER_MILL :{BLACK}{G=m}Μύλος Χαρτιού
+STR_024D_FOOD_PROCESSING_PLANT :{BLACK}{G=n}Εργοστάσιο Επεξεργασίας Τροφίμων
STR_024E_PRINTING_WORKS :{BLACK}Εργασίες Εκτύπωσης
STR_024F_GOLD_MINE :{BLACK}Ορυχείο Χρυσού
STR_0250_LUMBER_MILL :{BLACK}Μύλος Ξυλείας
@@ -551,7 +550,7 @@
STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Κατασκευή Γεννήτριας Φυσαλίδων
STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Κατασκευή Λατομείου Τόφυ
STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Κατασκευή Ορυχείου Ζάχαρης
-STR_0285_CAN_T_BUILD_HERE :{WHITE}Αδύνατο να χτιστεί {STRING} εδώ...
+STR_0285_CAN_T_BUILD_HERE :{WHITE}Αδύνατο να χτιστεί {G ο η το} {STRING} εδώ...
STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...πρέπει να χτιστεί πόλη πρώτα
STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...επιτρέπεται μόνο μία ανά πόλη
STR_0288_PLANT_TREES :{BLACK}Φύτευση Δέντρων
@@ -566,15 +565,14 @@
STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Πλήρης διαγραφή πόλεως
STR_0292_SAVE_SCENARIO :Απποθήκευση σεναρίου
STR_0293_LOAD_SCENARIO :Φόρτωση σεναρίου
-STR_0294_QUIT_EDITOR :Έξοδος από το Συντάκτη
+STR_0294_QUIT_EDITOR :Έξοδος από το πρόγραμμα επεξεργασίας
STR_0295 :
STR_0296_QUIT :Έξοδος
-STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Αποθήκευση σεναρίου, φόρτωση, παραίτηση συντάκτη, έξοδος
+STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Αποθήκευση σεναρίου, φόρτωση, παραίτηση πρόγραμμα επεξεργασίας, έξοδος
STR_0298_LOAD_SCENARIO :{WHITE}Φόρτωση Σεναρίου
STR_0299_SAVE_SCENARIO :{WHITE}Αποθήκευση Σεναρίου
STR_029A_PLAY_SCENARIO :{BLACK}Παιξτε το Σενάριο
-STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Είστε σίγουρος ότι θέλετε να κάνετε έξοδο;
-STR_029C_QUIT_EDITOR :{WHITE}Έξοδος από Συντάκτη
+STR_029C_QUIT_EDITOR :{WHITE}Έξοδος από το Πρόγραμμα Επεξεργασίας
STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...μπορεί να χτιστεί μόνο σε πόλεις με πληθυσμό άνω των 1200
STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Μετακίνηση ημ/νίας εκκίνησης 1 χρόνο πίσω
STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Μετακίνηση ημ/νίας εκκίνησης 1 χρόνο μπροστά
@@ -591,8 +589,8 @@
STR_02BB_TOWN_DIRECTORY :Καταλογος πόλεων
STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Ονόματα σχεδίων οχημάτων
STR_02BD :{BLACK}{STRING}
-STR_02BE_DEFAULT :Προεπιλεγμένο
-STR_02BF_CUSTOM :Προσαρμοσμένο
+STR_02BE_DEFAULT :Προεπιλεγμέν{G ος η ο}
+STR_02BF_CUSTOM :Προσαρμοσμέν{G ος η ο}
STR_02C0_SAVE_CUSTOM_NAMES :{BLACK}Αποθήκευση προσαρμοσμένων ονομάτων
STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Επιλογή ονομάτων σχεδίασης οχημάτων
STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Αποθήκευση προσαρμοσμένων ονομάτων σχεδίασης οχημάτων
@@ -1468,6 +1466,8 @@
+
+
##id 0x9000
@@ -1493,9 +1493,6 @@
-### looks odd, but trainslators requested this as depots aren't the same for all vehicles in all translations
-### we can use there whenever we want a depot mentioned in another string to avoid making 4 versions of all strings
-
@@ -1512,9 +1509,6 @@
-
-
-
############ Lists rail types
@@ -1528,4 +1522,8 @@
########### String for new airports
+
+############ Tooltip measurment
+
+
########
--- a/lang/unfinished/japanese.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/unfinished/japanese.txt Wed Jan 03 08:32:17 2007 +0000
@@ -1,2 +1,1436 @@
##name Japanese
-##ownname æ¥æ
+##ownname 日本語
+##isocode ja_JP.UTF-8
+##plural 1
+
+##id 0x0000
+STR_NULL :
+STR_0001_OFF_EDGE_OF_MAP :{WHITE}地図のエッジはちょっと近いです
+STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}地図のエッジはちょっと近いです
+STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}お金はありません。{CURRENCY}がかかります
+STR_0004 :{WHITE}{CURRENCY64}
+STR_0005 :{RED}{CURRENCY64}
+STR_EMPTY :
+STR_0007_FLAT_LAND_REQUIRED :{WHITE}平たい地面がかかります
+STR_0008_WAITING :{BLACK}待っています: {WHITE}{STRING}
+STR_0009 :{WHITE}{CARGO}
+STR_000B :{YELLOW}{STATION})
+STR_000C_ACCEPTS :{BLACK}受け取れる事は: {WHITE}
+STR_000D_ACCEPTS :{BLACK}受け取れる事は: {GOLD}
+STR_000E :
+STR_000F_PASSENGERS :乗客
+STR_0010_COAL :石炭
+STR_0011_MAIL :郵便物
+STR_0012_OIL :原油
+STR_0013_LIVESTOCK :家畜
+STR_0014_GOODS :商品
+STR_0015_GRAIN :穀物
+STR_0016_WOOD :木材
+STR_0017_IRON_ORE :鉄鉱
+STR_0018_STEEL :鋼鉄
+STR_0019_VALUABLES :貴重品
+STR_001A_COPPER_ORE :銅鉱
+STR_001B_MAIZE :トウモロコシ
+STR_001C_FRUIT :果物
+STR_001D_DIAMONDS :ダイヤモンド
+STR_001E_FOOD :食べ物
+STR_001F_PAPER :紙
+STR_0020_GOLD :金
+STR_0021_WATER :水
+STR_0022_WHEAT :小麦
+STR_0023_RUBBER :ゴム
+STR_0024_SUGAR :砂糖
+STR_0025_TOYS :おもちゃ
+STR_0026_CANDY :お菓子
+STR_0027_COLA :コーラ
+STR_0028_COTTON_CANDY :綿あめ
+STR_0029_BUBBLES :泡
+STR_002A_TOFFEE :タフィー
+STR_002B_BATTERIES :乾電池
+STR_002C_PLASTIC :プラスチク
+STR_002D_FIZZY_DRINKS :清涼飲料水
+STR_002E :
+STR_002F_PASSENGER :乗客
+STR_0030_COAL :石炭
+STR_0031_MAIL :郵便物
+STR_0032_OIL :原油
+STR_0033_LIVESTOCK :家畜
+STR_0034_GOODS :商品
+STR_0035_GRAIN :穀物
+STR_0036_WOOD :木材
+STR_0037_IRON_ORE :鉄鉱
+STR_0038_STEEL :鋼鉄
+STR_0039_VALUABLES :貴重品
+STR_003A_COPPER_ORE :銅鉱
+STR_003B_MAIZE :トウモロコシ
+STR_003C_FRUIT :果物
+STR_003D_DIAMOND :ダイヤモンド
+STR_003E_FOOD :食べ物
+STR_003F_PAPER :紙
+STR_0040_GOLD :金
+STR_0041_WATER :水
+STR_0042_WHEAT :小麦
+STR_0043_RUBBER :ゴム
+STR_0044_SUGAR :砂糖
+STR_0045_TOY :おもちゃ
+STR_0046_CANDY :お菓子
+STR_0047_COLA :コーラ
+STR_0048_COTTON_CANDY :綿あめ
+STR_0049_BUBBLE :泡
+STR_004A_TOFFEE :タフィー
+STR_004B_BATTERY :乾電池
+STR_004C_PLASTIC :プラスチク
+STR_004D_FIZZY_DRINK :清涼飲料水
+STR_QUANTITY_NOTHING :
+STR_00AE :{WHITE}{DATE_SHORT}
+STR_00AF :{WHITE}{DATE_LONG}
+STR_00B0_MAP :{WHITE}地図- {STRING}
+STR_00B1_GAME_OPTIONS :{WHITE}ゲーム設定
+STR_00B2_MESSAGE :{YELLOW}メッセージ
+STR_00B3_MESSAGE_FROM :{YELLOW} {STRING}からメッセージ
+STR_00B4_CAN_T_DO_THIS :{WHITE}出来ません
+STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}その所を空けません
+STR_00B7_VERSION :{BLACK}OpenTTD バージョン {REV}
+STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2006 The OpenTTD team
+STR_TRANSLATED_BY :{BLACK} 訳者-
+
+STR_00C5 :{BLACK}{CROSS}
+STR_00C6 :{SILVER}{CROSS}
+STR_00C8_YES :{BLACK}はい
+STR_00C9_NO :{BLACK}いいえ
+STR_00CB_1 :{BLACK}1
+STR_00CC_2 :{BLACK}2
+STR_00CD_3 :{BLACK}3
+STR_00CE_4 :{BLACK}4
+STR_00CF_5 :{BLACK}5
+STR_00D0_NOTHING :何も
+STR_00D1_DARK_BLUE :紺青色
+STR_00D2_PALE_GREEN :薄緑色
+STR_00D3_PINK :ピンク
+STR_00D4_YELLOW :黄色
+STR_00D5_RED :赤色
+STR_00D6_LIGHT_BLUE :薄青色
+STR_00D7_GREEN :緑色
+STR_00D8_DARK_GREEN :濃緑色
+STR_00D9_BLUE :青色
+STR_00DA_CREAM :クリーム色
+STR_00DB_MAUVE :藤色
+STR_00DC_PURPLE :紫色
+STR_00DD_ORANGE :オレンジ色
+STR_00DE_BROWN :茶色
+STR_00DF_GREY :灰色
+STR_00E0_WHITE :白色
+STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}ゲームのバス/トラック数の制限を超えています
+STR_00E2 :{BLACK}{COMMA}
+STR_00E3 :{RED}{COMMA}
+STR_00E4_LOCATION :{BLACK}見付けます
+STR_00E7_INDUSTRIES :産業
+STR_00E8_ROUTES :経路
+STR_00E9_VEGETATION :植物
+STR_00EB_ROADS :{BLACK}{TINYFONT}道路
+STR_00EC_RAILROADS :{BLACK}{TINYFONT}鉄道
+STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}駅/空港/波止場
+STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}建物/産業
+STR_00F0_100M :{BLACK}{TINYFONT}100m
+STR_00F1_200M :{BLACK}{TINYFONT}200m
+STR_00F2_300M :{BLACK}{TINYFONT}300m
+STR_00F3_400M :{BLACK}{TINYFONT}400m
+STR_00F4_500M :{BLACK}{TINYFONT}500m
+STR_00F5_TRAINS :{BLACK}{TINYFONT}電車
+STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}バス/トラック
+STR_00F7_SHIPS :{BLACK}{TINYFONT}船
+STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}飛行機
+STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}運送経路
+STR_00FA_COAL_MINE :{BLACK}{TINYFONT}炭坑
+STR_00FB_POWER_STATION :{BLACK}{TINYFONT}発電所
+STR_00FC_FOREST :{BLACK}{TINYFONT}森林
+STR_00FD_SAWMILL :{BLACK}{TINYFONT}製材工場
+STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}製油所
+STR_00FF_FARM :{BLACK}{TINYFONT} 農場
+STR_0100_FACTORY :{BLACK}{TINYFONT} 工場
+STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}印刷所
+STR_0102_OIL_WELLS :{BLACK}{TINYFONT}油井
+STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}鉄鉱石鉱山
+STR_0104_STEEL_MILL :{BLACK}{TINYFONT}製鋼所
+STR_0105_BANK :{BLACK}{TINYFONT}銀行
+STR_0106_PAPER_MILL :{BLACK}{TINYFONT}製紙工場
+STR_0107_GOLD_MINE :{BLACK}{TINYFONT}金鉱
+STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}食品加工場
+STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}ダイヤモンド鉱山
+STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}銅鉱山
+STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}果物農園
+STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}ゴム園
+STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}給水設備
+STR_010E_WATER_TOWER :{BLACK}{TINYFONT}給水塔
+STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}製材所
+STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}綿菓子
+STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}お菓子工場
+STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}電池農園
+STR_0113_COLA_WELLS :{BLACK}{TINYFONT}コーラ泉
+STR_0114_TOY_SHOP :{BLACK}{TINYFONT}玩具店
+STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}玩具工場
+STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}プラスチック泉
+STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}ソーダ工場
+STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}泡の発生器
+STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}トッフィー採石場
+STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}砂糖鉱山
+STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}駅
+STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}トラック荷役所
+STR_011D_BUS_STATION :{BLACK}{TINYFONT}バス停
+STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}空港/ヘリポート
+STR_011F_DOCK :{BLACK}{TINYFONT}波止場
+STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}でこぼこの土地
+STR_0121_GRASS_LAND :{BLACK}{TINYFONT}草地
+STR_0122_BARE_LAND :{BLACK}{TINYFONT}裸地
+STR_0123_FIELDS :{BLACK}{TINYFONT}田畑
+STR_0124_TREES :{BLACK}{TINYFONT}木
+STR_0125_ROCKS :{BLACK}{TINYFONT}
+STR_0126_WATER :{BLACK}{TINYFONT}水
+STR_0127_NO_OWNER :{BLACK}{TINYFONT}所有者なし
+STR_0128_TOWNS :{BLACK}{TINYFONT}町
+STR_0129_INDUSTRIES :{BLACK}{TINYFONT}産業
+STR_012A_DESERT :{BLACK}{TINYFONT}砂漠
+STR_012B_SNOW :{BLACK}{TINYFONT}雪
+STR_012C_MESSAGE :{WHITE}メッセージ
+STR_012D :{WHITE}{STRING}
+STR_012E_CANCEL :{BLACK}キャンセル
+STR_012F_OK :{BLACK}OK
+STR_0130_RENAME :{BLACK}名称を変更
+STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}名称定義数の制限を超えています
+STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}指定した名称は既に使用中です
+
+STR_0133_WINDOWS :Windows
+STR_0134_UNIX :Unix
+STR_0135_OSX :OS X
+
+STR_013B_OWNED_BY :{WHITE}...所有者は {STRING}
+STR_013C_CARGO :{BLACK}貨物
+STR_013D_INFORMATION :{BLACK}情報
+STR_013E_CAPACITIES :{BLACK}容量
+STR_013E_TOTAL_CARGO :{BLACK}合計貨物
+STR_013F_CAPACITY :{BLACK}容量:{LTBLUE}{CARGO}
+STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}この電車の貨物最大容量:
+STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO})
+STR_TOTAL_CAPACITY_MULT :{LTBLUE}- {CARGO} ({SHORTCARGO}) (x{NUM})
+STR_0140_NEW_GAME :{BLACK}新しいゲーム
+STR_0141_LOAD_GAME :{BLACK}ゲームを開く
+
+STR_64 :64
+STR_128 :128
+STR_256 :256
+STR_512 :512
+STR_1024 :1024
+STR_2048 :2048
+STR_BY :{BLACK}*
+STR_0148_GAME_OPTIONS :{BLACK}ゲームの設定
+
+STR_0150_SOMEONE :誰かは{SKIP}{SKIP}
+STR_0151_MAP_OF_WORLD :世界の地図
+STR_0152_TOWN_DIRECTORY :町のリスト
+STR_0153_SUBSIDIES :助成金
+
+STR_UNITS_METRIC :メートル法
+
+
+STR_UNITS_POWER_IMPERIAL :{COMMA}ホースポワー
+STR_UNITS_POWER_METRIC :{COMMA}ホースポワー
+STR_UNITS_POWER_SI :{COMMA}キロワット
+
+STR_UNITS_WEIGHT_SHORT_IMPERIAL :{COMMA}トン
+STR_UNITS_WEIGHT_SHORT_METRIC :{COMMA}トン
+STR_UNITS_WEIGHT_SHORT_SI :{COMMA}キロ
+
+STR_UNITS_WEIGHT_LONG_IMPERIAL :{COMMA} 英トン
+STR_UNITS_WEIGHT_LONG_METRIC :{COMMA} 仏トン
+STR_UNITS_WEIGHT_LONG_SI :{COMMA} キロ
+
+STR_UNITS_VOLUME_SHORT_IMPERIAL :{COMMA}ガロン
+STR_UNITS_VOLUME_SHORT_METRIC :{COMMA}リットル
+STR_UNITS_VOLUME_SHORT_SI :{COMMA}m³
+
+STR_UNITS_VOLUME_LONG_IMPERIAL :{COMMA} ガロン
+STR_UNITS_VOLUME_LONG_METRIC :{COMMA} リットル
+STR_UNITS_VOLUME_LONG_SI :{COMMA} m³
+
+
+############ range for menu starts
+STR_0154_OPERATING_PROFIT_GRAPH :営業利益
+STR_0155_INCOME_GRAPH :所得グラフ
+STR_0156_DELIVERED_CARGO_GRAPH :運送した貨物のグラフ
+STR_0157_PERFORMANCE_HISTORY_GRAPH :成績グラフ
+STR_0158_COMPANY_VALUE_GRAPH :会社価値グラフ
+STR_0159_CARGO_PAYMENT_RATES :貨物運送料
+STR_015A_COMPANY_LEAGUE_TABLE :会社の成績表
+############ range for menu ends
+
+STR_015B_OPENTTD :{WHITE}OpenTTDとは?でぐち
+STR_015C_SAVE_GAME :ゲームを保存
+STR_015D_LOAD_GAME :ゲームを開く
+STR_015E_QUIT_GAME :ゲームを断念
+STR_015F_QUIT :出口
+STR_0161_QUIT_GAME :{WHITE}ゲームの断念
+
+STR_SORT_BY_POPULATION :{BLACK}人口
+STR_SORT_BY_TYPE :{BLACK}種類
+STR_SORT_BY_TRANSPORTED :{BLACK}運びだ
+STR_SORT_BY_NAME :{BLACK}名前
+STR_SORT_BY_DROPDOWN_NAME :名前
+STR_SORT_BY_NUMBER :番号
+STR_SORT_BY_VALUE :価値
+STR_SORT_BY_WAITING :待っている積荷価値
+STR_ENGINE_SORT_COST :値段
+
+############ range for months starts
+STR_0162_JAN :1月
+STR_0163_FEB :2月
+STR_0164_MAR :3月
+STR_0165_APR :4月
+STR_0166_MAY :5月
+STR_0167_JUN :6月
+STR_0168_JUL :7月
+STR_0169_AUG :8月
+STR_016A_SEP :9月
+STR_016B_OCT :10月
+STR_016C_NOV :11月
+STR_016D_DEC :12月
+############ range for months ends
+
+STR_016E :{TINYFONT}{STRING}{} {STRING}
+STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUM}
+STR_0170 :{TINYFONT}{STRING}-
+STR_0171_PAUSE_GAME :{BLACK}ポーズ
+STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}ゲームを保存、ゲームを断念、終了
+STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}会社の駅を表示します
+STR_0174_DISPLAY_MAP :{BLACK}地図を見せます
+STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}地図、町のリストを表示します
+STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}町のリストを表示します
+STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}会社の財務状況を表示します
+STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}会社の一般情報を表示します
+STR_0179_DISPLAY_GRAPHS :{BLACK}グラフを表示します
+STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}会社の成績表を表示します
+STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}会社の電車のリストを表示します
+STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}会社のバス/トラックのリストを表示します
+STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}会社の船のリストを表示します
+STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}会社の飛行機のリストを表示します
+STR_017F_ZOOM_THE_VIEW_IN :{BLACK}拡大します
+STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}縮小します
+STR_0181_BUILD_RAILROAD_TRACK :{BLACK}鉄道を建造します
+STR_0182_BUILD_ROADS :{BLACK}道路を建造します
+STR_0183_BUILD_SHIP_DOCKS :{BLACK}波止場を建造します
+STR_0184_BUILD_AIRPORTS :{BLACK}空港を建造します
+STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}木の植え、標示の置くことなど
+STR_0186_LAND_BLOCK_INFORMATION :{BLACK}地域情報
+STR_0187_OPTIONS :{BLACK}設定
+STR_0188 :{BLACK}{SMALLUPARROW}
+STR_0189 :{BLACK}{SMALLDOWNARROW}
+STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}整備間隔が変更できません
+STR_018B_CLOSE_WINDOW :{BLACK}ウィンドウを閉じます
+STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}ウィンドウのタイトル - ウィンドウを動くには、クリックしてドラッグします
+STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}土地上の建物などを破壊します
+STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}土地の角を下げます
+STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}土地の角を上げます
+STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}スクロールバー
+STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}地図に土地の形勢を表示します
+STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}地図に乗り物を表示します
+STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}地図に産業を表示します
+STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}地図に運送経路を表示します
+STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}地図に植物を表示します
+STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}地図に土地の所有者を表示します
+STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}地図に町名の表示を入/切にします
+STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}今年の利益:{CURRENCY} (去年:{CURRENCY})
+
+############ range for service numbers starts
+############ range for service numbers ends
+
+STR_019C_ROAD_VEHICLE :バス/トラック
+STR_019D_AIRCRAFT :飛行機
+STR_019E_SHIP :船
+STR_019F_TRAIN :電車
+STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA} は古くなっています
+STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA} はかねて古くなっています
+STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} はかねて古くなっていて、緊急に取り替えられなければなりません
+STR_01A3_LAND_AREA_INFORMATION :{WHITE}地域情報
+STR_01A4_COST_TO_CLEAR_N_A :{BLACK}破壊の価格:{LTBLUE}破壊不可
+STR_01A5_COST_TO_CLEAR :{BLACK}破壊の価格:{LTBLUE}{CURRENCY}
+STR_01A6_N_A :N/A
+STR_01A7_OWNER :{BLACK}所有者:{LTBLUE}{STRING}
+STR_01A8_LOCAL_AUTHORITY :{BLACK} 地方官庁:{LTBLUE}{STRING}
+STR_01A9_NONE :何も
+STR_01AA_NAME :{BLACK}名前
+STR_01AB :{BLACK}{TINYFONT}{STRING}
+
+############ range for days starts
+STR_01AC_1ST :1日
+STR_01AD_2ND :2日
+STR_01AE_3RD :3日
+STR_01AF_4TH :4日
+STR_01B0_5TH :5日
+STR_01B1_6TH :6日
+STR_01B2_7TH :7日
+STR_01B3_8TH :8日
+STR_01B4_9TH :9日
+STR_01B5_10TH :10日
+STR_01B6_11TH :11日
+STR_01B7_12TH :12日
+STR_01B8_13TH :13日
+STR_01B9_14TH :14日
+STR_01BA_15TH :15日
+STR_01BB_16TH :16日
+STR_01BC_17TH :17日
+STR_01BD_18TH :18日
+STR_01BE_19TH :19日
+STR_01BF_20TH :20日
+STR_01C0_21ST :21日
+STR_01C1_22ND :22日
+STR_01C2_23RD :23日
+STR_01C3_24TH :24日
+STR_01C4_25TH :25日
+STR_01C5_26TH :26日
+STR_01C6_27TH :27日
+STR_01C7_28TH :28日
+STR_01C8_29TH :29日
+STR_01C9_30TH :30日
+STR_01CA_31ST :31日
+############ range for days ends
+
+STR_01CB :{TINYFONT}{COMMA}
+
+STR_01CE_CARGO_ACCEPTED :{BLACK}受け取る集荷: {LTBLUE}
+
+STR_01D1_8 :({COMMA}/8 {STRING})
+STR_01D2_JAZZ_JUKEBOX :{WHITE}ジャズジュークボックス
+STR_01D3_SOUND_MUSIC :エフェクト/音楽
+STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}エフェクト/音楽のウィンドウを表示します
+STR_01D5_ALL :{TINYFONT}すべて
+STR_01D6_OLD_STYLE :{TINYFONT}旧式
+STR_01D7_NEW_STYLE :{TINYFONT}新式
+STR_01D8_EZY_STREET :{TINYFONT}Ezy Street
+STR_01D9_CUSTOM_1 :{TINYFONT}カスタム 1
+STR_01DA_CUSTOM_2 :{TINYFONT}カスタム 2
+STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}音楽の音量
+STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}エフェクトの音量
+STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX
+STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}選択部分の前の曲へジャンプ
+STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}選択部分の次の曲へジャンプ
+STR_01E0_STOP_PLAYING_MUSIC :{BLACK}音楽の再生を停止
+STR_01E1_START_PLAYING_MUSIC :{BLACK}音楽の再生を開始
+STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}音楽とエフェクトの音量を設定するには、スライダーをドラッグします
+STR_01E3 :{DKGREEN}{TINYFONT}--
+STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA}
+STR_01E5 :{DKGREEN}{TINYFONT}{COMMA}
+STR_01E6 :{DKGREEN}{TINYFONT}------
+STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}"
+STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}曲{SETX 88}タイトル
+STR_01E9_SHUFFLE :{TINYFONT}シャッフル
+STR_01EA_PROGRAM :{TINYFONT}{BLACK}プレイリスト
+STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}プレイリストの選択
+STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA} "{STRING}"
+STR_01ED :{TINYFONT}{LTBLUE}{COMMA} "{STRING}"
+STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}曲のリスト
+STR_01EF_PROGRAM :{TINYFONT}{BLACK}プレイリスト - '{STRING}'
+STR_01F0_CLEAR :{TINYFONT}{BLACK}消去
+STR_01F1_SAVE :{TINYFONT}{BLACK}保存
+STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}再生中のプレイリスト
+STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}プレイリスト「すべての曲」を選択します
+STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}プレイリスト「旧式音楽」を選択します
+STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}プレイリスト「新式音楽」を選択します
+STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}プレイリスト「カスタム 1」を選択します
+STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}プレイリスト「カスタム 2」を選択します
+STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}選択したプレイリストの内容を消去します(カスタム 1/2 のみ)。
+STR_01F9_SAVE_MUSIC_SETTINGS :{BLACK}音楽の設定を保存
+STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}選択したプレイリストへ追加するには、曲をクリックします(カスタム 1/2 のみ)。
+STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}プレイリストのシャッフルを入/切にします
+STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}曲の選択のウィンドウ表示します
+STR_01FE_DIFFICULTY :{BLACK}難しさ({STRING})
+STR_01FF :{TINYFONT}{BLACK}{DATE_LONG}
+STR_0200_LAST_MESSAGE_NEWS_REPORT :最後メッセージ
+STR_0201_MESSAGE_SETTINGS :メッセージ設定
+STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}最後メッセージそれとも、メッセージ設定を見せます
+STR_0204_MESSAGE_OPTIONS :{WHITE}メッセージ設定
+STR_0205_MESSAGE_TYPES :{BLACK}メッセージタイプ:
+STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}プレヤーのバス停/駅などへ乗り物の初めての到着
+STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}競争者のバス停/駅などへ乗り物の初めての到着
+STR_0208_ACCIDENTS_DISASTERS :{YELLOW}事件/災害
+STR_0209_COMPANY_INFORMATION :{YELLOW}会社情報
+STR_020A_ECONOMY_CHANGES :{YELLOW}経済の変化
+STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}プレヤーの乗り物についての情報
+STR_020C_NEW_VEHICLES :{YELLOW}乗り物の新登場
+STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}貨物の受け取りの変化
+STR_020E_SUBSIDIES :{YELLOW}助成金
+STR_020F_GENERAL_INFORMATION :{YELLOW}一般情報
+STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...前の行き先から遠すぎます
+STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}{NUM}{}({STRING} レベル) に当たった最高の会社
+STR_TOP_COMPANIES_NETWORK_GAME :{BIGFONT}{BLACK}{NUM}の会社リーグ表
+STR_0212 :{BIGFONT}{COMMA}.
+STR_0213_BUSINESSMAN :ビジネスマン
+STR_0214_ENTREPRENEUR :企業家
+STR_0215_INDUSTRIALIST :産業主義者
+STR_0216_CAPITALIST :資本家
+STR_0217_MAGNATE :大立者
+STR_0218_MOGUL :大御所
+STR_0219_TYCOON_OF_THE_CENTURY :大将軍
+STR_HIGHSCORE_NAME :{BIGFONT}{PLAYERNAME}、 {COMPANY}
+STR_021B_ACHIEVES_STATUS :{BLACK}{BIGFONT}{COMPANY} は「{STRING}」に当たった!
+STR_021C_OF_ACHIEVES_STATUS :{WHITE}{BIGFONT}{PLAYERNAME}({COMPANY})は「{STRING}」に当たった!
+STR_021F :{BLUE}{COMMA}
+STR_0220_CREATE_SCENARIO :{BLACK}シナリオを作成
+STR_0221_OPENTTD :{YELLOW}OpenTTD
+STR_0222_SCENARIO_EDITOR :{YELLOW}シナリオエディタ
+STR_0223_LAND_GENERATION :{WHITE}地勢の生成
+STR_0224 :{BLACK}{UPARROW}
+STR_0225 :{BLACK}{DOWNARROW}
+STR_0226_RANDOM_LAND :{BLACK}ランダムな地勢
+STR_0227_RESET_LAND :{BLACK}地勢をリセット
+STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}あげる/下げる地域のサイズを拡大します
+STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}あげる/下げる地域のサイズを縮小します
+STR_022A_GENERATE_RANDOM_LAND :{BLACK}ランダムな地勢を生成します
+STR_022B_RESET_LANDSCAPE :{BLACK}地勢をリセットします
+STR_022C_RESET_LANDSCAPE :{WHITE}地勢のリセット
+STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}地勢をリセットしてもよろしいですか?
+STR_022E_LANDSCAPE_GENERATION :{BLACK}地勢の生成
+STR_022F_TOWN_GENERATION :{BLACK}市町村の生成
+STR_0230_INDUSTRY_GENERATION :{BLACK}産業の生成
+STR_0231_ROAD_CONSTRUCTION :{BLACK}道路の生成
+STR_0233_TOWN_GENERATION :{WHITE}市町村の生成
+STR_0234_NEW_TOWN :{BLACK}新規町
+STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}新規町を建造します
+STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}ここで町が建造できません...
+STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...他の町の近すぎます
+STR_0239_SITE_UNSUITABLE :{WHITE}...地域が不適当です
+STR_023A_TOO_MANY_TOWNS :{WHITE}...市町村数の制限を超えています
+STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}町のサイズをあげます
+STR_023C_EXPAND :{BLACK}拡大
+STR_023D_RANDOM_TOWN :{BLACK}ランダムな町
+STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}ランダムなところに町を建造します
+STR_023F_INDUSTRY_GENERATION :{WHITE}産業の生成
+STR_0240_COAL_MINE :{BLACK}炭坑
+STR_0241_POWER_STATION :{BLACK}発電所
+STR_0242_SAWMILL :{BLACK}製材工場
+STR_0243_FOREST :{BLACK}森林
+STR_0244_OIL_REFINERY :{BLACK}製油所
+STR_0246_FACTORY :{BLACK}工場
+STR_0247_STEEL_MILL :{BLACK}製鋼所
+STR_0248_FARM :{BLACK}農場
+STR_0249_IRON_ORE_MINE :{BLACK}鉄鉱石鉱山
+STR_024A_OIL_WELLS :{BLACK}油井
+STR_024B_BANK :{BLACK}銀行
+STR_024C_PAPER_MILL :{BLACK}製紙工場
+STR_024D_FOOD_PROCESSING_PLANT :{BLACK}食品加工場
+STR_024E_PRINTING_WORKS :{BLACK}印刷所
+STR_024F_GOLD_MINE :{BLACK}金鉱
+STR_0250_LUMBER_MILL :{BLACK}製材所
+STR_0251_FRUIT_PLANTATION :{BLACK}果物農園
+STR_0252_RUBBER_PLANTATION :{BLACK}ゴム園
+STR_0253_WATER_SUPPLY :{BLACK}給水設備
+STR_0254_WATER_TOWER :{BLACK}給水塔
+STR_0255_DIAMOND_MINE :{BLACK}ダイヤモンド鉱山
+STR_0256_COPPER_ORE_MINE :{BLACK}銅鉱石鉱山
+STR_0285_CAN_T_BUILD_HERE :{WHITE}そこに {STRING} を建てられません
+STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...まずは町を建造しなければなりません
+STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...一町内に一つしか建造できません
+STR_0296_QUIT :出口
+STR_0298_LOAD_SCENARIO :{WHITE}シナリオを開く
+STR_0299_SAVE_SCENARIO :{WHITE}シナリオを保存
+STR_029A_PLAY_SCENARIO :{BLACK}シナリオをプレイ
+STR_029C_QUIT_EDITOR :{WHITE}エディタの終了
+STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...人口が1200人以上の市町のみに建造できます
+STR_029E_MOVE_THE_STARTING_DATE :{BLACK}開始日を1年間減らします
+STR_029F_MOVE_THE_STARTING_DATE :{BLACK}開始日を1年間増やします
+STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...橋の端は両方土地上に建造しなければなりません
+STR_02A1_SMALL :{BLACK}小さい
+STR_02A2_MEDIUM :{BLACK}町
+STR_02A3_LARGE :{BLACK}大きい
+STR_02A4_SELECT_TOWN_SIZE :{BLACK}町のサイズを選択します
+STR_02A5_TOWN_SIZE :{YELLOW}町のサイズ:
+
+STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}最後のメッセージ/報道を表示します
+STR_SUMMARY :粗筋
+STR_02BA :{SILVER}- - {COMPANY} - -
+STR_02BB_TOWN_DIRECTORY :市町村のリスト
+STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}乗り物の名称
+STR_02BD :{BLACK}{STRING}
+STR_02BE_DEFAULT :デフォルト
+STR_02BF_CUSTOM :カスタム
+STR_02C0_SAVE_CUSTOM_NAMES :{BLACK}カスタム名称を保存
+STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}乗り物の名称の選択
+STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}カスタマイズした乗り物の名称を保存します
+
+STR_CHECKMARK :{CHECKMARK}
+############ range for menu starts
+STR_02C3_GAME_OPTIONS :ゲーム設定
+STR_02C5_DIFFICULTY_SETTINGS :難しさ設定
+STR_02C7_CONFIG_PATCHES :パッチの設定
+STR_GAMEOPTMENU_0A :
+STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}市町村名の表示
+STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}駅/バス停名の表示
+STR_02CE_SIGNS_DISPLAYED :{SETX 12}標示の表示
+STR_02D0_FULL_ANIMATION :{SETX 12}高級のアニメーション
+STR_02D2_FULL_DETAIL :{SETX 12}高級の画像
+STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}透明な建物
+STR_TRANSPARENT_SIGNS :{SETX 12}澄む駅看板
+############ range ends here
+
+############ range for menu starts
+STR_02D5_LAND_BLOCK_INFO :地域情報
+STR_02D6 :
+STR_02D7_SCREENSHOT_CTRL_S :スクリーンショット(Ctrl-S)
+STR_02D8_GIANT_SCREENSHOT_CTRL_G :大型スクリーンショット(Ctrl-G)
+STR_02D9_ABOUT_OPENTTD :'OpenTTD'とは?
+############ range ends here
+
+STR_02DB_OFF :{BLACK}切
+STR_02DA_ON :{BLACK}入
+STR_02DC_DISPLAY_SUBSIDIES :{BLACK}助成金を表示
+STR_02DD_SUBSIDIES :助成金
+STR_02DE_MAP_OF_WORLD :世界の地図
+STR_02DF_TOWN_DIRECTORY :市町村のリスト
+STR_TOWN_POPULATION :{BLACK}世界人口:{COMMA}
+
+STR_02E0_CURRENCY_UNITS :{BLACK}通貨単位
+STR_02E1 :{BLACK}{SKIP}{STRING}
+STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}通貨単位の選択
+STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING}
+STR_02E6_ROAD_VEHICLES :{BLACK}バス/トラック
+STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING}
+STR_02E9_DRIVE_ON_LEFT :左に運転します
+STR_02EA_DRIVE_ON_RIGHT :右に運転します
+STR_02EB_TOWN_NAMES :{BLACK}市町村名
+STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}市町村名の種類の選択
+
+STR_02F4_AUTOSAVE :{BLACK}自動保存
+STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}自動保存の間隔を選択します
+STR_02F7_OFF :切
+STR_02F8_EVERY_3_MONTHS :毎3月
+STR_02F9_EVERY_6_MONTHS :毎6月
+STR_02FA_EVERY_12_MONTHS :毎12月
+STR_02FB_START_A_NEW_GAME :{BLACK}新しいゲームを始めます
+STR_02FC_LOAD_A_SAVED_GAME :{BLACK}ゲームを開きます
+STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}カスタムシナリオを作成します
+STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}一人プレイを選択します
+STR_0300_SELECT_MULTIPLAYER_GAME :{BLACK}多人数プレイ(2〜8人)を選択します
+STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}ゲーム設定を見せます
+STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}難しさ設定を見せます
+STR_0303_START_A_NEW_GAME_USING :{BLACK}カスタムシナリオを使用して新規ゲームを開始します
+STR_0304_QUIT :{BLACK}出口
+STR_0305_QUIT_OPENTTD :{BLACK}'OpenTTD'を止めます
+STR_0307_OPENTTD :{WHITE}OpenTTD {REV}
+STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}…町の外に建てません
+STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}温帯地域を選択します
+STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}亜寒帯地域を選択します
+STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}亜熱帯地域を選択します
+STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}おもちゃの国を選択します
+STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}新規産業の建造に資金を供給します
+
+############ range for menu starts
+STR_0313_FUND_NEW_INDUSTRY :新規産業の建造に資金を出す
+############ range ends here
+
+STR_0314_FUND_NEW_INDUSTRY :{WHITE}新規産業の建造に資金の供給
+STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}…町の外に建てません
+STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}...雨林地域のみに建造できます
+STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...砂漠地域のみに建造できます
+STR_0319_PAUSED :{YELLOW}**ポーズ**
+
+STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}スクリーンショットを '{STRING}' に正常に保存しました
+STR_031C_SCREENSHOT_FAILED :{WHITE}スクリーンショットが失敗しました!
+
+STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}将来用に土地を購入
+STR_032F_AUTOSAVE :{RED}自動保存
+STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}'Ezy Street 式の音楽'のプレイリストを選択します
+
+STR_0335_6 :{BLACK}6
+STR_0336_7 :{BLACK}7
+
+############ start of townname region
+STR_TOWNNAME_ORIGINAL_ENGLISH :イギリス
+STR_TOWNNAME_FRENCH :フランス
+STR_TOWNNAME_GERMAN :ドイツ
+STR_TOWNNAME_ADDITIONAL_ENGLISH :イギリス(おまけ)
+STR_TOWNNAME_LATIN_AMERICAN :ラテンアメリカ
+STR_TOWNNAME_SILLY :愚
+STR_TOWNNAME_SWEDISH :スウェーデン
+STR_TOWNNAME_POLISH :ポーランド
+STR_TOWNNAME_SLOVAKISH :スロバキア
+STR_TOWNNAME_NORWEGIAN :ノルウェー
+STR_TOWNNAME_HUNGARIAN :洪牙利
+STR_TOWNNAME_AUSTRIAN :オーストリア
+STR_TOWNNAME_ROMANIAN :ルーマニア
+STR_TOWNNAME_CZECH :チェコ
+STR_TOWNNAME_SWISS :瑞西
+STR_TOWNNAME_DANISH :デーン
+STR_TOWNNAME_TURKISH :土国
+STR_TOWNNAME_ITALIAN :イタリ
+STR_TOWNNAME_CATALAN :カタラン
+############ end of townname region
+
+STR_CURR_YEN :日本の円(¥)
+
+
+STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+
+
+STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+
+STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+
+STR_AUTOSAVE_1_MONTH :毎月
+
+STR_MONTH_JAN :1月
+STR_MONTH_FEB :2月
+STR_MONTH_MAR :3月
+STR_MONTH_APR :4月
+STR_MONTH_MAY :5月
+STR_MONTH_JUN :6月
+STR_MONTH_JUL :7月
+STR_MONTH_AUG :8月
+STR_MONTH_SEP :9月
+STR_MONTH_OCT :10月
+STR_MONTH_NOV :11月
+STR_MONTH_DEC :12月
+
+
+STR_TONS :トン
+
+STR_SMALL_RIGHT_ARROW :{TINYFONT}{RIGHTARROW}
+
+
+STR_TRAIN_IS_LOST :{WHITE}電車{COMMA}は迷います
+STR_TRAIN_IS_UNPROFITABLE :{WHITE}去年、電車{COMMA}の取り柄は{CURRENCY}
+
+# Start of order review system.
+# DON'T ADD OR REMOVE LINES HERE
+STR_TRAIN_HAS_TOO_FEW_ORDERS :{WHITE}電車{COMMA}のルートは過小駅があります
+STR_TRAIN_HAS_VOID_ORDER :{WHITE}電車{COMMA}は 空々予定があります
+STR_TRAIN_HAS_DUPLICATE_ENTRY :{WHITE}電車{COMMA}のルートはデュープリケート 駅があります
+STR_TRAIN_HAS_INVALID_ENTRY :{WHITE}電車{COMMA} のルートは無効な駅があります
+# end of order system
+
+STR_TRAIN_AUTORENEW_FAILED :{WHITE}電車{COMMA} のオート取り替えられません (お金のかぎり)
+STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}付け替えの後で、電車{COMMA}は ちょっと長いです
+
+
+
+
+
+
+STR_CONFIG_PATCHES_LIVERIES_NONE :何も
+
+
+
+
+
+
+
+STR_CONFIG_PATCHES_INT32 :{NUM}
+STR_CONFIG_PATCHES_CURRENCY :{CURRENCY}
+
+
+STR_TEMPERATE_LANDSCAPE :温帯国
+STR_SUB_ARCTIC_LANDSCAPE :北極国
+STR_SUB_TROPICAL_LANDSCAPE :亜熱帯国
+STR_TOYLAND_LANDSCAPE :おまちゃ国
+
+
+
+
+
+
+STR_WAYPOINT_VIEWPORT :{WHITE}{WAYPOINT}
+STR_WAYPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{WAYPOINT}
+STR_WAYPOINT_RAW :{WAYPOINT}
+
+
+
+
+
+
+
+STR_TREES_RANDOM_TYPE :{BLACK}ランドム種類の木
+STR_TREES_RANDOM_TYPE_TIP :{BLACK}ランドム種類の木を植えます
+
+
+
+
+
+
+
+
+
+
+STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{INDUSTRY}
+
+
+
+TEMP_AI_IN_PROGRESS :{WHITE}いらっしゃいませ!このAIは発展中です。問題があったら、スクリーンショットを取って、フォーラムに送ってください
+TEMP_AI_ACTIVATED :{WHITE}注意:AIはまだアルファです!今、貨物自動車とバスだけ疲われます!
+TEMP_AI_MULTIPLAYER :{WHITE}注意:AIはまだ実験段階です!問題があったら、英語でtruelight@openttd.orgをメールしてください。
+
+############ network gui strings
+
+
+
+
+STR_NETWORK_GAME_NAME :{BLACK}名前
+
+
+STR_NETWORK_GENERAL_ONLINE :{BLACK}{COMMA}/{COMMA} - {COMMA}/{COMMA}
+STR_ORANGE :{ORANGE}{STRING}
+STR_NETWORK_LANGUAGE :{SILVER}国語: {WHITE}{STRING}
+
+
+
+
+STR_NETWORK_INTERNET :インターネット
+STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+STR_NETWORK_COMBO3 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+STR_NETWORK_COMBO4 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+STR_NETWORK_COMBO5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
+
+############ Leave those lines in this order!!
+STR_NETWORK_LANG_ENGLISH :英語
+STR_NETWORK_LANG_GERMAN :ドイツ語
+STR_NETWORK_LANG_FRENCH :フランス語
+############ End of leave-in-this-order
+
+
+
+
+
+
+
+############ Leave those lines in this order!!
+
+############ End of leave-in-this-order
+
+
+
+
+############ Leave those lines in this order!!
+############ End of leave-in-this-order
+
+
+
+
+
+############ end network gui strings
+
+
+
+
+##### PNG-MAP-Loader
+
+
+
+##id 0x0800
+STR_0800_COST :{TINYFONT}{RED}値段:{CURRENCY}
+STR_0801_COST :{RED}値段: {CURRENCY}
+STR_0802_INCOME :{TINYFONT}{GREEN}所得:{CURRENCY}
+STR_0803_INCOME :{GREEN}所得:{CURRENCY}
+STR_0805_ESTIMATED_COST :{WHITE}評価の価値:{CURRENCY}
+STR_0807_ESTIMATED_INCOME :{WHITE}評価の所得:{CURRENCY}
+STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}ここに土地が上げられません
+STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}ここに土地が下げられません
+STR_080A_ROCKS :岩石
+STR_080B_ROUGH_LAND :でこぼこの土地
+STR_080C_BARE_LAND :裸地
+STR_080D_GRASS :草地
+STR_080E_FIELDS :田畑
+STR_080F_SNOW_COVERED_LAND :積雪地域
+STR_0810_DESERT :砂漠
+
+##id 0x1000
+STR_1004_TOO_HIGH :{WHITE}ちょっと高いです
+STR_1007_ALREADY_BUILT :{WHITE}…もう建てました
+STR_100A_RAILROAD_CONSTRUCTION :{WHITE}鉄道の建造
+STR_TITLE_ELRAIL_CONSTRUCTION :{WHITE}電鉄建造
+STR_100B_MONORAIL_CONSTRUCTION :{WHITE}モノレールの建造
+STR_100C_MAGLEV_CONSTRUCTION :{WHITE}マグレブの建造
+STR_100D_SELECT_RAIL_BRIDGE :{WHITE}鉄道の橋の選択
+STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}ここに電車庫が建造できません
+STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}ここに駅が建造できません
+STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}ここに信号が建造できません
+STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}ここに線路が建造できません
+STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}ここから線路が廃止できません
+STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}ここから信号が廃止できません
+STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}電車庫の配置
+STR_1015_RAILROAD_CONSTRUCTION :鉄道の建造
+STR_TOOLB_ELRAIL_CONSTRUCTION :電鉄建造
+STR_1016_MONORAIL_CONSTRUCTION :モノレールの建造
+STR_1017_MAGLEV_CONSTRUCTION :マグレブの建造
+STR_1018_BUILD_RAILROAD_TRACK :{BLACK}線路を建造します
+STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}(電車の建造や整備のための)電車庫を建造します
+STR_101A_BUILD_RAILROAD_STATION :{BLACK}駅を建造します
+STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}鉄道の信号を建造します
+STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}鉄道の橋を建造します
+STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}鉄道のトンネルを建造します
+STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}線路と信号の建造/廃止を切り替えます
+STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}橋の選択 - お好きな橋を建造するにはクリックします
+STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}電車庫の配置を選択します
+STR_1021_RAILROAD_TRACK :線路
+STR_1023_RAILROAD_TRAIN_DEPOT :電車庫
+STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...この土地は他の会社に所有されています
+
+
+
+##id 0x1800
+STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}ここから道路が廃止できません...
+STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}車庫の配置
+STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}ここに車庫が建造できません...
+STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}バス停が建造できません...
+STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}荷役所が建造できません...
+STR_180A_ROAD_CONSTRUCTION :道路の建造
+STR_180B_BUILD_ROAD_SECTION :{BLACK}道路の部分を建造します
+STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}(バス、トラックの建造、整備のための)車庫を建造します
+STR_180D_BUILD_BUS_STATION :{BLACK}バス停を建造します
+STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}荷役所を建造します
+STR_180F_BUILD_ROAD_BRIDGE :{BLACK}道路の端を建造します
+STR_1810_BUILD_ROAD_TUNNEL :{BLACK}道路のトンネルを建造します
+STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}道路の建造/廃止を切り替えます
+STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}車庫の配置の選択
+STR_1814_ROAD :道路
+STR_1815_ROAD_WITH_STREETLIGHTS :街路照明のある道路
+STR_1816_TREE_LINED_ROAD :並木道
+STR_1817_ROAD_VEHICLE_DEPOT :車庫
+STR_1818_ROAD_RAIL_LEVEL_CROSSING :踏切
+
+##id 0x2000
+STR_2000_TOWNS :{WHITE}町
+STR_TOWN_LABEL_POP :{WHITE}{TOWN} ({COMMA})
+STR_TOWN_LABEL :{WHITE}{TOWN}
+STR_TOWN_LABEL_TINY_BLACK :{TINYFONT}{BLACK}{TOWN}
+STR_TOWN_LABEL_TINY_WHITE :{TINYFONT}{WHITE}{TOWN}
+STR_2002 :{TINYFONT}{BLACK}{STRING}
+STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}まずは建物を破壊しなければなりません
+STR_2005 :{WHITE}{TOWN}
+STR_2006_POPULATION :{BLACK}人口:{ORANGE}{COMMA}人{BLACK} 建物:{ORANGE}{COMMA}戸
+STR_2007_RENAME_TOWN :町名を変更
+STR_2008_CAN_T_RENAME_TOWN :{WHITE}町名が変更できません...
+STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN}の町議会は許可しません
+STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}町名 - 画面をその町に集中するには、クリックします
+STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}画面を町に集中します
+STR_200C_CHANGE_TOWN_NAME :{BLACK}町名を変更します
+STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}先月の乗客:{ORANGE}{COMMA}人{BLACK} 最大:{ORANGE}{COMMA}人
+STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}先月の郵便物:{ORANGE}{COMMA}個{BLACK} 最大:{ORANGE}{COMMA}個
+STR_200F_TALL_OFFICE_BLOCK :超高層ビル
+STR_2010_OFFICE_BLOCK :オフィスビル
+STR_2011_SMALL_BLOCK_OF_FLATS :アパート
+STR_2012_CHURCH :チャーチ
+STR_2013_LARGE_OFFICE_BLOCK :大型オフィスビル
+STR_2014_TOWN_HOUSES :マンション
+STR_2015_HOTEL :ホテル
+STR_2016_STATUE :彫像
+STR_2017_FOUNTAIN :噴水
+STR_2018_PARK :公園
+STR_2019_OFFICE_BLOCK :オフィスビル
+STR_201A_SHOPS_AND_OFFICES :雑居ビル
+STR_201B_MODERN_OFFICE_BUILDING :近代のオフィスビル
+STR_201C_WAREHOUSE :倉庫
+STR_201D_OFFICE_BLOCK :オフィスビル
+STR_201E_STADIUM :スタジアム
+STR_201F_OLD_HOUSES :老舗
+STR_2020_LOCAL_AUTHORITY :{BLACK}町議会
+STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}町議会の情報を表示します
+STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN}の町議会
+STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}会社の町内の世評:
+STR_2024 :{YELLOW}{COMPANY}{PLAYERNAME}: {ORANGE}{STRING}
+STR_2025_SUBSIDIES :{WHITE}助成金
+STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}次の運送経路に助成金を提案します:
+STR_2027_FROM_TO :{ORANGE}{STRING}を{STRING}から{STRING}へ
+STR_2028_BY :{YELLOW} ({DATE_SHORT}の前)
+STR_202A_NONE :{ORANGE}何も
+STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}既に助成金を受けている運送経路:
+STR_202C_FROM_TO :{ORANGE}{STRING}{STATION}から{STATION}まで{YELLOW} ({COMPANY}
+STR_202D_UNTIL :{YELLOW}、{DATE_SHORT}まで)
+STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}助成金の提案の有効期限が切られた:{}{}{STRING}を{STRING}から{STRING}への運送経路は今から助成金を受けない。
+STR_2036_COTTAGES :小屋
+STR_2037_HOUSES :家
+STR_2038_FLATS :アパート
+STR_2039_TALL_OFFICE_BLOCK :大型オフィスビル
+STR_203A_SHOPS_AND_OFFICES :雑居
+STR_203B_SHOPS_AND_OFFICES :雑居
+STR_203C_THEATER :劇場
+STR_203D_STADIUM :スタジアム
+STR_203E_OFFICES :オフィスビル
+STR_203F_HOUSES :家
+STR_2040_CINEMA :映画館
+STR_2041_SHOPPING_MALL :デパート
+STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}この町の起こせる動作 - 詳しくは項目をクリックします
+STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}上記のリストの洗濯中の動作を起こします。
+STR_2045_ACTIONS_AVAILABLE :{BLACK}起こせる動作:
+STR_2046_SMALL_ADVERTISING_CAMPAIGN :小型広告キャンペーン
+STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :中型広告キャンペーン
+STR_2048_LARGE_ADVERTISING_CAMPAIGN :大型広告キャンペーン
+STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :道路再建を出資
+STR_204A_BUILD_STATUE_OF_COMPANY :会社長の彫像を建造
+STR_204B_FUND_NEW_BUILDINGS :市街地開発を出資
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :地方自治体を買収します
+STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} あなたの運送経路の利用率を増やすには、町内の小型広告キャンペーンを行います。{} 価値:{CURRENCY}
+STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} あなたの運送経路の利用率を増やすには、町内の中型広告キャンペーンを行います。{} 価値:{CURRENCY}
+STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} あなたの運送経路の利用率を増やすには、町内の大型広告キャンペーンを行います。{} 価値:{CURRENCY}
+STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} 町内の道路の再建を出資します。最高 6 ヶ月間まで、道路交通に途絶を与えます。{} 価値:{CURRENCY}
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} 名声を増殖します地方自治体を買収します。けれども、あぶないです!{} 値段: {CURRENCY}
+STR_2056 :{TINYFONT}{WHITE}{TOWN}
+STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA})
+
+STR_INDUSTRY :{INDUSTRY}
+STR_TOWN :{TOWN}
+STR_INDUSTRY_FORMAT :{TOWN} {STRING}
+STR_STATION :{STATION}
+
+##id 0x2800
+STR_2802_TREES :{WHITE}木
+STR_2803_TREE_ALREADY_HERE :{WHITE}...木はもうあります
+STR_2806 :{WHITE}{STRING}
+STR_280E_TREES :木
+
+##id 0x3000
+STR_3003_NUMBER_OF_TRACKS :{BLACK}線路数
+STR_3004_PLATFORM_LENGTH :{BLACK}ホームの長さ
+STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}他の駅に近すぎます
+STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}町内に駅/バス停/荷役所が多すぎます
+STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}駅/荷役所が多すぎます
+STR_3008A_TOO_MANY_BUS_STOPS :{WHITE}バス停が多すぎます
+STR_3008B_TOO_MANY_TRUCK_STOPS :{WHITE}荷役所が多すぎます
+STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}他の駅/荷役所に近すぎます
+STR_300A_0 :{WHITE}{STATION} {STATIONFEATURES}
+STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}まずは駅を破壊しなければなりません
+STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}他の空港に近すぎます
+STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}まずは空港を破壊しなければなりません
+
+STR_3030_RENAME_STATION_LOADING :駅/荷役所の名称の変更
+STR_3031_CAN_T_RENAME_STATION :{WHITE}駅名が変更できません...
+
+############ range for rating starts
+STR_3035_APPALLING :最低
+STR_3036_VERY_POOR :とても悪い
+STR_3037_POOR :悪い
+STR_3038_MEDIOCRE :平凡
+STR_3039_GOOD :良い
+STR_303A_VERY_GOOD :とても良い
+STR_303B_EXCELLENT :すばらしい
+STR_303C_OUTSTANDING :最高
+############ range for rating ends
+
+STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA}%)
+STR_3049_0 :{YELLOW}{STATION} {STATIONFEATURES}
+STR_304A_NONE :{YELLOW}- 何も-
+STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}駅の線路数を選択します
+STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}駅のホームの長さを選択します
+STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}バス停の配置を選択します
+STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}荷役所の配置を選択します
+STR_3054_SHOW_STATION_RATINGS :{BLACK}駅の評価を表示します
+STR_3055_CHANGE_NAME_OF_STATION :{BLACK}駅名を変更します
+STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}受け取る貨物のリストを表示します
+STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}空港のサイズ/種類を選択します
+STR_305C_0 :{STATION} {STATIONFEATURES}
+STR_STATION_SIGN_TINY :{TINYFONT}{STATION}
+STR_305E_RAILROAD_STATION :駅
+STR_305F_AIRCRAFT_HANGAR :格納庫
+STR_3060_AIRPORT :空港
+STR_3061_TRUCK_LOADING_AREA :荷役所
+STR_3062_BUS_STATION :バス停
+STR_3063_SHIP_DOCK :波止場
+STR_3068_DOCK :{WHITE}波止場
+STR_3069_BUOY :ブイ
+STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...駅が広すぎます
+STR_USE_CTRL_TO_SELECT_MORE :{BLACK}もっと事を選ぶために、CTRLをプッシュ
+
+STR_UNDEFINED :(ハンナ・ストリング)
+STR_STAT_CLASS_DFLT :デフォルト駅
+STR_STAT_CLASS_WAYP :通過点
+
+##id 0x3800
+STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}造船所の配置
+STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}造船所の配置を選択します
+STR_3804_WATER :水
+STR_3806_SHIP_DEPOT :造船所
+
+##id 0x4000
+STR_4000_SAVE_GAME :{WHITE}ゲームを保存
+STR_4001_LOAD_GAME :{WHITE}ゲームを開く
+STR_4002_SAVE :{BLACK}保存
+STR_4003_DELETE :{BLACK}削除
+STR_4004 :{COMPANY}、 {DATE_LONG}
+STR_4005_BYTES_FREE :{BLACK}{COMMA} MB 使用可能
+STR_4007_GAME_SAVE_FAILED :{WHITE}ゲームの保存が失敗しました
+STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}ファイルを削除できません
+STR_4009_GAME_LOAD_FAILED :{WHITE}ゲームの読み込むが失敗しました
+STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}ドライブ、フォルダ、ゲームファイルのリスト
+STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}ゲームのファイル名
+STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}選択したゲームを削除します
+STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}指定したファイル名に現在のゲームを保存します
+STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}新規ゲーム種類の選択
+STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}シナリオ(緑)、プリセットゲーム(青)もしくは新規ランダムゲームを選択します
+STR_4010_GENERATE_RANDOM_NEW_GAME :新規ランダムゲームを作成
+
+##id 0x4800
+STR_4801 :{WHITE}{INDUSTRY}
+STR_4802_COAL_MINE :炭坑
+STR_4803_POWER_STATION :発電所
+STR_4804_SAWMILL :製材工場
+STR_4805_FOREST :森林
+STR_4806_OIL_REFINERY :石油精製所
+STR_4808_FACTORY :工場
+STR_4809_PRINTING_WORKS :印刷所
+STR_480A_STEEL_MILL :製鋼所
+STR_480B_FARM :農場
+STR_480C_COPPER_ORE_MINE :銅鉱石鉱山
+STR_480D_OIL_WELLS :油井
+STR_480E_BANK :銀行
+STR_480F_FOOD_PROCESSING_PLANT :食品加工場
+STR_4810_PAPER_MILL :製紙工場
+STR_4811_GOLD_MINE :金山
+STR_4812_BANK :銀行
+STR_4813_DIAMOND_MINE :ダイヤモンド鉱山
+STR_4814_IRON_ORE_MINE :鉄鉱石鉱山
+STR_4815_FRUIT_PLANTATION :果物農園
+STR_4816_RUBBER_PLANTATION :ゴム園
+STR_4817_WATER_SUPPLY :給水設備
+STR_4818_WATER_TOWER :給水塔
+STR_4819_FACTORY :工場
+STR_481A_FARM :農場
+STR_481B_LUMBER_MILL :製材所
+STR_481E_BATTERY_FARM :電池園
+STR_4826_SUGAR_MINE :砂糖鉱山
+
+############ range for requires starts
+############ range for requires ends
+
+STR_482F_COST :{BLACK}値段: {YELLOW}{CURRENCY}
+STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}この産業がここに建造できません...
+
+##id 0x5000
+STR_500D :{GOLD}{STRING}、{} {VELOCITY} {WHITE}{CURRENCY}
+STR_500E_SUSPENSION_STEEL :つり橋、鋼鉄製
+STR_500F_GIRDER_STEEL :けた橋、鋼鉄製
+STR_5010_CANTILEVER_STEEL :カンチレバー橋、鋼鉄製
+STR_5011_SUSPENSION_CONCRETE :つり橋、コンクリート製
+STR_5012_WOODEN :木製
+STR_5013_CONCRETE :コンクリート製
+STR_5014_TUBULAR_STEEL :鋼管橋、鋼鉄製
+STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}橋がここに建造できません...
+STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}トンネルがここに建造できません...
+STR_5017_RAILROAD_TUNNEL :鉄道トンネル
+STR_5018_ROAD_TUNNEL :道路トンネル
+
+##id 0x5800
+STR_5801_TRANSMITTER :送信機
+STR_5802_LIGHTHOUSE :灯台
+STR_5803_COMPANY_HEADQUARTERS :交通会社本部ビル
+STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...交通会社本部ビルがあります
+
+
+############ WARNING, using range 0x6000 for strings that are stored in the savegame
+############ These strings may never get a new id, or savegames will break!
+##id 0x6000
+STR_SV_EMPTY :
+STR_SV_UNNAMED :名前無し
+STR_SV_TRAIN_NAME :電車{COMMA}
+STR_SV_ROADVEH_NAME :車{COMMA}
+STR_SV_SHIP_NAME :シップ{COMMA}
+STR_SV_AIRCRAFT_NAME :飛行機{COMMA}
+
+STR_SV_STNAME :{STRING}
+STR_SV_STNAME_NORTH :{STRING} 北
+STR_SV_STNAME_SOUTH :{STRING} 南
+STR_SV_STNAME_EAST :{STRING} 東
+STR_SV_STNAME_WEST :{STRING} 西
+STR_SV_STNAME_CENTRAL :{STRING}中
+STR_SV_STNAME_TRANSFER :{STRING}乗り換え
+STR_SV_STNAME_HALT :{STRING} 停留
+STR_SV_STNAME_VALLEY :{STRING} 谷
+STR_SV_STNAME_HEIGHTS :{STRING}高地
+STR_SV_STNAME_WOODS :{STRING} 森
+STR_SV_STNAME_LAKESIDE :{STRING} 池側
+STR_SV_STNAME_EXCHANGE :{STRING}更代
+STR_SV_STNAME_AIRPORT :{STRING}空港
+STR_SV_STNAME_OILFIELD :{STRING}油田
+STR_SV_STNAME_MINES :{STRING} 鉱区
+STR_SV_STNAME_DOCKS :{STRING} 船渠
+STR_SV_STNAME_BUOY_1 :{STRING} ボイ1
+STR_SV_STNAME_BUOY_2 :{STRING} ボイ2
+STR_SV_STNAME_BUOY_3 :{STRING} ボイ3
+STR_SV_STNAME_BUOY_4 :{STRING} ボイ4
+STR_SV_STNAME_BUOY_5 :{STRING} ボイ5
+STR_SV_STNAME_BUOY_6 :{STRING} ボイ6
+STR_SV_STNAME_BUOY_7 :{STRING} ボイ7
+STR_SV_STNAME_BUOY_8 :{STRING} ボイ8
+STR_SV_STNAME_BUOY_9 :{STRING} ボイ9
+STR_SV_STNAME_ANNEXE :{STRING}新館
+STR_SV_STNAME_SIDINGS :{STRING} 側線
+STR_SV_STNAME_BRANCH :{STRING}支所
+STR_SV_STNAME_UPPER :{STRING}上
+STR_SV_STNAME_LOWER :{STRING}下
+STR_SV_STNAME_HELIPORT :{STRING}ヘリポート
+STR_SV_STNAME_FOREST :{STRING} 森林
+
+############ end of savegame specific region!
+
+##id 0x6800
+STR_6800_DIFFICULTY_LEVEL :{WHITE}難易度
+
+############ range for difficulty levels starts
+STR_6801_EASY :{BLACK}安い
+STR_6802_MEDIUM :{BLACK}中位
+STR_6803_HARD :{BLACK}難しい
+STR_6804_CUSTOM :{BLACK}カスタム
+############ range for difficulty levels ends
+
+############ range for difficulty settings starts
+STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}競争者数の上限:{ORANGE}{COMMA}
+STR_6806_COMPETITOR_START_TIME :{LTBLUE}競争者の開始遅延:{ORANGE}{STRING}
+STR_6807_NO_OF_TOWNS :{LTBLUE}市町村数:{ORANGE}{STRING}
+STR_6808_NO_OF_INDUSTRIES :{LTBLUE}工業数:{ORANGE}{STRING}
+STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}初期の最高貸付金:{ORANGE}{CURRENCY}
+STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}初期の金利:{ORANGE}{COMMA}%
+STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}乗り物の運転費:{ORANGE}{STRING}
+STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR :{LTBLUE}競争者の建造速度:{ORANGE}{STRING}
+STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}競争者の能力レベル:{ORANGE}{STRING}
+STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}乗り物の機能停止:{ORANGE}{STRING}
+STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}助成金の乗数:{ORANGE}{STRING}
+STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}建造の価値:{ORANGE}{STRING}
+STR_6813_ECONOMY :{LTBLUE}経済の傾向:{ORANGE}{STRING}
+STR_6814_TRAIN_REVERSING :{LTBLUE}電車の反転:{ORANGE}{STRING}
+STR_6815_DISASTERS :{LTBLUE}災害:{ORANGE}{STRING}
+STR_16816_CITY_APPROVAL :{LTBLUE}町議会の地域の再構築に関わる姿勢:{ORANGE}{STRING}
+############ range for difficulty settings ends
+
+STR_26816_NONE :何も
+STR_6816_LOW :低い
+STR_6817_NORMAL :通常
+STR_6818_HIGH :高い
+STR_6819 :{BLACK}{SMALLLEFTARROW}
+STR_681A :{BLACK}{SMALLRIGHTARROW}
+STR_681B_VERY_SLOW :特に遅い
+STR_681C_SLOW :遅い
+STR_681D_MEDIUM :中位
+STR_681E_FAST :速い
+STR_681F_VERY_FAST :特に速い
+STR_6820_LOW :低い
+STR_6821_MEDIUM :中位
+STR_6822_HIGH :高い
+STR_6823_NONE :なし
+STR_6824_REDUCED :軽減
+STR_6825_NORMAL :通常
+STR_6826_X1_5 :x1.5
+STR_6827_X2 :x2
+STR_6828_X3 :x3
+STR_6829_X4 :x4
+STR_682A_VERY_FLAT :特に平たい
+STR_682B_FLAT :平たい
+STR_682C_HILLY :丘陵地
+STR_682D_MOUNTAINOUS :山岳地
+STR_682E_STEADY :安定的
+STR_682F_FLUCTUATING :変動的
+STR_6830_IMMEDIATE :すぐに
+STR_6831_3_MONTHS_AFTER_PLAYER :開始から 3 ヶ月
+STR_6832_6_MONTHS_AFTER_PLAYER :開始から 6 ヶ月
+STR_6833_9_MONTHS_AFTER_PLAYER :開始から 9 ヶ月
+STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :線路終点と駅
+STR_6835_AT_END_OF_LINE_ONLY :線路終点のみ
+STR_6836_OFF :切
+STR_6837_ON :入
+STR_6838_SHOW_HI_SCORE_CHART :{BLACK}ハイスコアを表示
+
+##id 0x7000
+STR_7000 :
+STR_7001 :{WHITE}{COMPANY} {BLACK}{PLAYERNAME}
+STR_7008_COMPANY_NAME :{BLACK}会社名
+STR_7009_PRESIDENT_NAME :{BLACK}社長の名前
+STR_700A_COMPANY_NAME :会社名
+STR_700B_PRESIDENT_S_NAME :社長の名前
+STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}会社名が変更できません...
+STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}社長の名前が変更できません...
+STR_7010 :{WHITE}{NUM}
+STR_701E :{BLACK}-{CURRENCY64}
+STR_701F :{BLACK}+{CURRENCY64}
+STR_7021 :{COMPANY}{PLAYERNAME}
+STR_CURRCOMPACT :{CURRCOMPACT64}
+STR_7024 :{COMMA}
+STR_7028 :{BLACK}{CURRENCY64}
+STR_TRAINS :{WHITE}{COMMA} 電車
+STR_AIRCRAFT :{WHITE}{COMMA} 飛行機
+STR_7042_NONE :{WHITE}何も
+STR_7065 :{BLACK}{TINYFONT}{STRING}
+
+STR_LIVERY_BUS :バス
+
+
+##id 0x8000
+STR_8104_AIRCRAFT :飛行機
+
+##id 0x8800
+
+
+
+STR_UNKNOWN_DESTINATION :不明行き先
+STR_8816 :{BLACK}-
+
+
+STR_881F_BUILD_VEHICLE :{BLACK}車両を購入
+STR_8820_RENAME :{BLACK}名称を変更
+STR_8823_SKIP :{BLACK}スキップ
+STR_8824_DELETE :{BLACK}削除
+STR_8825_NON_STOP :{BLACK}直行便
+STR_8826_GO_TO :{BLACK}駅を選択
+STR_8827_FULL_LOAD :{BLACK}全負荷
+STR_8828_UNLOAD :{BLACK}降ろす
+STR_8829_ORDERS :{WHITE}{VEHICLE}(指令)
+STR_882A_END_OF_ORDERS :{SETX 10}- - 指名終了 - -
+STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING}
+STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}鉄道車両が購入できません...
+STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} 購入日付:{LTBLUE}{NUM}{BLACK} 価値:{LTBLUE}{CURRENCY}
+STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} 価値:{LTBLUE}{CURRENCY}
+STR_882E :{WHITE}{VEHICLE}
+STR_882F_LOADING_UNLOADING :{LTBLUE}積み降ろし中
+STR_TRAIN_MUST_BE_STOPPED :{WHITE}電車は車庫に止めなければ成らないんです
+STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}電車が電車庫へ回送できません...
+STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}これ以上の指令が追加できません
+STR_8832_TOO_MANY_ORDERS :{WHITE}指令が多すぎます
+STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}新規指令が挿入できません...
+STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}この指令が削除できません...
+STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}この指令が変更できません...
+STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}この車輌が移動できません...
+STR_8838_N_A :N/A{SKIP}
+STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}車両が販売できません...
+STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}電車庫への経路が見つけられません
+STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}電車が開始/停止できません...
+STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}補修間隔:{LTBLUE}{COMMA}日間{BLACK} 最新の補修:{LTBLUE}{DATE_LONG}
+STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}電車 - 情報を見るには電車をクリックします
+STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}新規電車を購入(電車庫が必要)
+STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}電車 - 情報を見るには電車をクリックします。車両を追加/取り除くにはドラッグします。
+STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}新規電車車両を購入
+STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}車両を販売するには、ここへドラッグします
+STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}電車車両のリスト - 情報を見るには車両をクリックします
+STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}選択した車両を購入
+STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}車両名を変更
+STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}電車の現在の動作 - 開始/停止するにはここにクリックします
+STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}電車の指令を表示します
+STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}電車を電車庫へ回送します。Control+クリックすすると、補修のみします。
+STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}信号が青になるまで待たずに電車の続行を強制します
+STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}電車を逆転します
+STR_884C_SHOW_TRAIN_DETAILS :{BLACK}電車の情報を表示します
+STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}補修間隔を増やす
+STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}補修間隔を減らす
+STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}積んだ貨物の情報を表示します
+STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}電車車両の情報を表示します
+STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}各車両の容量を表示します
+STR_8852_SHOW_TOTAL_CARGO :{BLACK}貨物種類に並べ替えて電車の合計容量を表示します
+STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}指令リスト - 指令を選択するにはクリックします。
+STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}現在の指令をスキップして、次へ移動します
+STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}選択した指令を削除します
+STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}選択した指令を「直行便」にします
+STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}選択した指令の前/リストの終わりに新規指令を挿入します
+STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}選択した指令に全負荷まで待つことを強制します
+STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}選択した指令に降ろすことを強制します
+STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}{STRING} が新登場!
+STR_885A :{BLACK}{BIGFONT}{STRING}
+STR_VEHICLE_INFO_COST_WEIGHT_SPEED_POWER :{BLACK}値段: {CURRENCY}重さ: {WEIGHT_S}{}スピード: {VELOCITY} 力: {POWER}{}運転費:{CURRENCY}/年{}体積: {CARGO}
+STR_885C_BROKEN_DOWN :{RED}故障
+STR_885D_AGE_RUNNING_COST_YR :{BLACK}年齢:{LTBLUE}{STRING}{BLACK} 運転費:{LTBLUE}1 年間に{CURRENCY}
+STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}重さ: {LTBLUE}{WEIGHT_S} {BLACK}力: {LTBLUE}{POWER}{BLACK} 最大スピード: {LTBLUE}{VELOCITY}
+STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}今年の利益:{LTBLUE}{CURRENCY}(去年:{CURRENCY})
+STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}信頼度:{LTBLUE}{COMMA}% {BLACK}最新補修後の故障:{LTBLUE}{COMMA}
+STR_8861_STOPPED :{RED}停止中
+
+STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}電車事件!{}{COMMA} 人が死亡
+STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}電車が逆転できません...
+STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}電車車両名を変更
+STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}車両名が変更できません...
+
+STR_TRAIN_STOPPING :{RED}止まっています
+STR_TRAIN_STOPPING_VEL :{RED}止まっています、 {VELOCITY}
+STR_TRAIN_NO_POWER :{RED}電源はありません
+STR_TRAIN_START_NO_CATENARY :電車はけん垂線がありませんから、電車は動き出せません。
+
+##id 0x9000
+STR_9002 :{WHITE}{VEHICLE}
+STR_9029 :{BLACK}{BIGFONT}{STRING}
+
+
+
+##id 0x9800
+STR_980F :{WHITE}{VEHICLE}
+
+
+##id 0xA000
+STR_A00A :{WHITE}{VEHICLE}
+STR_A02D :{BLACK}{BIGFONT}{STRING}
+
+STR_A036 :{TINYFONT}{BLACK}{STATION}
+
+##id 0xB000
+
+
+STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY :{BLACK}({CURRCOMPACT}/{CURRCOMPACT})
+STR_PERFORMANCE_DETAIL_AMOUNT_INT :{BLACK}({COMMA}/{COMMA})
+SET_PERFORMANCE_DETAIL_INT :{BLACK}{NUM}
+############ Those following lines need to be in this order!!
+############ End of order list
+
+
+
+
+
+
+STR_TRAIN :{BLACK}{TRAIN}
+STR_BUS :{BLACK}{BUS}
+STR_LORRY :{BLACK}{LORRY}
+STR_SHIP :{BLACK}{SHIP}
+
+STR_SCHEDULED_AIRCRAFT :{WHITE}{STATION} - {COMMA} 飛行機
+
+
+STR_VEH_WITH_SHARED_ORDERS_LIST :{WHITE}シェアード ・ルート{COMMA} 車
+STR_VEH_WITH_SHARED_ORDERS_LIST_TIP :{BLACK}このスケジュールの車全部を見せます
+
+### depot strings
+
+
+
+
+STR_VEHICLE_LIST_TRAIN_DEPOT :{BLACK}{STRING} - {COMMA} 電車
+STR_VEHICLE_LIST_ROADVEH_DEPOT :{BLACK}{STRING} - {COMMA} 車
+STR_VEHICLE_LIST_SHIP_DEPOT :{BLACK}{STRING} - {COMMA} シップ
+STR_VEHICLE_LIST_AIRCRAFT_DEPOT :{BLACK}{STRING} - {COMMA} 飛行機
+
+
+
+
+
+
+STR_SHORT_DATE :{WHITE}{DATE_TINY}
+
+
+############ Lists rail types
+
+
+############ End of list of rail types
+
+STR_TINY_BLACK :{BLACK}{TINYFONT}{COMMA}
+
+
+########### String for New Landscape Generator
+
+STR_WORLD_GENERATION_CAPTION :{WHITE}世界発電
+STR_TREE_PLACER :{BLACK}木アルゴリズム:
+STR_TERRAIN_TYPE :{BLACK}地形種類:
+STR_GENERATE_DATE :{BLACK}{DATE_LONG}
+STR_START_DATE_QUERY_CAPT :{WHITE}始める年を変えます
+STR_SNOW_LINE_HEIGHT_NUM :{NUM}
+STR_GENERATION_PROGRESS :{BLACK}{NUM} / {NUM}
+STR_WORLD_GENERATION :{BLACK}世界発電
+STR_TREE_GENERATION :{BLACK}木発電
+STR_UNMOVABLE_GENERATION :{BLACK}可動ない 発電
+STR_FLAT_WORLD_HEIGHT_NUM :{NUM}
+
+
+########### String for new airports
+
+
+############ Tooltip measurment
+
+
+########
--- a/lang/unfinished/lithuanian.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/unfinished/lithuanian.txt Wed Jan 03 08:32:17 2007 +0000
@@ -1,87 +1,89 @@
##name Lithuanian
-##ownname Lietuviu
+##ownname Lietuvių
##isocode lt_LT.UTF-8
##plural 5
+##case kas ko kam ka kuo kur kreip
+##gender vyr mot
##id 0x0000
STR_NULL :
-STR_0001_OFF_EDGE_OF_MAP :{WHITE}Uz zemelapio krasto
-STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Per arti zemelapio krasto
-STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Neuztenka lesu - reikia {CURRENCY}
+STR_0001_OFF_EDGE_OF_MAP :{WHITE}Už žemelapio kraštų
+STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Per arti žemėlapio krašto
+STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Neužtenka lėšų: reikia {CURRENCY}
STR_0004 :{WHITE}{CURRENCY64}
STR_0005 :{RED}{CURRENCY64}
STR_EMPTY :
-STR_0007_FLAT_LAND_REQUIRED :{WHITE}Reikia lygaus paviršiaus
+STR_0007_FLAT_LAND_REQUIRED :{WHITE}Paviršius turi būti lygus
STR_0008_WAITING :{BLACK}Laukia: {WHITE}{STRING}
STR_0009 :{WHITE}{CARGO}
-STR_000A_EN_ROUTE_FROM :{WHITE}{CARGO}{YELLOW} (marsrutas is
+STR_000A_EN_ROUTE_FROM :{WHITE}{CARGO}{YELLOW} (maršrutas iš
STR_000B :{YELLOW}{STATION})
-STR_000C_ACCEPTS :{BLACK}Laukia: {WHITE}
-STR_000D_ACCEPTS :{BLACK}Laukia: {GOLD}
+STR_000C_ACCEPTS :{BLACK}Priima: {WHITE}
+STR_000D_ACCEPTS :{BLACK}Priima: {GOLD}
STR_000E :
-STR_000F_PASSENGERS :Keleiviu
+STR_000F_PASSENGERS :
STR_0010_COAL :Anglis
-STR_0011_MAIL :Pasto
+STR_0011_MAIL :Pašto
STR_0012_OIL :Naftos
-STR_0013_LIVESTOCK :Galviju
-STR_0014_GOODS :Prekiu
-STR_0015_GRAIN :Grudu
+STR_0013_LIVESTOCK :Galvijų
+STR_0014_GOODS :Prekių
+STR_0015_GRAIN :Grūdų
STR_0016_WOOD :Medienos
-STR_0017_IRON_ORE :Gelezies rudos
+STR_0017_IRON_ORE :Geležies rūdos
STR_0018_STEEL :Plieno
-STR_0019_VALUABLES :Brangenybiu
-STR_001A_COPPER_ORE :Vario rudos
-STR_001B_MAIZE :Kukuruzu
-STR_001C_FRUIT :Vaisiu
-STR_001D_DIAMONDS :Deimantu
+STR_0019_VALUABLES :Brangenybių
+STR_001A_COPPER_ORE :Vario rūdos
+STR_001B_MAIZE :Kukurūzų
+STR_001C_FRUIT :Vaisių
+STR_001D_DIAMONDS :Deimantų
STR_001E_FOOD :Maisto
STR_001F_PAPER :Popieriaus
STR_0020_GOLD :Aukso
STR_0021_WATER :Vandens
-STR_0022_WHEAT :Kvieciu
+STR_0022_WHEAT :Kviečių
STR_0023_RUBBER :Gumos
STR_0024_SUGAR :Cukraus
-STR_0025_TOYS :Zaislu
-STR_0026_CANDY :Saldumynu
+STR_0025_TOYS :Žaislų
+STR_0026_CANDY :Saldumynų
STR_0027_COLA :Kolos
STR_0028_COTTON_CANDY :Cukraus vatos
-STR_0029_BUBBLES :Burbulu
-STR_002A_TOFFEE :Karameles
-STR_002B_BATTERIES :Bateriju
-STR_002C_PLASTIC :Plastmases
-STR_002D_FIZZY_DRINKS :Gaiviuju gerimu
+STR_0029_BUBBLES :Burbulų
+STR_002A_TOFFEE :Karamelės
+STR_002B_BATTERIES :Baterijų
+STR_002C_PLASTIC :Plastmasės
+STR_002D_FIZZY_DRINKS :Gaiviųjų gėrimų
STR_002E :
-STR_002F_PASSENGER :Keleiviu
+STR_002F_PASSENGER :Keleivių
STR_0030_COAL :Anglies
-STR_0031_MAIL :Pasto
+STR_0031_MAIL :Pašto
STR_0032_OIL :Naftos
-STR_0033_LIVESTOCK :Galviju
-STR_0034_GOODS :Prekiu
-STR_0035_GRAIN :Grudu
+STR_0033_LIVESTOCK :Galvijų
+STR_0034_GOODS :Prekių
+STR_0035_GRAIN :Grūdų
STR_0036_WOOD :Medienos
-STR_0037_IRON_ORE :Gelezies rudos
+STR_0037_IRON_ORE :Geležies rūdos
STR_0038_STEEL :Plieno
-STR_0039_VALUABLES :Brangenybiu
-STR_003A_COPPER_ORE :Vario rudos
-STR_003B_MAIZE :Kukuruzu
-STR_003C_FRUIT :Vaisiu
-STR_003D_DIAMOND :Deimantu
+STR_0039_VALUABLES :Brangenybių
+STR_003A_COPPER_ORE :Vario rūdos
+STR_003B_MAIZE :Kukurūzų
+STR_003C_FRUIT :Vaisių
+STR_003D_DIAMOND :Deimantų
STR_003E_FOOD :Maisto
STR_003F_PAPER :Popieriaus
STR_0040_GOLD :Aukso
STR_0041_WATER :Vandens
-STR_0042_WHEAT :Kvieciu
-STR_0043_RUBBER :Kauciuko
+STR_0042_WHEAT :Kviečių
+STR_0043_RUBBER :Kaučiuko
STR_0044_SUGAR :Cukraus
-STR_0045_TOY :Zaislu
-STR_0046_CANDY :Saldumynu
+STR_0045_TOY :Žaislų
+STR_0046_CANDY :Saldumynų
STR_0047_COLA :Kolos
STR_0048_COTTON_CANDY :Cukraus vatos
-STR_0049_BUBBLE :Burbulu
-STR_004A_TOFFEE :Karameles
-STR_004B_BATTERY :Bateriju
-STR_004C_PLASTIC :Plastic
-STR_004D_FIZZY_DRINK :Gaiviuju gerimu
+STR_0049_BUBBLE :Burbulų
+STR_004A_TOFFEE :Karamelės
+STR_004B_BATTERY :Baterijų
+STR_004C_PLASTIC :Plastmasės
+STR_004D_FIZZY_DRINK :Gaiviųjų gėrimų
STR_QUANTITY_NOTHING :
STR_QUANTITY_PASSENGERS :{COMMA} keleiviai
STR_QUANTITY_COAL :{WEIGHT} tonu anglies
@@ -93,6 +95,7 @@
STR_QUANTITY_WOOD :{WEIGHT} tonu medienos
STR_QUANTITY_IRON_ORE :{WEIGHT} tonu gelezies rudos
STR_QUANTITY_STEEL :{WEIGHT} tonu plieno
+STR_QUANTITY_VALUABLES :{COMMA} maiš{P as ai ų} brangenybių
STR_QUANTITY_COPPER_ORE :{WEIGHT} tonu vario rudos
STR_QUANTITY_MAIZE :{WEIGHT} tonu kukuruzu
STR_QUANTITY_FRUIT :{WEIGHT} tonu vaisiu
@@ -149,13 +152,14 @@
STR_ABBREV_ALL :{TINYFONT}VISI
STR_00AE :{WHITE}{DATE_SHORT}
STR_00AF :{WHITE}{DATE_LONG}
-STR_00B0_MAP :{WHITE}Zemelapis - {STRING}
-STR_00B1_GAME_OPTIONS :{WHITE}Zaidimo nustatymai
-STR_00B2_MESSAGE :{YELLOW}Zinute
-STR_00B3_MESSAGE_FROM :{YELLOW}Zinute nuo {STRING}
+STR_00B0_MAP :{WHITE}Žemėlapis - {STRING}
+STR_00B1_GAME_OPTIONS :{WHITE}Žaidimo nustatymai
+STR_00B2_MESSAGE :{YELLOW}Žinutė
+STR_00B3_MESSAGE_FROM :{YELLOW}Žinutė nuo {STRING}
+STR_POPUP_CAUTION_CAPTION :{WHITE}Įspėjimas!
STR_00B4_CAN_T_DO_THIS :{WHITE}To daryti negalima....
-STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Negalima griauti sios teritorijos....
-STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Orginalo teises priklauso {COPYRIGHT} 1995 Chris Sawyer, Visos teises saugomos
+STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Negalima griauti šios teritorijos....
+STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Pradinės versijos teisės priklauso {COPYRIGHT} 1995 Chris Sawyer, Visos teisės saugomos
STR_00B7_VERSION :{BLACK}OpenTTD versija {REV}
STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2006 OpenTTD komanda
STR_TRANSLATED_BY :{BLACK} Vertejai: Mindaugas Surdokas (L781), Vytautas Liuolia
@@ -165,44 +169,44 @@
STR_00C7_QUIT :{WHITE}Baigti
STR_00C8_YES :{BLACK}Taip
STR_00C9_NO :{BLACK}Ne
-STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Ar jus tikrai norite nutraukti zaidima ir grizti i {STRING}?
+STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Ar jūs tikrai norite nutraukti žaidimą ir grižti į {STRING}?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
STR_00CE_4 :{BLACK}4
STR_00CF_5 :{BLACK}5
-STR_00D0_NOTHING :Tuscia
-STR_00D1_DARK_BLUE :Tamsiai melyna
-STR_00D2_PALE_GREEN :Pilksvai zalia
-STR_00D3_PINK :Ruzava
+STR_00D0_NOTHING :Tuščia
+STR_00D1_DARK_BLUE :Tamsiai mėlyna
+STR_00D2_PALE_GREEN :Pilkšvai žalia
+STR_00D3_PINK :Rausva
STR_00D4_YELLOW :Geltona
STR_00D5_RED :Raudona
-STR_00D6_LIGHT_BLUE :Zydra
-STR_00D7_GREEN :Zalia
-STR_00D8_DARK_GREEN :Tamsiai zalia
-STR_00D9_BLUE :Melyna
-STR_00DA_CREAM :Kremine
-STR_00DB_MAUVE :Pilksvai melyna
-STR_00DC_PURPLE :Violetine
-STR_00DD_ORANGE :Oranzine
+STR_00D6_LIGHT_BLUE :Žydra
+STR_00D7_GREEN :Žalia
+STR_00D8_DARK_GREEN :Tamsiai žalia
+STR_00D9_BLUE :Mėlyna
+STR_00DA_CREAM :Kreminė
+STR_00DB_MAUVE :Pilkšvai mėlyna
+STR_00DC_PURPLE :Violetinė
+STR_00DD_ORANGE :Oranžinė
STR_00DE_BROWN :Ruda
STR_00DF_GREY :Pilka
STR_00E0_WHITE :Balta
-STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Per daug transporto priemoniu zaidime
+STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Per daug transporto priemonių žaidime
STR_00E2 :{BLACK}{COMMA}
STR_00E3 :{RED}{COMMA}
STR_00E4_LOCATION :{BLACK}Vieta
-STR_00E5_CONTOURS :Konturai
-STR_00E6_VEHICLES :Transporto priemones
-STR_00E7_INDUSTRIES :Pramones imones
+STR_00E5_CONTOURS :Kontūrai
+STR_00E6_VEHICLES :Transporto priemonės
+STR_00E7_INDUSTRIES :Pramonės įmonės
STR_00E8_ROUTES :Keliai
STR_00E9_VEGETATION :Augalija
STR_00EA_OWNERS :Savininkai
STR_00EB_ROADS :{BLACK}{TINYFONT}Keliai
-STR_00EC_RAILROADS :{BLACK}{TINYFONT}Gelezinkeliai
-STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stoteles/Oro uostai/Prieplaukos
-STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Pastatai/Pramones imones
-STR_00EF_VEHICLES :{BLACK}{TINYFONT}Transporto priemones
+STR_00EC_RAILROADS :{BLACK}{TINYFONT}Geležinkeliai
+STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stotelės/Oro uostai/Prieplaukos
+STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Pastatai/Pramonės įmonės
+STR_00EF_VEHICLES :{BLACK}{TINYFONT}Transporto priemonės
STR_00F0_100M :{BLACK}{TINYFONT}100m
STR_00F1_200M :{BLACK}{TINYFONT}200m
STR_00F2_300M :{BLACK}{TINYFONT}300m
@@ -211,64 +215,64 @@
STR_00F5_TRAINS :{BLACK}{TINYFONT}Traukiniai
STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Automobiliai
STR_00F7_SHIPS :{BLACK}{TINYFONT}Laivai
-STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Lektuvai
+STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Lėktuvai
STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Keliai
STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Anglies kasykla
-STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Elektrine
-STR_00FC_FOREST :{BLACK}{TINYFONT}Miskas
-STR_00FD_SAWMILL :{BLACK}{TINYFONT}Lentpjuve
-STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Naftos perdirbimo imone
+STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Elektrinė
+STR_00FC_FOREST :{BLACK}{TINYFONT}Miškas
+STR_00FD_SAWMILL :{BLACK}{TINYFONT}Lentpjūvė
+STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Naftos perdirbimo įmonė
STR_00FF_FARM :{BLACK}{TINYFONT}Ferma
STR_0100_FACTORY :{BLACK}{TINYFONT}Gamykla
-STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Spaustuve
-STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Naftos grezinys
-STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Gelezies rudos kasykla
+STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Spaustuvė
+STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Naftos gręžinys
+STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Geležies rūdos kasykla
STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Plieno liejykla
STR_0105_BANK :{BLACK}{TINYFONT}Bankas
-STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Popieriaus fabrikas
+STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Popieriaus gamykla
STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Aukso kasykla
-STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Maisto paruosimo fabrikas
-STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Deimantu kasykla
-STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Vario rudos kasykla
-STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Vaisiu plantacija
-STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Kauciuko plantacija
-STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Vandens grezinys
-STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vandentiekio bokstas
-STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Lentpjuve
+STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Maisto perdirbimo įmonė
+STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Deimantų kasykla
+STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Vario rūdos kasykla
+STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Vaismedžių plantacija
+STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Kaučiukmedžių plantacija
+STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Vandens grežinys
+STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vandentiekio bokštas
+STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Lentpjūvė
STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Cukraus vatos krumynai
-STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Saldainiu fabrikas
-STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Bateriju ferma
-STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Kolos greziniai
-STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Zaislu parduotuve
-STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Zaislu fabrikas
-STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastmases versmes
-STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Gaiviuju gerimu fabrikas
-STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Burbulu leistuvas
-STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Karameles telkinys
+STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Saldumynų gamykla
+STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Baterijų ūkis
+STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Kolos gręžiniai
+STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Žaislų parduotuvė
+STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Žaislų gamykla
+STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastmasės versmės
+STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Gaiviųjų gėrimų gamykla
+STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Burbulų leistuvas
+STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Karamelės telkinys
STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Cukraus kasykla
-STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Gelezinkelio stotis
-STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Sunkvezimiu pakrovimo aikstele
-STR_011D_BUS_STATION :{BLACK}{TINYFONT}Autobusu stotele
-STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Oro uostas/Malunsparniu aikstele
+STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Geležinkelio stotis
+STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Sunkvežimių pakrovimo aikštelė
+STR_011D_BUS_STATION :{BLACK}{TINYFONT}Autobusų stotis
+STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Oro uostas/Sraigtasparnių aikštelė
STR_011F_DOCK :{BLACK}{TINYFONT}Prieplauka
-STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Kalnuotas krastas
+STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Kalnuotas kraštas
STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Ganykla
STR_0122_BARE_LAND :{BLACK}{TINYFONT}Lygumos
STR_0123_FIELDS :{BLACK}{TINYFONT}Laukai
-STR_0124_TREES :{BLACK}{TINYFONT}Medziai
+STR_0124_TREES :{BLACK}{TINYFONT}Medžiai
STR_0125_ROCKS :{BLACK}{TINYFONT}Uolos
STR_0126_WATER :{BLACK}{TINYFONT}Vanduo
-STR_0127_NO_OWNER :{BLACK}{TINYFONT}Nera savininko
+STR_0127_NO_OWNER :{BLACK}{TINYFONT}Nėra savininko
STR_0128_TOWNS :{BLACK}{TINYFONT}Miestai
-STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Pramones imones
+STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Pramonės įmonės
STR_012A_DESERT :{BLACK}{TINYFONT}Dykuma
STR_012B_SNOW :{BLACK}{TINYFONT}Sniegas
-STR_012C_MESSAGE :{WHITE}Pranesimas
+STR_012C_MESSAGE :{WHITE}Pranešimas
STR_012D :{WHITE}{STRING}
-STR_012E_CANCEL :{BLACK}Atsaukti
+STR_012E_CANCEL :{BLACK}Atšaukti
STR_012F_OK :{BLACK}Gerai
STR_0130_RENAME :{BLACK}Pervardinti
-STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Per daug vardu
+STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Per daug vardų
STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Pasirinktas vardas jau naudojamas
STR_0133_WINDOWS :Windows
@@ -285,12 +289,14 @@
STR_013E_CAPACITIES :{BLACK}Talpumas
STR_013E_TOTAL_CARGO :{BLACK}Visa keliamoji galia
STR_013F_CAPACITY :{BLACK}Talpa: {LTBLUE}{CARGO}
+STR_CAPACITY_MULT :{BLACK}Talpa: {LTBLUE}{CARGO} (x{NUM})
STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Visa traukinio keliamoji galia:
STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO})
-STR_0140_NEW_GAME :{BLACK}Naujas zaidimas
-STR_0141_LOAD_GAME :{BLACK}Atverti zaidima
+STR_TOTAL_CAPACITY_MULT :{LTBLUE}- {CARGO} ({SHORTCARGO}) (x{NUM})
+STR_0140_NEW_GAME :{BLACK}Naujas žaidimas
+STR_0141_LOAD_GAME :{BLACK}Atverti žaidimą
STR_SINGLE_PLAYER :{BLACK}Vienas zaidejas
-STR_MULTIPLAYER :{BLACK}Keli zaidejai
+STR_MULTIPLAYER :{BLACK}Komandinis žaidimas
STR_64 :64
STR_128 :128
@@ -300,11 +306,11 @@
STR_2048 :2048
STR_MAPSIZE :{BLACK}Zemelapio dydis:
STR_BY :{BLACK}*
-STR_0148_GAME_OPTIONS :{BLACK}Zaidimo nustatymai
+STR_0148_GAME_OPTIONS :{BLACK}Žaidimo nustatymai
-STR_0150_SOMEONE :kazkas{SKIP}{SKIP}
-STR_0151_MAP_OF_WORLD :Zemelapis
-STR_0152_TOWN_DIRECTORY :Miestu sarasas
+STR_0150_SOMEONE :kažkas{SKIP}{SKIP}
+STR_0151_MAP_OF_WORLD :Žemėlapis
+STR_0152_TOWN_DIRECTORY :Miestų sąrašas
STR_0153_SUBSIDIES :Subsidijos
STR_UNITS_IMPERIAL :Imperines
@@ -319,34 +325,44 @@
STR_UNITS_POWER_METRIC :{COMMA}AG
STR_UNITS_POWER_SI :{COMMA}kW
+STR_UNITS_WEIGHT_SHORT_IMPERIAL :{COMMA}t
+STR_UNITS_WEIGHT_SHORT_METRIC :{COMMA}t
+STR_UNITS_WEIGHT_SHORT_SI :{COMMA}kg
+STR_UNITS_WEIGHT_LONG_IMPERIAL :{COMMA} ton{P a os ų}
+STR_UNITS_WEIGHT_LONG_METRIC :{COMMA} ton{P a os ų}
+STR_UNITS_WEIGHT_LONG_SI :{COMMA} kg
STR_UNITS_VOLUME_SHORT_IMPERIAL :{COMMA}gal
STR_UNITS_VOLUME_SHORT_METRIC :{COMMA}l
STR_UNITS_VOLUME_SHORT_SI :{COMMA}m?
+STR_UNITS_VOLUME_LONG_IMPERIAL :{COMMA} galon{P as ai ų}
+STR_UNITS_VOLUME_LONG_METRIC :{COMMA} litr{P as ai ų}
STR_UNITS_VOLUME_LONG_SI :{COMMA} m?
+STR_UNITS_FORCE_IMPERIAL :{COMMA}x10³ svar{P o ų ų} jėga (lbf)
+STR_UNITS_FORCE_METRIC :{COMMA} ton{P os ų ų} jėga
STR_UNITS_FORCE_SI :{COMMA} kN
############ range for menu starts
-STR_0154_OPERATING_PROFIT_GRAPH :Dirbancio pelno grafikas
-STR_0155_INCOME_GRAPH :Iplauku diagrama
-STR_0156_DELIVERED_CARGO_GRAPH :Pristatytu kroviniu diagrama
-STR_0157_PERFORMANCE_HISTORY_GRAPH :Spartos istorinis grafikas
-STR_0158_COMPANY_VALUE_GRAPH :Kompanijos vertes kitimas
-STR_0159_CARGO_PAYMENT_RATES :Kroviniu apmokejimo lygis
-STR_015A_COMPANY_LEAGUE_TABLE :Kompanijos uzimama vieta
+STR_0154_OPERATING_PROFIT_GRAPH :Įprastinės veiklos pelno diagrama
+STR_0155_INCOME_GRAPH :Pajamų diagrama
+STR_0156_DELIVERED_CARGO_GRAPH :Krovinių pristatymo diagrama
+STR_0157_PERFORMANCE_HISTORY_GRAPH :Našumo diagrama
+STR_0158_COMPANY_VALUE_GRAPH :Kompanijos vertės diagrama
+STR_0159_CARGO_PAYMENT_RATES :Krovinių apmokėjimo lygis
+STR_015A_COMPANY_LEAGUE_TABLE :Kompanijos užimama vieta
STR_PERFORMANCE_DETAIL_MENU :Issamus veiklos ivertinimas
############ range for menu ends
STR_015B_OPENTTD :{WHITE}Apie OpenTTD
-STR_015C_SAVE_GAME :Issaugoti zaidima
-STR_015D_LOAD_GAME :Atverti zaidima
-STR_015E_QUIT_GAME :Nutraukti zaidima
-STR_015F_QUIT :Iseiti
-STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Ar tu tikrai nori nutraukti zaidima?
-STR_0161_QUIT_GAME :{WHITE}Nutraukti zaidima
+STR_015C_SAVE_GAME :Išsaugoti žaidimą
+STR_015D_LOAD_GAME :Atverti žaidimą
+STR_015E_QUIT_GAME :Nutraukti žaidimą
+STR_015F_QUIT :Išeiti
+STR_ABANDON_GAME_QUERY :{YELLOW}Ar tikrai norite išeiti iš žaidimo?
+STR_0161_QUIT_GAME :{WHITE}Nutraukti žaidima
STR_SORT_ORDER_TIP :{BLACK}Pasirink rikiavimo tvarka (mazejimo/didejimo)
STR_SORT_CRITERIA_TIP :{BLACK}Pasirink rikiavimo kriteriju
STR_SORT_BY :{BLACK}Rikiuoti pagal
@@ -370,10 +386,25 @@
STR_SORT_BY_FACILITY :Stoties tipas
STR_SORT_BY_WAITING :Laukiancio krovinio verte
STR_SORT_BY_RATING_MAX :Kroviniu reitingavimas
+STR_ENGINE_SORT_ENGINE_ID :VariklioID (klasikinis rūšiavimas)
+STR_ENGINE_SORT_COST :Kaina
+STR_ENGINE_SORT_POWER :Galia
+STR_ENGINE_SORT_INTRO_DATE :Atsiradimo data
+STR_ENGINE_SORT_RUNNING_COST :Eksplotacijos išlaidos
+STR_ENGINE_SORT_POWER_VS_RUNNING_COST :Galia/Eksplotacijos išlaidos
+STR_ENGINE_SORT_CARGO_CAPACITY :Vagono talpa
STR_NO_WAITING_CARGO :{BLACK}Jokiu kroviniu nera pakrovimui
STR_SELECT_ALL_FACILITIES :{BLACK}Pazymeti visus pastatus
STR_SELECT_ALL_TYPES :{BLACK}Pazymeti visus krovinio tipus (iskaitant nelaukiancius kroviniu)
-STR_REPLACE_VEHICLES :{BLACK}Keisti tr. priemones
+STR_AVAILABLE_ENGINES_TIP :{BLACK}Peržiūrėti galimų variklių sąrašą tinkamų šiai transporto priemonei.
+STR_MANAGE_LIST :{BLACK}Tvarkyti sąrašą
+STR_MANAGE_LIST_TIP :{BLACK}Siųsti nurodymus visoms šio sąrašo tr. priemonėms
+STR_REPLACE_VEHICLES :Keisti tr. priemones
+STR_SEND_TRAIN_TO_DEPOT :Siųsti į depą
+STR_SEND_ROAD_VEHICLE_TO_DEPOT :Siųsti į depą
+STR_SEND_SHIP_TO_DEPOT :Siųsti į depą
+STR_SEND_AIRCRAFT_TO_HANGAR :Siųsti į angarą
+STR_SEND_FOR_SERVICING :Siųsti techninės apžiūros
############ range for months starts
STR_0162_JAN :Sau
@@ -393,50 +424,50 @@
STR_016E :{TINYFONT}{STRING}{} {STRING}
STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUM}
STR_0170 :{TINYFONT}{STRING}-
-STR_0171_PAUSE_GAME :{BLACK}Sustabdyti zaidima
-STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Issaugoti, nutraukti, iseiti is zaidimo
-STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Parodyti stoteliu sarasa
-STR_0174_DISPLAY_MAP :{BLACK}Parodyti zemelapi
-STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Parodyti zemelapi, miestus
-STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Parodyti miestu sarasa
-STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Parodyti kompanijos finansine informacija
-STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Parodyti pagrindine kompanijos informacija
+STR_0171_PAUSE_GAME :{BLACK}Sustabdyti žaidimą
+STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Išsaugoti, nutraukti, išeiti iš žaidimo
+STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti stotelių sąrašą
+STR_0174_DISPLAY_MAP :{BLACK}Rodyti žemėlapį
+STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Rodyti žemėlapį, miestų sąrašą
+STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Rodyti miestų sąrašą
+STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Rodyti kompanijos finansinę informaciją
+STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Rodyti pagrindinę kompanijos informaciją
STR_0179_DISPLAY_GRAPHS :{BLACK}Rodyti diagramas
-STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Transporto kompaniju vertinimas
-STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti traukiniu sarasa
-STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti automobiliu sarasa
-STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti laivu sarasa
-STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti lektuvu sarasa
-STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Priartinti vaizda
-STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Atitolinti vaizda
-STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Statyti gelezinkeli
+STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Transporto kompanijų vertinimas
+STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti traukinių sąrašą
+STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti automobilių sąrašą
+STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti laivų sąrašą
+STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Rodyti lektuvų sąrašą
+STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Priartinti vaizdą
+STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Nutolinti vaizdą
+STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Tiesti geležinkelius
STR_0182_BUILD_ROADS :{BLACK}Tiesti kelius
-STR_0183_BUILD_SHIP_DOCKS :{BLACK}Statyti prieplauka
-STR_0184_BUILD_AIRPORTS :{BLACK}Statyti oro uosta
-STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Statyti medzius, zenklus ir kt.
-STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Langelio informacija
-STR_0187_OPTIONS :{BLACK}Nustatymai
+STR_0183_BUILD_SHIP_DOCKS :{BLACK}Statyti prieplaukas
+STR_0184_BUILD_AIRPORTS :{BLACK}Statyti oro uostus
+STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Sodinti medžius, statyti ženklus ir kt.
+STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Žemės ploto informacija
+STR_0187_OPTIONS :{BLACK}Parinktys
STR_0188 :{BLACK}{SMALLUPARROW}
STR_0189 :{BLACK}{SMALLDOWNARROW}
STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Aptarnavimo intervalo keisti negalima...
-STR_018B_CLOSE_WINDOW :{BLACK}Uzdaryti langa
-STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Lango pavadinimas - tempk uz jo, jei nori langa perkelti
+STR_018B_CLOSE_WINDOW :{BLACK}Uždaryti langą
+STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Lango pavadinimas - už jo tempiant galima judinti langą
STR_STICKY_BUTTON :{BLACK}Pazymeti si langa kaip neuzdaroma komandos 'Uzdaryti visus langus' pagalba (arba 'Delete' klavisas)
STR_RESIZE_BUTTON :{BLACK}Spragtelk ir trauk, jei nori pakeisti lango dydi
STR_SAVELOAD_HOME_BUTTON :{BLACK}Spausti cia persokimui i numatytaja saugojimo/ikrovimo direktorija
-STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Sprogdinti pastatus ir kita
-STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Nuzeminti zemes lygi
-STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Paaukstinti zemes lygi
-STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Prasukimo juosta - prasuka sarasa aukstyn/zemyn
+STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Nugriauti pastatus ir kita pasirinktam žemės plote
+STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Pažeminti žemės lygį
+STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Paaukštinti žemės lygį
+STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Slinkties juosta - paslenka sąrašą aukštyn/žemyn
STR_HSCROLL_BAR_SCROLLS_LIST :{BLACK}Prasukimo juosta - prasuka sarasa i kaire/desine
-STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Rodyti zemes konturus zemelapyje
-STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Rodyti transporto priemones zemelapyje
-STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Rodyti gamyklas zemelapyje
-STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Rodyti transporto kelius zemelapyje
-STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Rodyti augmenija zemelapyje
-STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Rodyti zemes savininkus zemelapyje
-STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Rodyti/paslepti miestu pavadinimus zemelapyje
-STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Pelnas siais metais: {CURRENCY} (praeitais metais: {CURRENCY})
+STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Rodyti žemės kontūrus žemėlapyje
+STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Rodyti transporto priemones žemėlapyje
+STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Rodyti gamyklas žemėlapyje
+STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Rodyti transporto kelius žemėlapyje
+STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Rodyti augmeniją žemėlapyje
+STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Rodyti žemės savininkus žemėlapyje
+STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Rodyti/paslepti miestų pavadinimus žemėlapyje
+STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Šių metų pelnas: {CURRENCY} (praėjusių metų: {CURRENCY})
############ range for service numbers starts
STR_AGE :{COMMA} metai ({COMMA})
@@ -444,306 +475,308 @@
############ range for service numbers ends
STR_019C_ROAD_VEHICLE :Automobilis
-STR_019D_AIRCRAFT :Lektuvas
+STR_019D_AIRCRAFT :Lėktuvas
STR_019E_SHIP :Laivas
STR_019F_TRAIN :Traukinys
STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA} sensta
-STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA} labai suseno
-STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} labai suseno ir butinai turi buti pakeistas
-STR_01A3_LAND_AREA_INFORMATION :{WHITE}Informacija apie zemes plota
-STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Kaina isvalyti: {LTBLUE}N/A
-STR_01A5_COST_TO_CLEAR :{BLACK}Kaina isvalyti: {LTBLUE}{CURRENCY}
-STR_01A6_N_A :N/A
+STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA} labai paseno
+STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} labai paseno ir būtinai turi būti pakeistas
+STR_01A3_LAND_AREA_INFORMATION :{WHITE}Informacija apie žemės plotą
+STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Išvalymo kaina: {LTBLUE}NĖRA
+STR_01A5_COST_TO_CLEAR :{BLACK}Išvalymo kaina: {LTBLUE}{CURRENCY}
+STR_01A6_N_A :NĖRA
STR_01A7_OWNER :{BLACK}Savininkas: {LTBLUE}{STRING}
-STR_01A8_LOCAL_AUTHORITY :{BLACK}Valdzia: {LTBLUE}{STRING}
-STR_01A9_NONE :Nieko
+STR_01A8_LOCAL_AUTHORITY :{BLACK}Vietos valdžia: {LTBLUE}{STRING}
+STR_01A9_NONE :Nėra
STR_01AA_NAME :{BLACK}Vardas
STR_01AB :{BLACK}{TINYFONT}{STRING}
############ range for days starts
-STR_01AC_1ST :1-a
-STR_01AD_2ND :2-a
-STR_01AE_3RD :3-ias
-STR_01AF_4TH :4-a
-STR_01B0_5TH :5-a
-STR_01B1_6TH :6-a
-STR_01B2_7TH :7-a
-STR_01B3_8TH :8-a
-STR_01B4_9TH :9-a
-STR_01B5_10TH :10-a
-STR_01B6_11TH :11-a
-STR_01B7_12TH :12-a
-STR_01B8_13TH :13-a
-STR_01B9_14TH :14-a
-STR_01BA_15TH :15-a
-STR_01BB_16TH :16-a
-STR_01BC_17TH :17-a
-STR_01BD_18TH :18-a
-STR_01BE_19TH :19-a
-STR_01BF_20TH :20-a
-STR_01C0_21ST :21-a
-STR_01C1_22ND :22-a
-STR_01C2_23RD :23-ia
-STR_01C3_24TH :24-a
-STR_01C4_25TH :25-a
-STR_01C5_26TH :26-a
-STR_01C6_27TH :27-a
-STR_01C7_28TH :28-a
-STR_01C8_29TH :29-a
-STR_01C9_30TH :30-a
-STR_01CA_31ST :31-a
+STR_01AC_1ST :1-ma(s)
+STR_01AD_2ND :2-ra(s)
+STR_01AE_3RD :3-čia(s)
+STR_01AF_4TH :4-ta(s)
+STR_01B0_5TH :5-ta(s)
+STR_01B1_6TH :6-ta(s)
+STR_01B2_7TH :7-ta(s)
+STR_01B3_8TH :8-ta(s)
+STR_01B4_9TH :9-ta(s)
+STR_01B5_10TH :10-ta(s)
+STR_01B6_11TH :11-ta(s)
+STR_01B7_12TH :12-ta(s)
+STR_01B8_13TH :13-ta(s)
+STR_01B9_14TH :14-ta(s)
+STR_01BA_15TH :15-ta(s)
+STR_01BB_16TH :16-ta(s)
+STR_01BC_17TH :17-ta(s)
+STR_01BD_18TH :18-ta(s)
+STR_01BE_19TH :19-ta(s)
+STR_01BF_20TH :20-ta(s)
+STR_01C0_21ST :21-ma(s)
+STR_01C1_22ND :22-ra(s)
+STR_01C2_23RD :23-čia(s)
+STR_01C3_24TH :24-ta(s)
+STR_01C4_25TH :25-ta(s)
+STR_01C5_26TH :26-ta(s)
+STR_01C6_27TH :27-ta(s)
+STR_01C7_28TH :28-ta(s)
+STR_01C8_29TH :29-ta(s)
+STR_01C9_30TH :30-ta(s)
+STR_01CA_31ST :31-ma(s)
############ range for days ends
STR_01CB :{TINYFONT}{COMMA}
-STR_01CE_CARGO_ACCEPTED :{BLACK}Krovinys priimamas: {LTBLUE}
+STR_01CE_CARGO_ACCEPTED :{BLACK}Krovinys priimtas: {LTBLUE}
STR_01D1_8 :({COMMA}/8 {STRING})
STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox
STR_01D3_SOUND_MUSIC :Garsas/muzika
-STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Rodyti garso/muzikos nustatymu langa
-STR_01D5_ALL :{TINYFONT}Viskas
+STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Rodyti garso/muzikos nustatymus
+STR_01D5_ALL :{TINYFONT}Visi
STR_01D6_OLD_STYLE :{TINYFONT}Senas stilius
STR_01D7_NEW_STYLE :{TINYFONT}Naujas stilius
STR_01D8_EZY_STREET :{TINYFONT}Ezy Street
-STR_01D9_CUSTOM_1 :{TINYFONT}Pasirinktas 1
-STR_01DA_CUSTOM_2 :{TINYFONT}Pasirinktas 2
+STR_01D9_CUSTOM_1 :{TINYFONT}Speciali 1
+STR_01DA_CUSTOM_2 :{TINYFONT}Speciali 2
STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Muzikos garsas
-STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Efektu garsas
-STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAKS
+STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Efektų garsas
+STR_01DD_MIN_MAX :{BLACK}{TINYFONT}TYLU ' ' ' ' ' ' GARSU
STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Pereiti prie buvusio garso takelio
-STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Pereiti prie kito pazymeto takelio
-STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Sustabdyti muzikos grojima
-STR_01E1_START_PLAYING_MUSIC :{BLACK}Groti muzika
-STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Tempk uz slankiklio, jei nori nustatyti muzikos ir efektu garsuma
+STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Pereiti prie kito pažymėto takelio
+STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Sustabdyti muzikos grojimą
+STR_01E1_START_PLAYING_MUSIC :{BLACK}Groti muziką
+STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Muzikos ir efektų garsumą galima keisti stumdant slankiklius
STR_01E3 :{DKGREEN}{TINYFONT}--
STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA}
STR_01E5 :{DKGREEN}{TINYFONT}{COMMA}
STR_01E6 :{DKGREEN}{TINYFONT}------
-STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}"
+STR_01E7 :{DKGREEN}{TINYFONT}„{STRING}“
STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Takelis{SETX 88}Pavadinimas
STR_01E9_SHUFFLE :{TINYFONT}Atsitiktinis
STR_01EA_PROGRAM :{TINYFONT}{BLACK}Programa
STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Muzikos programos pasirinkimas
-STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA} "{STRING}"
-STR_01ED :{TINYFONT}{LTBLUE}{COMMA} "{STRING}"
+STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA} „{STRING}“
+STR_01ED :{TINYFONT}{LTBLUE}{COMMA} „{STRING}“
STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Takelio numeris
-STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programa - '{STRING}'
-STR_01F0_CLEAR :{TINYFONT}{BLACK}Isvalyti
-STR_01F1_SAVE :{TINYFONT}{BLACK}Issaugoti
-STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Dabartine garso takeliu programa
-STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Pazymeti 'visi takeliai' programa
-STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Pazymeti 'seno stiliaus muzika' programa
-STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Pazymeti 'naujo stiliaus muzika' programa
-STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Pazymeti 'Speciali 1' (vartotojo sukurta) programa
-STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Pazymeti 'Speciali 2' (vartotojo sukurta) programa
-STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Panaikinti esama programa (tik Speciali1 arba Speciali2)
-STR_01F9_SAVE_MUSIC_SETTINGS :{BLACK}Issaugoti muzikos nustatymus
-STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Paspauskite ant garso takelio, kad itrauktumete i sarasa (tik Speciali1 arba Speciali2)
-STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Programos masyti ij./isj.
-STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Rodyti muzikos takeliu pasirinkimo langa
-STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Paspausk ant paslaugos, kad pamatytum? centre
+STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programa - „{STRING}“
+STR_01F0_CLEAR :{TINYFONT}{BLACK}Išvalyti
+STR_01F1_SAVE :{TINYFONT}{BLACK}Išsaugoti
+STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Dabartinė garso takelių programa
+STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Parinkti „visi takeliai“ programą
+STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Parinkti „seno stiliaus muzika“ programą
+STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Parinkti „naujo stiliaus muzika“ programą
+STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Parinkti „Speciali 1“ (vartotojo sukurtą) programą
+STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Parinkti „Speciali 2“ (vartotojo sukurtą) programą
+STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Panaikinti esama programa (tik „Speciali 1“ arba „Speciali 2“)
+STR_01F9_SAVE_MUSIC_SETTINGS :{BLACK}Išsaugoti muzikos nustatymus
+STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Paspauskite ant garso takelio, norėdami įtraukti į sąrašą (tik „Speciali 1“ arba „Speciali 2“)
+STR_CLICK_ON_TRACK_TO_REMOVE :{BLACK}Spragtelėjus takelį, jis pašalinamas iš dabartinės programos (tik „Speciali 1“ ir „Speciali 2“)
+STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Programos „Atsitiktiniai takeliai“ įj./išj.
+STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Rodyti muzikos takelių pasirinkimo langą
+STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Paspauskite ant paslaugos, norėdami pamatyti įmonę/miestą
STR_01FE_DIFFICULTY :{BLACK}Sunkumo lygis ({STRING})
STR_01FF :{TINYFONT}{BLACK}{DATE_LONG}
-STR_0200_LAST_MESSAGE_NEWS_REPORT :Paskutine zinute/naujiena
-STR_0201_MESSAGE_SETTINGS :Zinuciu nustatymai
+STR_0200_LAST_MESSAGE_NEWS_REPORT :Paskutinė žinutė/naujiena
+STR_0201_MESSAGE_SETTINGS :Žinučių nustatymai
STR_MESSAGE_HISTORY_MENU :Zinuciu istorija
-STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Parodyti paskutine zinute/naujiena, rodyti zinuciu nustatymus
-STR_0204_MESSAGE_OPTIONS :{WHITE}Zinuciu nustatymai
-STR_0205_MESSAGE_TYPES :{BLACK}Zinuciu tipai:
-STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Pirmos transporto priemones atvykimas i zaidejo stotele
-STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Pirmos transporto priemones atvykimas i konkurento stotele
-STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Incidentai / nelaimes
+STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Rodyti paskutinę žinute/naujieną, rodyti žinučių nustatymus
+STR_0204_MESSAGE_OPTIONS :{WHITE}Žinučių nustatymai
+STR_0205_MESSAGE_TYPES :{BLACK}Žinučių tipai:
+STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Pirmosios transporto priemonės atvykimas į žaidėjo stotelę
+STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Pirmosios transporto priemonės atvykimas į konkurento stotelę
+STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Avarijos / nelaimės
STR_0209_COMPANY_INFORMATION :{YELLOW}Kompanijos informacija
-STR_020A_ECONOMY_CHANGES :{YELLOW}Ekonomikos pasikeitimai
-STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Patarimai / informacija apie zaidejo transporto priemones
-STR_020C_NEW_VEHICLES :{YELLOW}Naujas transporto priemones
-STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Prekiu supirkimo stotelese pokycius
-STR_020E_SUBSIDIES :{YELLOW}Subsidijas
-STR_020F_GENERAL_INFORMATION :{YELLOW}Bendraja informacija
+STR_020A_ECONOMY_CHANGES :{YELLOW}Ekonomikos pokyčiai
+STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Patarimai / informacija apie žaidėjo transporto priemones
+STR_020C_NEW_VEHICLES :{YELLOW}Naujos transporto priemonės
+STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Prekių supirkimo pokyčiai
+STR_020E_SUBSIDIES :{YELLOW}Subsidijos
+STR_020F_GENERAL_INFORMATION :{YELLOW}Bendroji informacija
STR_MESSAGES_ALL :{YELLOW}Pranesimu nustatymai (ijungta/isjungta/santrauka)
STR_MESSAGE_SOUND :{YELLOW}Groti garsus pasirodzius naujienu santraukoms
-STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...per toli nuo pries tai buvusio keliones tikslo
-STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Geriausios kompanijos, kurios pasieke {NUM}{}({STRING} lygi)
+STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...per toli buvusio keliones tikslo
+STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Geriausios kompanijos, kurios pasieke {NUM}{}({STRING} lygį)
STR_TOP_COMPANIES_NETWORK_GAME :{BIGFONT}{BLACK}Kompaniju Lygos lentele {NUM}
STR_0212 :{BIGFONT}{COMMA}.
STR_0213_BUSINESSMAN :Biznierius
STR_0214_ENTREPRENEUR :Verslininkas
-STR_0215_INDUSTRIALIST :Fabrikantas
+STR_0215_INDUSTRIALIST :Pramonininkas
STR_0216_CAPITALIST :Kapitalistas
STR_0217_MAGNATE :Magnatas
STR_0218_MOGUL :Didziausias magnatas
-STR_0219_TYCOON_OF_THE_CENTURY :Amziaus magnatas
+STR_0219_TYCOON_OF_THE_CENTURY :Amžiaus magnatas
STR_HIGHSCORE_NAME :{BIGFONT}{PLAYERNAME}, {COMPANY}
STR_HIGHSCORE_STATS :{BIGFONT}'{STRING}' ({COMMA})
-STR_021B_ACHIEVES_STATUS :{BLACK}{BIGFONT}{COMPANY} pasieke '{STRING}' statusa!
-STR_021C_OF_ACHIEVES_STATUS :{WHITE}{BIGFONT}Zaidejas{PLAYERNAME}{COMPANY} pasieke '{STRING}' statusa!
+STR_021B_ACHIEVES_STATUS :{BLACK}{BIGFONT}{COMPANY} pasiekė „{STRING}“ statusą!
+STR_021C_OF_ACHIEVES_STATUS :{WHITE}{BIGFONT}{PLAYERNAME} iš {COMPANY} pasiekė „{STRING}“ statusą!
STR_021F :{BLUE}{COMMA}
-STR_0220_CREATE_SCENARIO :{BLACK}Sukurti scenariju
+STR_0220_CREATE_SCENARIO :{BLACK}Sukurti scenarijų
STR_0221_OPENTTD :{YELLOW}OpenTTD
-STR_0222_SCENARIO_EDITOR :{YELLOW}Scenarijaus Redaktorius
-STR_0223_LAND_GENERATION :{WHITE}Sausumos generatorius
+STR_0222_SCENARIO_EDITOR :{YELLOW}Scenarijaus redaktorius
+STR_0223_LAND_GENERATION :{WHITE}Kraštovaidžio kūrimas
STR_0224 :{BLACK}{UPARROW}
STR_0225 :{BLACK}{DOWNARROW}
-STR_0226_RANDOM_LAND :{BLACK}Atsitiktine sausuma
-STR_0227_RESET_LAND :{BLACK}Generuoti isnaujo sausuma
-STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Padidinkite plota zemes aukstinimui/zeminimui
-STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Sumazinkite plota zemes aukstinimui/zeminimui
-STR_022A_GENERATE_RANDOM_LAND :{BLACK}Generuoti atsitiktine sausuma
-STR_022B_RESET_LANDSCAPE :{BLACK}Perkrauti landsafta
-STR_022C_RESET_LANDSCAPE :{WHITE}Perkrauti landsafta
+STR_0226_RANDOM_LAND :{BLACK}Atsitiktinis reljefas
+STR_0227_RESET_LAND :{BLACK}Anuliuoti reljefą
+STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Padidinkite sausumos plotą norėdami paaukštinti/pažeminti
+STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Sumažinkite sausumos plotą norėdami paaukštinti/pažeminti
+STR_022A_GENERATE_RANDOM_LAND :{BLACK}Kurti atsitiktinę sausumą
+STR_022B_RESET_LANDSCAPE :{BLACK}Anuliuoti kraštovaizdį
+STR_022C_RESET_LANDSCAPE :{WHITE}Anuliuoti kraštovaizdį
STR_LOAD_GAME_HEIGHTMAP :{WHITE}Naudoti Papildoma Zemelapi
STR_LOAD_SCEN_HEIGHTMAP :{BLACK}Naudoti Papildoma Zemelapi
-STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Ar tikrai nori perkrauti landsafta?
-STR_022E_LANDSCAPE_GENERATION :{BLACK}Landsafto generavimas
-STR_022F_TOWN_GENERATION :{BLACK}Miestu generavimas
-STR_0230_INDUSTRY_GENERATION :{BLACK}Pramones generavimas
-STR_0231_ROAD_CONSTRUCTION :{BLACK}Kelio konstrukcijos
-STR_0233_TOWN_GENERATION :{WHITE}Miesto generavimas
+STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Ar tikrai norite anuliuoti kraštovaiždį?
+STR_022E_LANDSCAPE_GENERATION :{BLACK}Kraštovaizdžio kūrimas
+STR_022F_TOWN_GENERATION :{BLACK}Miesto įkūrimas
+STR_0230_INDUSTRY_GENERATION :{BLACK}Pramonės kūrimas
+STR_0231_ROAD_CONSTRUCTION :{BLACK}Kelio tiesimas
+STR_0233_TOWN_GENERATION :{WHITE}Miesto įkūrimas
STR_0234_NEW_TOWN :{BLACK}Naujas miestas
-STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Ikurti nauja miesta
-STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Miesto cia statyti negalima...
-STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...per arti zemelapio krasto
+STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Įkurti naują miestą
+STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Negalima įkurti miesto...
+STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...per arti žemėlapio krašto
STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...per arti kito miesto
STR_0239_SITE_UNSUITABLE :{WHITE}...netinkamas sklypas
-STR_023A_TOO_MANY_TOWNS :{WHITE}...per daug miestu
+STR_023A_TOO_MANY_TOWNS :{WHITE}...per daug miestų
STR_CANNOT_GENERATE_TOWN :{WHITE}Neimanoma statyti jokiu miestu
STR_NO_SPACE_FOR_TOWN :{WHITE}...daugiau nera vietos zemelapyje
-STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Padidinti miesto dydi
-STR_023C_EXPAND :{BLACK}Isplesti
+STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Padidinti miesto dydį
+STR_023C_EXPAND :{BLACK}Išplėsti
STR_023D_RANDOM_TOWN :{BLACK}Atsitiktinis miestas
-STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Pastatyti miesta atsitiktineje vietoje
-STR_023F_INDUSTRY_GENERATION :{WHITE}Pramones generavimas
+STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Pastatyti miestą atsitiktinėję vietoje
+STR_023F_INDUSTRY_GENERATION :{WHITE}Pramonės kūrimas
STR_0240_COAL_MINE :{BLACK}Anglies kasykla
-STR_0241_POWER_STATION :{BLACK}Elektrine
-STR_0242_SAWMILL :{BLACK}Lentpjuve
-STR_0243_FOREST :{BLACK}Miskas
-STR_0244_OIL_REFINERY :{BLACK}Naftos perdirbimo imone
-STR_0245_OIL_RIG :{BLACK}Naftos bokstas
-STR_0246_FACTORY :{BLACK}Fabrikas
+STR_0241_POWER_STATION :{BLACK}Elektrinė
+STR_0242_SAWMILL :{BLACK}Lentpjūvė
+STR_0243_FOREST :{BLACK}Miškas
+STR_0244_OIL_REFINERY :{BLACK}Naftos perdirbimo įmone
+STR_0245_OIL_RIG :{BLACK}Naftos bokštas
+STR_0246_FACTORY :{BLACK}Gamykla
STR_0247_STEEL_MILL :{BLACK}Plieno liejykla
STR_0248_FARM :{BLACK}Ferma
-STR_0249_IRON_ORE_MINE :{BLACK}Gelezies rudos kasykla
-STR_024A_OIL_WELLS :{BLACK}Naftos greziniai
+STR_0249_IRON_ORE_MINE :{BLACK}Geležies rūdos kasykla
+STR_024A_OIL_WELLS :{BLACK}Naftos gręžiniai
STR_024B_BANK :{BLACK}Bankas
-STR_024C_PAPER_MILL :{BLACK}Popieriaus fabrikas
-STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Maisto perdirbimo imone
-STR_024E_PRINTING_WORKS :{BLACK}Spaustuve
+STR_024C_PAPER_MILL :{BLACK}Popieriaus gamykla
+STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Maisto perdirbimo įmonė
+STR_024E_PRINTING_WORKS :{BLACK}Spaustuvė
STR_024F_GOLD_MINE :{BLACK}Aukso kasykla
-STR_0250_LUMBER_MILL :{BLACK}Lentpjuve
-STR_0251_FRUIT_PLANTATION :{BLACK}Vaisiu plantacija
-STR_0252_RUBBER_PLANTATION :{BLACK}Kauciuko plantacija
-STR_0253_WATER_SUPPLY :{BLACK}Vandens grezinys
-STR_0254_WATER_TOWER :{BLACK}Vandentiekio bokstas
-STR_0255_DIAMOND_MINE :{BLACK}Deimantu kasykla
-STR_0256_COPPER_ORE_MINE :{BLACK}Vario rudos kasykla
-STR_0257_COTTON_CANDY_FOREST :{BLACK}Cukraus vatos krumynai
-STR_0258_CANDY_FACTORY :{BLACK}Saldainiu fabrikas
-STR_0259_BATTERY_FARM :{BLACK}Bateriju ferma
-STR_025A_COLA_WELLS :{BLACK}Kolos greziniai
-STR_025B_TOY_SHOP :{BLACK}Zaislu parduotuve
-STR_025C_TOY_FACTORY :{BLACK}Zaislu fabrikas
-STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastmases versmes
-STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Gaiviuju gerimu fabrikas
-STR_025F_BUBBLE_GENERATOR :{BLACK}Burbulu leistuvas
-STR_0260_TOFFEE_QUARRY :{BLACK}Karameles telkinys
+STR_0250_LUMBER_MILL :{BLACK}Lentpjuvė
+STR_0251_FRUIT_PLANTATION :{BLACK}Vaismedžių plantacija
+STR_0252_RUBBER_PLANTATION :{BLACK}Kaučiukmedių plantacija
+STR_0253_WATER_SUPPLY :{BLACK}Vandens gręžinys
+STR_0254_WATER_TOWER :{BLACK}Vandentiekio bokštas
+STR_0255_DIAMOND_MINE :{BLACK}Deimantų kasykla
+STR_0256_COPPER_ORE_MINE :{BLACK}Vario rūdos kasykla
+STR_0257_COTTON_CANDY_FOREST :{BLACK}Cukraus vatos krūmynai
+STR_0258_CANDY_FACTORY :{BLACK}Saldumynų gamykla
+STR_0259_BATTERY_FARM :{BLACK}Baterijų ūkis
+STR_025A_COLA_WELLS :{BLACK}Kolos gręžiniai
+STR_025B_TOY_SHOP :{BLACK}Žaislų parduotuvė
+STR_025C_TOY_FACTORY :{BLACK}Žaislų gamykla
+STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastmasės versmės
+STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Gaiviųjų gėrimų gamykla
+STR_025F_BUBBLE_GENERATOR :{BLACK}Burbulų leistuvas
+STR_0260_TOFFEE_QUARRY :{BLACK}Karamelės telkinys
STR_0261_SUGAR_MINE :{BLACK}Cukraus kasykla
-STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Statyti anglies kasykla
-STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Statyti elektrine
-STR_0264_CONSTRUCT_SAWMILL :{BLACK}Statyti lentpjuve
-STR_0265_PLANT_FOREST :{BLACK}Uzsodinti miska
-STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Statyti naftos perdirbimo imone
-STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Statyti naftos grezini juroje (Tik netoli zemelapio krastu)
-STR_0268_CONSTRUCT_FACTORY :{BLACK}Statyti fabrika
-STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Statyti plieno liejykla
-STR_026A_CONSTRUCT_FARM :{BLACK}Statyti ferma
-STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Statyti gelezies rudos kasykla
-STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Grezti naftos grezinius
-STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Statyti banka (Tik miestuose su bent 1200 gyventoju)
-STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Statyti popieriaus fabrika
-STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Statyti maisto perdirbimo imone
-STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Statyti spaustuve
-STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Statyti aukso kasykla
-STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Statyti banka (statyti galima tiktai miestuose)
-STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Pastatykite lentpjuve (nukirstos medienos perdirbimui)
-STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Uzsodinti vaisiu plantacija
-STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Uzsodinti kauciuko plantacija
-STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Grezti artezini grezini
-STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Statyti vandentiekio boksta (tik miestuose)
-STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Statyti deimantu kasykla
-STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Statyti vario rudos kasykla
-STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Uzveisti cukraus vatos krumynus
-STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Statyti saldainiu fabrika
-STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Uzsodinti bateriju ferma
-STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Statyti kolos grezinius
-STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Statyti zaislu parduotuve
-STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Statyti zaislu fabrika
-STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Statyti plastmases versmes
-STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Statyti gaiviuju gerimu fabrika
-STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Statyti burbulu generatoriu
-STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Statyti karameles telkini
-STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Statyti cukraus kasykla
-STR_0285_CAN_T_BUILD_HERE :{WHITE}Cia statyti neimanoma {STRING} ...
-STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...pirma reikia pastatyti miesta
+STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Statyti anglies kasyklą
+STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Statyti elektrinę
+STR_0264_CONSTRUCT_SAWMILL :{BLACK}Statyti lentpjuvę
+STR_0265_PLANT_FOREST :{BLACK}Užsodinti mišką
+STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Statyti naftos perdirbimo įmone
+STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Statyti naftos grežinį jūroje (tik prie žemelapio kraštų)
+STR_0268_CONSTRUCT_FACTORY :{BLACK}Statyti gamyklą
+STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Statyti plieno liejyklą
+STR_026A_CONSTRUCT_FARM :{BLACK}Statyti ūkį
+STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Statyti geležies rūdos kasyklą
+STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Gręžti naftos gręžinius
+STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Statyti banką (tik miestuose, kuriuose yra bent 1200 gyventojų)
+STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Statyti popieriaus gamyklą
+STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Statyti maisto perdirbimo imonę
+STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Statyti spaustuvę
+STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Statyti aukso kasyklą
+STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Statyti banką (tik miestuose)
+STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Pastatykite lentpjūvę (perdirbama nukirsta mediena)
+STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Užsodinti vaismedžių plantaciją
+STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Užsodinti kaučiukmedžių plantaciją
+STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Statyti vandentiekį
+STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Statyti vandentiekio bokštą (tik miestuose)
+STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Statyti deimantų kasyklą
+STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Statyti vario rūdos kasyklą
+STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Užsodinti cukraus vatos krūmynus
+STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Statyti saldumynų gamyklą
+STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Statyti baterijų ūkį
+STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Statyti kolos šulinius
+STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Statyti žaislų parduotuvę
+STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Statyti žaislų gamyklą
+STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Statyti plastmasės versmes
+STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Statyti gaiviųjų gėrimų gamyklą
+STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Statyti burbulų pūstuvą
+STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Statyti karamelės telkinį
+STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Statyti cukraus kasyklą
+STR_0285_CAN_T_BUILD_HERE :{WHITE}{STRING} čia negali būti pastatytas...
+STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...pirma reikia pastatyti miestą
STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...mieste gali buti tik vienas
-STR_0288_PLANT_TREES :{BLACK}Sodinti medzius
-STR_0289_PLACE_SIGN :{BLACK}Statyti zenkla
-STR_028A_RANDOM_TREES :{BLACK}Atsitiktiniai medziai
-STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Atsitiktinai apsodinti sausuma medziais
-STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Sukurti uoletas vietas
-STR_028D_PLACE_LIGHTHOUSE :{BLACK}Statyti svyturi
-STR_028E_PLACE_TRANSMITTER :{BLACK}Statyti retransliatoriu
-STR_028F_DEFINE_DESERT_AREA :{BLACK}Pazymeti kaip dykuma
+STR_0288_PLANT_TREES :{BLACK}Sodinti medžius
+STR_0289_PLACE_SIGN :{BLACK}Statyti ženklą
+STR_028A_RANDOM_TREES :{BLACK}Atsitiktiniai medžiai
+STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Atsitiktinai apsodinti sausumą medziais
+STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Sukurti uolėtas vietas
+STR_028D_PLACE_LIGHTHOUSE :{BLACK}Statyti švyturį
+STR_028E_PLACE_TRANSMITTER :{BLACK}Statyti siųstuvą
+STR_028F_DEFINE_DESERT_AREA :{BLACK}Nurodyti dykumos plotus{}Laikant nuspaustą VALD (CTRL) galima ją pašalinti
STR_CREATE_LAKE :{BLACK}Pazymeti kaip vandeni, aplinkines zemes bus uztvindytos, jei bus juros lygyje
-STR_0290_DELETE :{BLACK}Salinti
-STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Salinti si miesta
-STR_0292_SAVE_SCENARIO :Issaugoti scenariju
-STR_0293_LOAD_SCENARIO :Atverti scenariju
-STR_0294_QUIT_EDITOR :Uzdaryti Redaktoriu
+STR_0290_DELETE :{BLACK}Šalinti
+STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Šalinti šį miestą
+STR_0292_SAVE_SCENARIO :Išsaugoti scenarijų
+STR_0293_LOAD_SCENARIO :Atverti scenarijų
+STR_0294_QUIT_EDITOR :Uždaryti redaktoriu
STR_0295 :
-STR_0296_QUIT :Iseiti
-STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Issaugoti, atverti scenariju, iseiti
-STR_0298_LOAD_SCENARIO :{WHITE}Atverti scenariju
-STR_0299_SAVE_SCENARIO :{WHITE}Issaugoti scenariju
-STR_029A_PLAY_SCENARIO :{BLACK}Isbandyti scenariju (zaisti)
+STR_0296_QUIT :Išeiti
+STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Išsaugoti scenarijų, atverti scenarijų, išjungti scenarijų redaktorių, išeiti
+STR_0298_LOAD_SCENARIO :{WHITE}Atverti scenarijų
+STR_0299_SAVE_SCENARIO :{WHITE}Išsaugoti scenarijų
+STR_029A_PLAY_SCENARIO :{BLACK}Išbandyti scenarijų (žaisti)
STR_PLAY_HEIGHTMAP :{BLACK}Zaisti Papildomam zemelapyje
STR_PLAY_HEIGHTMAP_HINT :{BLACK}Pradeti zaidima naudojant papildoma zemelapi ir zemtvraka
-STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Ar tikrai nori iseiti is sio scenarijaus?
-STR_029C_QUIT_EDITOR :{WHITE}Iseiti is Redaktoriaus
-STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...gali buti pastatyta tik miestuose, kuriuose yra bent 1200 gyventoju
-STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Zaidimo pradzios data sumazinti 1 metais
-STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Zaidimo pradzios data padidinti 1 metais
-STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...abu tilto galai turi buti ant zemes
-STR_02A1_SMALL :{BLACK}Mazas
+STR_QUIT_SCENARIO_QUERY :{YELLOW}Ar tikrai norite išeiti iš šio scenarijaus?
+STR_029C_QUIT_EDITOR :{WHITE}Išeiti iš redaktoriaus
+STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...gali buti pastatyta tik miestuose, kuriuose yra bent 1200 gyventojų
+STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Žaidimo pradžios datą sumažinti 1 metais
+STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Žaidimo pradžios datą padidinti 1 metais
+STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...abu tilto galai turi buti ant zemės
+STR_02A1_SMALL :{BLACK}Mažas
STR_02A2_MEDIUM :{BLACK}Vidutinis
STR_02A3_LARGE :{BLACK}Didelis
-STR_02A4_SELECT_TOWN_SIZE :{BLACK}Issirinkite miesto dydi
+STR_02A4_SELECT_TOWN_SIZE :{BLACK}Išsirinkite miesto dydį
STR_02A5_TOWN_SIZE :{YELLOW}Miesto dydis:
STR_02B6 :{STRING} - {STRING}
-STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Parodyti paskutine zinute ar spaudos pranesima
+STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Parodyti paskutinę žinutę ar spaudos pranešimą
STR_OFF :Isjungta
STR_SUMMARY :Santrauka
STR_FULL :Pilnas
STR_02BA :{SILVER}- - {COMPANY} - -
-STR_02BB_TOWN_DIRECTORY :Miestai
-STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Tr. priemoniu pavadinimai
+STR_02BB_TOWN_DIRECTORY :Miestų sąrašas
+STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Tr. priemonių pavadinimai
STR_02BD :{BLACK}{STRING}
STR_02BE_DEFAULT :Standartinis
-STR_02BF_CUSTOM :Tinkintas :)
-STR_02C0_SAVE_CUSTOM_NAMES :{BLACK}Issaugoti tinkintus vardus
-STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Transporto priemoniu pavadinimu pasirinkimo laukas
-STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Issaugoti transporto priemoniu pavadinimus
+STR_02BF_CUSTOM :Tinkintas
+STR_02C0_SAVE_CUSTOM_NAMES :{BLACK}Išsaugoti tinkintus vardus
+STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Transporto priemonių pavadinimų pasirinkimo laukas
+STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Išsaugoti transporto priemonių pavadinimus
+STR_CHECKMARK :{CHECKMARK}
############ range for menu starts
-STR_02C3_GAME_OPTIONS :Zaidimo nustatymai
+STR_02C3_GAME_OPTIONS :Žaidimo parinktys
STR_02C5_DIFFICULTY_SETTINGS :Sunkumo nustatymai
STR_02C7_CONFIG_PATCHES :Nustatymai
STR_NEWGRF_SETTINGS :Papild. grafikos nustatymai
STR_GAMEOPTMENU_0A :
-STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Rodyti miestu pavadinimus
-STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Rodyti stoteliu pavadinimus
-STR_02CE_SIGNS_DISPLAYED :{SETX 12}Rodyti zenklus
+STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Rodyti miestų pavadinimus
+STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Rodyti stotelių pavadinimus
+STR_02CE_SIGNS_DISPLAYED :{SETX 12}Rodyti ženklus
STR_WAYPOINTS_DISPLAYED2 :{SETX 12}Rodyti tarpines stoteles
STR_02D0_FULL_ANIMATION :{SETX 12}Pilna animacija
STR_02D2_FULL_DETAIL :{SETX 12}Pilna detalizacija
@@ -757,7 +790,7 @@
STR_CONSOLE_SETTING :Konsole
STR_02D7_SCREENSHOT_CTRL_S :Fotografuoti ekrano vaizda (Ctrl-S)
STR_02D8_GIANT_SCREENSHOT_CTRL_G :Fotografuoti viso ekrano vaizda (Ctrl-G)
-STR_02D9_ABOUT_OPENTTD :Apie 'OpenTTD'
+STR_02D9_ABOUT_OPENTTD :Apie „OpenTTD“
############ range ends here
STR_02DB_OFF :{BLACK}Isjungta
@@ -801,7 +834,7 @@
STR_02FC_LOAD_A_SAVED_GAME :{BLACK}Atverti issaugota zaidima
STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Sukurk savo zaidimo zemelapi/scenariju
STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Pasirink 1 zaidejo zaidima
-STR_0300_SELECT_MULTIPLAYER_GAME :{BLACK}Pasirink keliu zaideju (2-8) zaidima tinkle
+STR_0300_SELECT_MULTIPLAYER_GAME :{BLACK}Pasirinkite komandinį žaidima skirtą 2-8 žaidėjams
STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Rodyti zaidimo nustatymus
STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Rodyti sudetingumo nustatymus
STR_0303_START_A_NEW_GAME_USING :{BLACK}Naujas zaidimas naudojantis scenarijumi
@@ -840,25 +873,27 @@
STR_0336_7 :{BLACK}7
############ start of townname region
-STR_TOWNNAME_ORIGINAL_ENGLISH :Anglu (Oginalus)
-STR_TOWNNAME_FRENCH :Prancuzu
-STR_TOWNNAME_GERMAN :Vokieciu
-STR_TOWNNAME_ADDITIONAL_ENGLISH :Anglu (Papildomas)
-STR_TOWNNAME_LATIN_AMERICAN :Lotynu-Amerikos
+STR_TOWNNAME_ORIGINAL_ENGLISH :Anglų (Oginalus)
+STR_TOWNNAME_FRENCH :Prancūzų
+STR_TOWNNAME_GERMAN :Vokiečių
+STR_TOWNNAME_ADDITIONAL_ENGLISH :Anglų (Papildomas)
+STR_TOWNNAME_LATIN_AMERICAN :Lotynų-Amerikos
STR_TOWNNAME_SILLY :Kvaili
-STR_TOWNNAME_SWEDISH :Svedu
-STR_TOWNNAME_DUTCH :Olandu
-STR_TOWNNAME_FINNISH :Suomiu
-STR_TOWNNAME_POLISH :Lenku
-STR_TOWNNAME_SLOVAKISH :Slovaku
-STR_TOWNNAME_NORWEGIAN :Norvegu
-STR_TOWNNAME_HUNGARIAN :Vengru
-STR_TOWNNAME_AUSTRIAN :Austru
-STR_TOWNNAME_ROMANIAN :Rumunu
-STR_TOWNNAME_CZECH :Ceku
-STR_TOWNNAME_SWISS :Sveicaru
-STR_TOWNNAME_DANISH :Daniski
-STR_TOWNNAME_TURKISH :Turkiski
+STR_TOWNNAME_SWEDISH :Švedų
+STR_TOWNNAME_DUTCH :Olandų
+STR_TOWNNAME_FINNISH :Suomių
+STR_TOWNNAME_POLISH :Lenkų
+STR_TOWNNAME_SLOVAKISH :Slovakų
+STR_TOWNNAME_NORWEGIAN :Norvegų
+STR_TOWNNAME_HUNGARIAN :Vengrų
+STR_TOWNNAME_AUSTRIAN :Austrų
+STR_TOWNNAME_ROMANIAN :Rumunų
+STR_TOWNNAME_CZECH :Čekų
+STR_TOWNNAME_SWISS :Šveicarų
+STR_TOWNNAME_DANISH :Danų
+STR_TOWNNAME_TURKISH :Turkiški
+STR_TOWNNAME_ITALIAN :Italų
+STR_TOWNNAME_CATALAN :Katalonų
############ end of townname region
STR_CURR_GBP :Svarai sterlingai (£)
@@ -883,7 +918,11 @@
STR_CURR_PLN :Lenkijos zlotai (PLN)
STR_CURR_ROL :Rumunijos lejos (ROL)
STR_CURR_RUR :Rusijos rubliai (RUR)
+STR_CURR_SIT :Slovėnijos tolarai (SIT)
STR_CURR_SEK :Svedijos kronos (SEK)
+STR_CURR_YTL :Turkijos liros (YTL)
+STR_CURR_SKK :Slovakijos kronos (SKK)
+STR_CURR_BRR :Brazilijos realai (BRL)
STR_CURR_CUSTOM :Kita...
@@ -984,6 +1023,7 @@
STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Leisti sujungti greta pastatytas stoteles: {ORANGE}{STRING}
STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Palikti stotele, jei nors 1 krovinys pilnai pakrautas: {ORANGE}{STRING}
STR_CONFIG_PATCHES_IMPROVEDLOAD :{LTBLUE}Naudoti patobulinta krovimo algoritma: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_GRADUAL_LOADING :{LTBLUE}Pakrauti tr. priemones paeiliui: {ORANGE}{STRING}
STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Infliacija: {ORANGE}{STRING}
STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Pristatyti krovini stotelei tiktai tuomet, kai yra poreikis: {ORANGE}{STRING}
STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Leisti statyti labai ilgus tiltus: {ORANGE}{STRING}
@@ -1000,9 +1040,11 @@
STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Leisti papirkineti miesto valdzia: {ORANGE}{STRING}
STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Nestandartines stoteles: {ORANGE}{STRING}
STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL :{LTBLUE}Globalus kelio radimo algoritmas (NPF, panaikina NTP): {ORANGE}{STRING}
+STR_CONFIG_PATCHES_FREIGHT_TRAINS :{LTBLUE}Krovinių svorio daugiklis skirtas imituoti prikrautus traukinius: {ORANGE}{STRING}
STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Visada leisti statyti mazus oro uotus: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_WARN_LOST_TRAIN :{LTBLUE}Perspėti apie traukinio praradimą: {ORANGE}{STRING}
STR_CONFIG_PATCHES_ORDER_REVIEW :{LTBLUE}Perziureti tr. pr. uzduotis: {ORANGE}{STRING}
STR_CONFIG_PATCHES_ORDER_REVIEW_OFF :ne
STR_CONFIG_PATCHES_ORDER_REVIEW_EXDEPOT :taip, bet isskyrus sustabdytas tr. pr.
@@ -1016,10 +1058,35 @@
STR_CONFIG_PATCHES_POPULATION_IN_LABEL :{LTBLUE}Rodyti miestu gyventoju skaiciu salia pavadinimo: {ORANGE}{STRING}
STR_CONFIG_PATCHES_INVISIBLE_TREES :{LTBLUE}Nematomi medziai (kai ijungti permatomi pastatai): {ORANGE}{STRING}
+STR_CONFIG_PATCHES_LAND_GENERATOR :{LTBLUE}Sausumos kūrimas: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL :Originalus
+STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis
+STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE :{LTBLUE}Didžiausias atstumas nuo kraštų naftos perdirbimo įmonėms {ORANGE}{STRING}
STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Sniego linijos aukstis: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN :{LTBLUE}Paviršiaus nelygumas (tik TerraGenesis) : {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Labai lygus
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH :Lygus
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH :Kalnuotas
+STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :Labai kalnuotas
+STR_CONFIG_PATCHES_TREE_PLACER :{LTBLUE}Medžių sodinimo algoritmas: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_TREE_PLACER_NONE :Jokio
+STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL :Standartinis
+STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED :Pagerintas
+STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION :{LTBLUE}Aukščių žemėlapio pasukimas: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :Prieš laikrodžio rodyklę
+STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE :Pagal laikrodžio rodyklę
+STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT :{LTBLUE}Aušktis skiriamas „lygiaus scenarijaus“ žemėlapiui: {ORANGE}{STRING}
STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maks. soties plotis: {ORANGE}{STRING} {RED}Demesio: Auksti parametrai letina zaidima
STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Remontuoti malunsparnius automatiskai: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR :{LTBLUE}Susieti kraštovaizdžio įrankių juostą su bėgių/kelių/vandens/orouostų įrankių juostomis: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_REVERSE_SCROLLING :{LTBLUE}Apkeisti slinkties kryptį: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_MEASURE_TOOLTIP :{LTBLUE}Rodyti matavimo pastabą, kai naudojami įvairūs statybų įrankiai: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_LIVERIES :{LTBLUE}Rodyti kompanijos ženklus: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_LIVERIES_NONE :Jokių
+STR_CONFIG_PATCHES_LIVERIES_OWN :Savo kompanijos
+STR_CONFIG_PATCHES_LIVERIES_ALL :Visų kompanijų
+STR_CONFIG_PATCHES_PREFER_TEAMCHAT :{LTBLUE}Rašyti komandai naudojant <ĮVESTI> (ENTER): {ORANGE}{STRING}
STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maks. traukiniu vienam zaidejui: {ORANGE}{STRING}
STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maks. automobiliu zaidejui: {ORANGE}{STRING}
@@ -1032,6 +1099,7 @@
STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Atjungti laivus kompiuteriui: {ORANGE}{STRING}
STR_CONFIG_PATCHES_AINEW_ACTIVE :{LTBLUE}Naujas dirbtinio intelekto algoritmas AI (testuojamas): {ORANGE}{STRING}
+STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER :{LTBLUE}Naudoti DI (dirbtinį intelektą) komandiniame žaidime (eksperimentinis): {ORANGE}{STRING}
STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Traukiniu remonto intervalas: {ORANGE}{STRING} (d. ar %)
STR_CONFIG_PATCHES_SERVINT_TRAINS_DISABLED :{LTBLUE}Traukiniu remonto intervalas: {ORANGE}isjungta
@@ -1043,6 +1111,7 @@
STR_CONFIG_PATCHES_SERVINT_SHIPS_DISABLED :{LTBLUE}Laivu remonto intervalas: {ORANGE} isjungta
STR_CONFIG_PATCHES_NOSERVICE :{LTBLUE}Atjungti technine apziura, jei gedimai nenaudojami: {ORANGE}{STRING}
STR_CONFIG_PATCHES_WAGONSPEEDLIMITS :{LTBLUE}Suaktyvinti vagonu greicio apribojima: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_DISABLE_ELRAILS :{LTBLUE}Uždrausti elektrinius bėgius: {ORANGE}{STRING}
STR_CONFIG_PATCHES_COLORED_NEWS_YEAR :{LTBLUE}Spalvotos naujienos atsiranda: {ORANGE}{STRING}
STR_CONFIG_PATCHES_STARTING_YEAR :{LTBLUE}Zaidimo pradzia: {ORANGE}{STRING}
@@ -1055,6 +1124,7 @@
STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER :Centruoti
STR_CONFIG_PATCHES_TOOLBAR_POS_RIGHT :Desineje
STR_CONFIG_PATCHES_SNAP_RADIUS :{LTBLUE}Langu persidengimo atstumas: {ORANGE}{STRING} px
+STR_CONFIG_PATCHES_SNAP_RADIUS_DISABLED :{LTBLUE}Langų kibumo atsumas: {ORANGE}disabled
STR_CONFIG_PATCHES_GUI :{BLACK}Vaizdas
STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstrukcijos
@@ -1165,14 +1235,14 @@
STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Statyti anglies kasykla
STR_CONSTRUCT_FOREST_TIP :{BLACK}Sodinti miska
STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Statyti naftos platforma
-STR_CONSTRUCT_FARM_TIP :{BLACK}Isteigti ferma
+STR_CONSTRUCT_FARM_TIP :{BLACK}Įsteigti ūkį
STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Statyti vario rudos kasykla
STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Ieskoti naftos
STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Statyti aukso kasyklas
STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Statyti deimantu kasyklas
STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Statyti anglies rudos kasykla
-STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Uzsodinti vaisiu plantacija
-STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Uzsodinti kauciuko plantacija
+STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Užsodinti vaismedžių plantaciją
+STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Užsodinti kaučiukmedžių plantaciją
STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Statyti vandens siurbline
STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Uzsodinti ledinuku miska
STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Statyti saules energijos baterijas
@@ -1199,10 +1269,11 @@
TEMP_AI_IN_PROGRESS :{WHITE}Dirbtinio intelekto algoritmas pradeda darba. Jei iskils problemu - fotografuok ekrano vaizda ir konsultuokis forumuose. Sekmes!
TEMP_AI_ACTIVATED :{WHITE}Demesio: sis naujas dirbtinio intelekto algoritmas dar tik testuojamas! Siuo metu dirba tik su automobiliais!
+TEMP_AI_MULTIPLAYER :{WHITE}Įspėjimas: realizacija dar eksperimentinė (naudojamas naujas Dirbtinis intelektas). Visas iškilusias problemas praneškite truelight@openttd.org.
############ network gui strings
-STR_NETWORK_MULTIPLAYER :{WHITE}Tinkle
+STR_NETWORK_MULTIPLAYER :{WHITE}Komandinis žaidimas
STR_NETWORK_PLAYER_NAME :{BLACK}Zaidejo vardas:
STR_NETWORK_ENTER_NAME_TIP :{BLACK}Tai vardas, pagal kuri kiti zaidejai tave pazins
@@ -1240,6 +1311,7 @@
STR_NETWORK_SERVER_OFFLINE :{SILVER}SERVERIS ISJUNGTAS
STR_NETWORK_SERVER_FULL :{SILVER}SERVERIS PILNAS
STR_NETWORK_VERSION_MISMATCH :{SILVER}VERSIJU NESUTAPIMAS
+STR_NETWORK_GRF_MISMATCH :{SILVER}NEWGRF NEATITIKIMAS
STR_NETWORK_JOIN_GAME :{BLACK}Jungtis
@@ -1331,6 +1403,7 @@
STR_NETWORK_CONNECTING_SPECIAL_1 :{BLACK}Gaunama zaidimo informacija..
STR_NETWORK_CONNECTING_SPECIAL_2 :{BLACK}Gaunama kompanijos informacija..
############ End of leave-in-this-order
+STR_NETWORK_CONNECTING_WAITING :{BLACK}{NUM} vartotoj{P as ai ų} prieš tave
STR_NETWORK_CONNECTING_DOWNLOADING :{BLACK}{NUM} / {NUM} Kb parsiusta
STR_NETWORK_DISCONNECT :{BLACK}Atsijungti
@@ -1377,17 +1450,21 @@
STR_NETWORK_CLIENT_JOINED :prisijunge prie zaidimo
STR_NETWORK_GIVE_MONEY :dave tavo kompanijai siek tiek pinigu: ({CURRENCY})
STR_NETWORK_GAVE_MONEY_AWAY :tu davei {STRING} siek tiek pinigu: ({CURRENCY})
-STR_NETWORK_CHAT_COMPANY :[Komanda] {STRING}:
-STR_NETWORK_CHAT_TO_COMPANY :[Komanda] Kam {STRING}:
-STR_NETWORK_CHAT_CLIENT :[Privaciai] {STRING}:
-STR_NETWORK_CHAT_TO_CLIENT :[Privaciai] Kam {STRING}:
-STR_NETWORK_CHAT_ALL :[Visiems] {STRING}:
+STR_NETWORK_CHAT_COMPANY_CAPTION :[Komandai] :
+STR_NETWORK_CHAT_COMPANY :[Komandai] {STRING}: {GRAY}{STRING}
+STR_NETWORK_CHAT_TO_COMPANY :[Komandai] {STRING}: {GRAY}{STRING}
+STR_NETWORK_CHAT_CLIENT_CAPTION :[Privačiai] :
+STR_NETWORK_CHAT_CLIENT :[Privačiai] {STRING}: {GRAY}{STRING}
+STR_NETWORK_CHAT_TO_CLIENT :[Privačiai] {STRING}: {GRAY}{STRING}
+STR_NETWORK_CHAT_ALL_CAPTION :[Visiems] :
+STR_NETWORK_CHAT_ALL :[Visiems] {STRING}: {GRAY}{STRING}
STR_NETWORK_NAME_CHANGE :pakeite savo varda i
STR_NETWORK_SERVER_SHUTDOWN :{WHITE} Serveris uzsidare
STR_NETWORK_SERVER_REBOOT :{WHITE} Serveris persikrauna...{}Prasau palaukti...
STR_NETWORK_SERVER :Serveris
STR_NETWORK_CLIENT :Zaidejas
+STR_NETWORK_SPECTATORS :Stebėtojai
STR_NETWORK_CLIENTLIST_NONE :(nera)
STR_NETWORK_CLIENTLIST_KICK :Ismesti (Kick)
@@ -1413,6 +1490,8 @@
STR_PNGMAP_ERR_IMAGE_TYPE :{WHITE}...Negali perversti paveiklselio. 8 arba 24-bit PNG paveikslelis reikalingas.
STR_PNGMAP_ERR_MISC :{WHITE}...kazkas buvo ne taip. Atsiprasome. (greiciausiai pazeistas failas)
+STR_BMPMAP_ERROR :{WHITE}Negalima nuskaityti kraštovaizdžio iš BMP...
+STR_BMPMAP_ERR_IMAGE_TYPE :{WHITE}...nepavyko pakeisti vaizdo failo formato.
##id 0x0800
STR_0800_COST :{TINYFONT}{RED}Kainuoja: {CURRENCY}
@@ -1590,6 +1669,7 @@
STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Statyti statula kompanijos garbei.{} Kainuos: {CURRENCY}
STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Finansuoti nauju komerciniu pastatu statyba mieste.{} Cost: {CURRENCY}
STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Pirkti isskirtines transporto teises mieste 1 metams. Miesto valdzia keleivius ir krovinius leis pervezti tik tavo kompanijai.{} Kaina: {CURRENCY}
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Paperkant vietinę valdžią pakeliamas Jūsų reitingas, tačiau, jeigu pagaus, bus taikoma sunki bausmė.{} Kaina: {CURRENCY}
STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING :{BIGFONT}{BLACK}Eismo chaosas {TOWN}!{}{}Keliu rekonstrukcija, finansuojama {COMPANY}, sukels 6 menesiu chaosa keliuose!
STR_2056 :{TINYFONT}{WHITE}{TOWN}
STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA})
@@ -1700,7 +1780,9 @@
STR_306A_BUOY_IN_THE_WAY :{WHITE}...pluduras pakeliui
STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stotis per daug issipletusi
STR_306D_NONUNIFORM_STATIONS_DISALLOWED :{WHITE}...nestandartines stoteles atjungtos
+STR_USE_CTRL_TO_SELECT_MORE :{BLACK}Laikant nuspaustą VALD (CTRL) galima pažymėti daugiau nei vieną
+STR_UNDEFINED :(neapibrėžta eilutė)
STR_STAT_CLASS_DFLT :Numatytoji stotis
STR_STAT_CLASS_WAYP :Keliarodziai
@@ -1732,6 +1814,7 @@
STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Pasirink zaujo zaidimo tipa
STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Pasirinkite scenariju (zalia spalva), nustatyta zaidima (melyna), ar atsitiktini nauja zaidima
STR_4010_GENERATE_RANDOM_NEW_GAME :Atsitiktinai generuoti nauja zaidima
+STR_4011_LOAD_HEIGHTMAP :{WHITE}Atverti aukščių žemėlapį
##id 0x4800
STR_4800_IN_THE_WAY :{WHITE}{STRING} kelyje
@@ -1745,11 +1828,11 @@
STR_4808_FACTORY :gamykla
STR_4809_PRINTING_WORKS :spaustuveje
STR_480A_STEEL_MILL :plieno liejykla
-STR_480B_FARM :ferma
+STR_480B_FARM :ūkis
STR_480C_COPPER_ORE_MINE :vario rudos kasykla
STR_480D_OIL_WELLS :naftos grezinys
STR_480E_BANK :banke
-STR_480F_FOOD_PROCESSING_PLANT :maisto perdirbimo imone
+STR_480F_FOOD_PROCESSING_PLANT :Maisto perdirbimo įmone
STR_4810_PAPER_MILL :popieriaus fabrike
STR_4811_GOLD_MINE :aukso kasykla
STR_4812_BANK :bankas
@@ -1760,7 +1843,7 @@
STR_4817_WATER_SUPPLY :vandens saugykloje
STR_4818_WATER_TOWER :vandentiekio bokste
STR_4819_FACTORY :gamykloje
-STR_481A_FARM :ferma
+STR_481A_FARM :ūkis
STR_481B_LUMBER_MILL :Lentpjuve
STR_481C_COTTON_CANDY_FOREST :ledinuku miskas
STR_481D_CANDY_FACTORY :saldumynu fabrike
@@ -2030,10 +2113,10 @@
STR_7037_PRESIDENT :{WHITE}{PLAYERNAME}{}{GOLD}(Direktorius)
STR_7038_INAUGURATED :{GOLD}Eina pareigas nuo: {WHITE}{NUM}
STR_7039_VEHICLES :{GOLD}Transporto priemones:
-STR_TRAINS :{WHITE}{COMMA} traukin{P ys iai}
-STR_ROAD_VEHICLES :{WHITE}{COMMA} automobili{P s ai}
+STR_TRAINS :{WHITE}{COMMA} traukin{P ys iai ių}
+STR_ROAD_VEHICLES :{WHITE}{COMMA} automobili{P s ai ų}
STR_AIRCRAFT :{WHITE}{COMMA} lektuvai
-STR_SHIPS :{WHITE}{COMMA} laiva{P s i}
+STR_SHIPS :{WHITE}{COMMA} laiv{P as ai ų}
STR_7042_NONE :{WHITE}Neturi
STR_7043_FACE_SELECTION :{WHITE}Veido pasirinkimas
STR_7044_MALE :{BLACK}Vyras
@@ -2403,8 +2486,8 @@
STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Gyventojai svencia . . .{}Pirmas traukinys atvaziavo i {STATION}!
STR_8802_DETAILS :{WHITE}{STRING} (Detales)
STR_8803_TRAIN_IN_THE_WAY :{WHITE}Traukinys kelyje
-STR_8804 :{SETX 10}{COMMA}: {STRING}
-STR_8805 :{RIGHTARROW}{SETX 10}{COMMA}: {STRING}
+STR_8804 :{SETX 10}{COMMA}: {STRING} {STRING}
+STR_8805 :{RIGHTARROW}{SETX 10}{COMMA}: {STRING} {STRING}
STR_8806_GO_TO :Vaziuoja i {STATION}
STR_8807_GO_TO_TRANSFER :Vykti i {STATION} (Perkelti ir pakrauti krovinius)
STR_8808_GO_TO_UNLOAD :Vykti i {STATION} (Issikrauti)
@@ -2432,6 +2515,7 @@
STR_UNKNOWN_DESTINATION :nezinomas tikslas
STR_8812_EMPTY :{LTBLUE}Tuscias
STR_8813_FROM :{LTBLUE}{CARGO} is {STATION}
+STR_FROM_MULT :{LTBLUE}{CARGO} iš {STATION} (x{NUM})
STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Traukinys {COMMA} laukia depe
STR_8815_NEW_VEHICLES :{BLACK}Naujos tr. priemones
STR_8816 :{BLACK}-
@@ -2443,10 +2527,15 @@
STR_NEW_ELRAIL_VEHICLES :{WHITE}Nauji Elektriniai Traukiniai
STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nauji Vienbegiai Traukiniai
STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nauji Maglev Traukiniai
+STR_ALL_AVAIL_RAIL_VEHICLES :{WHITE}Traukiniai
STR_881F_BUILD_VEHICLE :{BLACK}Pirkti
-STR_CLONE_ROAD_VEHICLE :{BLACK}Klonuoti Masina
-STR_CLONE_TRAIN :{BLACK}Klonuoti Traukini
+STR_CLONE_ROAD_VEHICLE :{BLACK}Kopijuoti automobilį
+STR_CLONE_ROAD_VEHICLE_INFO :{BLACK}Tai pagamins automobilio kopiją. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
+STR_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}Tai pagamins automobilio kopiją. Spragtelkite šį mygtuką, o tada automobilį esantį depe arba už jo ribų. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
+STR_CLONE_TRAIN :{BLACK}Kopijuoti traukinį
+STR_CLONE_TRAIN_INFO :{BLACK}Tai pagamins traukinio kopiją su visais vagonais. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
+STR_CLONE_TRAIN_DEPOT_INFO :{BLACK}Tai pagamins traukinio kopiją su visais vagonais. Spragtelkite šį mygtuką, o tada traukinį esantį depe arba už jo ribų. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
STR_8820_RENAME :{BLACK}Pervardinti
STR_8823_SKIP :{BLACK}Praleisti
STR_8824_DELETE :{BLACK}Istrinti
@@ -2454,6 +2543,9 @@
STR_8826_GO_TO :{BLACK}Vaziuoti
STR_8827_FULL_LOAD :{BLACK}Pakrauti
STR_8828_UNLOAD :{BLACK}Iskrauti
+STR_REFIT :{BLACK}Naujinti
+STR_REFIT_TIP :{BLACK}Pasirinkite kurį vagonų tipą kuriuo tipu pakeisti (eilės tvarka). Spragtelėjus laikant VALD (CTRL) nurodymas pašalinamas
+STR_REFIT_ORDER :(Keisti į {STRING})
STR_8829_ORDERS :{WHITE}{VEHICLE} (Uzduotys)
STR_882A_END_OF_ORDERS :{SETX 10}- - Uzduociu pabaiga- -
STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING}
@@ -2500,6 +2592,7 @@
STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Rodyti detalia vagonu informacija
STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Rodyti detalia vagonu talpos informacija
STR_8852_SHOW_TOTAL_CARGO :{BLACK}Rodyti bendra traukinio talpos informacija pagal kroviniu tipa
+STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Nurodymų sąrašas - nurodymas pažymimas ant jo spragtelėjus. Spregtelėjimas laikant VALD (CTRL) nukelia į stotį
STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Praleisti esama uzduoti, vygdyti sekancia
STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Istrinti pazymeta uzduoti
STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Nestoti pazymetoje stoteleje
@@ -2509,8 +2602,11 @@
STR_SERVICE_HINT :{BLACK}Nevykdyti sios uzduoties iki tol, kol nereikes remonto
STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Naujas {STRING} atsirado!
STR_885A :{BLACK}{BIGFONT}{STRING}
+STR_VEHICLE_INFO_COST_WEIGHT_SPEED_POWER :{BLACK}Kaina: {CURRENCY} Svoris: {WEIGHT_S}{}Greitis: {VELOCITY} Galia: {POWER}{}Eksplotacijos išlaidos: {CURRENCY}/metus{}Talpa: {CARGO}
STR_885C_BROKEN_DOWN :{RED}Sugedo
STR_885D_AGE_RUNNING_COST_YR :{BLACK}Amzius: {LTBLUE}{STRING}{BLACK} Eksploatacijos islaidos: {LTBLUE}{CURRENCY}/met
+STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Svoris: {LTBLUE}{WEIGHT_S} {BLACK}Galia: {LTBLUE}{POWER}{BLACK} Did. greitis: {LTBLUE}{VELOCITY}
+STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Svoris: {LTBLUE}{WEIGHT_S} {BLACK}Galia: {LTBLUE}{POWER}{BLACK} Did. greitis {LTBLUE}{VELOCITY} {BLACK}Did. K.G.: {LTBLUE}{FORCE}
STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Siu metu pelnas : {LTBLUE}{CURRENCY} (praeitu metu: {CURRENCY})
STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Patikimumas: {LTBLUE}{COMMA}% {BLACK}Gedimai nuo praeito remonto: {LTBLUE}{COMMA}
STR_8861_STOPPED :{RED}Sustabdyta
@@ -2524,11 +2620,14 @@
STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Traukinio vaziavimo krypties pakeisti negalima...
STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Pervardinti traukinio tipa
STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Neimanoma pervardinti traukinio tipo...
+STR_886D_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Priversti iškrauti krovinius pažymėta tvarka
STR_886F_TRANSFER :{BLACK}Perkelti
STR_TRAIN_STOPPING :{RED}Stabdoma
STR_TRAIN_STOPPING_VEL :{RED}Stabdomas, {VELOCITY}
STR_INCOMPATIBLE_RAIL_TYPES :Nesuderinami begiai
+STR_TRAIN_NO_POWER :{RED}Nėra energijos
+STR_TRAIN_START_NO_CATENARY :Šiuose bėgiuose trūkta grandies, taigi traukiniai negali judėti
##id 0x9000
STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Automobilis kelyje
@@ -2594,6 +2693,7 @@
STR_REFIT_ROAD_VEHICLE :{BLACK}Perkomplektuoti
STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED :{BLACK}Perkomplektuoti transporto priemone kad galetu vezti pazymeta krovinio tipa
STR_REFIT_ROAD_VEHICLE_CAN_T :{WHITE}Neimanoma perkomplektuoti...
+STR_ROAD_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Nurodykite šios transporto priemonės pervežamą krovinių tipą
##id 0x9800
STR_9800_DOCK_CONSTRUCTION :Doku konstrukcija
@@ -2604,7 +2704,9 @@
STR_9805_SHIPS :{WHITE}{COMPANY} - {COMMA} Laivai
STR_9808_NEW_SHIPS :{WHITE}Nauji laivai
STR_9809_BUILD_SHIP :{BLACK}Nupirkti Laiva
-STR_CLONE_SHIP :{BLACK}Klonuoti Laiva
+STR_CLONE_SHIP :{BLACK}Kopijuoti laivą
+STR_CLONE_SHIP_INFO :{BLACK}Tai pagamins laivo kopiją. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
+STR_CLONE_SHIP_DEPOT_INFO :{BLACK}Tai pagamins laivo kopiją. Spragtelkite šį mygtuką, o tada traukinį esantį depe arba už jo ribų. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Laivas turi buti sustabdytas garaze
STR_980C_CAN_T_SELL_SHIP :{WHITE}Laivo parduoti negalima...
STR_980D_CAN_T_BUILD_SHIP :{WHITE}Laivo isigyti negalima...
@@ -2664,15 +2766,16 @@
STR_9841_CAN_T_REFIT_SHIP :{WHITE}Negalima perorientuotilaivo...
STR_9842_REFITTABLE :(perorientuotinas)
STR_GO_TO_SHIP_DEPOT :Uzduotis: laivu depas {TOWN}
-SERVICE_AT_SHIP_DEPOT :Remontas laivu depe {TOWN}
+SERVICE_AT_SHIP_DEPOT :Remontas {TOWN} miesto laivų depe
##id 0xA000
STR_A000_AIRPORTS :{WHITE}Oro uostai
STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Negalima cia statyti oro uosto...
STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Lektuvu angaras
STR_A003_NEW_AIRCRAFT :{BLACK}Naujas lektuvas
-STR_CLONE_AIRCRAFT :{BLACK}Klonuoti lektuva
-STR_CLONE_AIRCRAFT_INFO :{BLACK}Tai pagamins lektuvo kopija ir nustatys marsrutus.
+STR_CLONE_AIRCRAFT :{BLACK}Kopijuoti lėktuvą
+STR_CLONE_AIRCRAFT_INFO :{BLACK}Tai pagamins lėktuvo kopiją. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
+STR_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}Tai pagamins lėktuvo kopiją. Spragtelkite šį mygtuką, o tada traukinį esantį angare arba už jo ribų. Spragtelėjus laikant VALD (CTRL) nukopijuojami nurodymai
STR_A005_NEW_AIRCRAFT :{WHITE}Naujas lektuvas
STR_A006_BUILD_AIRCRAFT :{BLACK}Isigyti lektuva
STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Negalima isigyti lektuvo...
@@ -2737,13 +2840,13 @@
STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nauja talpa: {GOLD}{STRING}{}{BLACK}Pakeitimo kaina: {GOLD}{CURRENCY}
STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Negalima pakeisti krovinio tipo...
STR_GO_TO_AIRPORT_HANGAR :Kursas: {STATION} angaras
-SERVICE_AT_AIRPORT_HANGAR :Remontas angare: {STATION}
+SERVICE_AT_AIRPORT_HANGAR :Remontas {STATION} angare
##id 0xB000
STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT} Dirizablio katastrofa {STATION}!
STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Automobilis sunaikintas ateiviu!
STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Naftos perdirbimo fabriko sprogimas salia {TOWN}!
-STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS :{BLACK}{BIGFONT} Del neaiskiu aplinkybiu sunaikinta ferma salia {TOWN}!
+STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS :{BLACK}{BIGFONT} Įtartinomis aplinkybėmis sunaikintas ūkis, esantis prie {TOWN}!
STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}Ateiviai nusileido salia {TOWN}!
STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Anglies kasyklose salia {TOWN} sedantis gruntas sukele katastrofa - kasykla nenaudojama!
STR_B006_FLOOD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Potvynis!{}Automobilio {COMMA} buvo pasigesta, kaip spejama, tai susije su potvyniu!
@@ -2781,6 +2884,7 @@
STR_PERFORMANCE_DETAIL_LOAN_TIP :{BLACK}Kompanijos pasiskolintu pinigu kiekis
STR_PERFORMANCE_DETAIL_TOTAL_TIP :{BLACK}Viso tasku (is visu galimu)
+STR_NEWGRF_SETTINGS_BUTTON :{BLACK}NewGRF Nustatymai
STR_NEWGRF_SETTINGS_CAPTION :{WHITE}Newgrf settings
STR_NEWGRF_APPLY_CHANGES :{BLACK}Pakeitimai isigalioja
STR_NEWGRF_SET_PARAMETERS :{BLACK}Nustatyti parametrus
@@ -2788,9 +2892,31 @@
STR_NEWGRF_NO_FILES_INSTALLED :{BLACK}Nera instaliuota NewGRF failu! Prasau skaityti vartotojo vadove apie tai, kaip instaliuoti naujus grafinus elementus (NewGRF)
STR_NEWGRF_FILENAME :{BLACK}Failo vardas: {SILVER}{STRING}
STR_NEWGRF_GRF_ID :{BLACK}GRF ID: {SILVER}{STRING}
+STR_NEWGRF_MD5SUM :{BLACK}MD5suma: {SILVER}{STRING}
+STR_NEWGRF_CONFIRMATION_TEXT :{YELLOW}Jūs norite atlikti pakeitimus veikiančiam žaidimui: OpenTTD gali pakibti.{}Ar jūs tikrai norite tai atlikti?
+STR_NEWGRF_ADD :{BLACK}Pridėti
+STR_NEWGRF_ADD_TIP :{BLACK}Pridėti NewGRF failą į sąrašą
+STR_NEWGRF_REMOVE :{BLACK}Pašalinti
+STR_NEWGRF_REMOVE_TIP :{BLACK}Pašalinti pažymėtą NewGRF filą iš sąrašo
+STR_NEWGRF_MOVEUP :{BLACK}Perkelti aukštyn
+STR_NEWGRF_MOVEUP_TIP :{BLACK}Perkelti pažymėtus NewGRF failus sąraše aukštyn
+STR_NEWGRF_MOVEDOWN :{BLACK}Perkelti žemyn
+STR_NEWGRF_MOVEDOWN_TIP :{BLACK}Perkelti pažymėtus NewGRF failus sąraše žemyn
+STR_NEWGRF_FILE_TIP :{BLACK}Įdiegtų NewGRF filų sąrašas. Sragtelėjus failą galima keisti jo parametrus
+STR_NEWGRF_PARAMETER :{BLACK}Parametrai: {SILVER}{STRING}
+STR_NEWGRF_PARAMETER_QUERY :{BLACK}Įveskite NewGRF parametrus
+STR_NEWGRF_NO_INFO :{BLACK}Informacija neprieinama
+STR_NEWGRF_ADD_CAPTION :{WHITE}Prieinami NewGRF filai
+STR_NEWGRF_ADD_FILE :{BLACK}Pridėti prie pažymėjimo
+STR_NEWGRF_ADD_FILE_TIP :{BLACK}Įtraukti pažymėtus NewGRF failus į jūsų nustatymus
+STR_NEWGRF_RESCAN_FILES :{BLACK}Atnaujinti sąrašą
+STR_NEWGRF_RESCAN_FILES_TIP :{BLACK}Atnaujinti prieinamų NewGRF filų sąrašą
+STR_NEWGRF_DUPLICATE_GRFID :{WHITE}Negalima pridėti failo: pasikartojantis GRF ID
+STR_NEWGRF_NOT_FOUND :{RED}Atitinkamas failas nerastas
+STR_NEWGRF_DISABLED :{RED}Uždrausta
STR_CURRENCY_WINDOW :{WHITE}Pasirinkti valiuta
STR_CURRENCY_EXCHANGE_RATE :{LTBLUE}Keitimo santykis: {ORANGE}{CURRENCY} = £ {COMMA}
@@ -2818,20 +2944,35 @@
STR_SCHEDULED_AIRCRAFT_TIP :{BLACK}Rodyti visus lektuvus, kuriu uzduotyse yra pamineta si stotele
STR_SCHEDULED_SHIPS_TIP :{BLACK}Rodyti visus laivus, kuriu uzduotyse yra pamineta si stotele
+STR_VEH_WITH_SHARED_ORDERS_LIST :{WHITE}Nurodymais dalijasi {COMMA} tr. priemon{P ė ės ių}
+STR_VEH_WITH_SHARED_ORDERS_LIST_TIP :{BLACK}Parodyti visas tr. priemones, kurios dalijasi šiais nurodymais
### depot strings
-
-STR_SELL :{BLACK}Parduoti
-
+STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}Ar tikrai norite parduoti visas tr. priemones esančias šiame depe?
-
+STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TIP :{BLACK}Parduoti visus traukinius šiame depe
+STR_DEPOT_SELL_ALL_BUTTON_ROADVEH_TIP :{BLACK}Parduoti visus automobilius šiame depe
+STR_DEPOT_SELL_ALL_BUTTON_SHIP_TIP :{BLACK}Parduoti visus laivus šiame depe
+STR_DEPOT_SELL_ALL_BUTTON_AIRCRAFT_TIP :{BLACK}Parduoti visus lėktuvus šiame angare
+STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TIP :{BLACK}Gauti sąrašą visų traukinių turiunčių nurodymuose šį depą
+STR_DEPOT_VEHICLE_ORDER_LIST_ROADVEH_TIP :{BLACK}Gauti sąrašą visų automobilių turiunčių nurodymuose šį depą
+STR_DEPOT_VEHICLE_ORDER_LIST_SHIP_TIP :{BLACK}Gauti sąrašą visų laivų turiunčių nurodymuose šį depą
+STR_DEPOT_VEHICLE_ORDER_LIST_AIRCRAFT_TIP :{BLACK}Gauti sąrašą visų lėktuvų turiunčių nurodymuose šį angarą
+STR_DEPOT_AUTOREPLACE_TRAIN_TIP :{BLACK}Pakeisti visus traukinius depe
+STR_DEPOT_AUTOREPLACE_ROADVEH_TIP :{BLACK}Pakeisti automobilius traukinius depe
+STR_DEPOT_AUTOREPLACE_SHIP_TIP :{BLACK}Pakeisti visus laivus depe
+STR_DEPOT_AUTOREPLACE_AIRCRAFT_TIP :{BLACK}Pakeisti visus lėktuvus angare
+STR_VEHICLE_LIST_TRAIN_DEPOT :{BLACK}{STRING} - {COMMA} traukin{P ys iai ių}
+STR_VEHICLE_LIST_ROADVEH_DEPOT :{BLACK}{STRING} - {COMMA} automobil{P is iai ių}
+STR_VEHICLE_LIST_SHIP_DEPOT :{BLACK}{STRING} - {COMMA} laiv{P as ai ų}
+STR_VEHICLE_LIST_AIRCRAFT_DEPOT :{BLACK}{STRING} - {COMMA} lėktuv{P as ai ų}
STR_REPLACE_VEHICLES_WHITE :{WHITE}Keisti tr. priemones {STRING}
-STR_REPLACE_VEHICLES_START :{BLACK}Pradeti keitima
-STR_REPLACE_VEHICLES_STOP :{BLACK}Sustabdyti keitima
+STR_REPLACE_VEHICLES_START :{BLACK}Pradeti tr. priemonių keitimą
+STR_REPLACE_VEHICLES_STOP :{BLACK}Stabdyti tr. priemonių keitimą
STR_NOT_REPLACING :{BLACK}Nekeiciama
STR_NOT_REPLACING_VEHICLE_SELECTED :{BLACK}Nera pazymeta nei viena tr. priemone
STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}Pasirink tr. priemones tipa, kuriuo reikes keisti
@@ -2842,12 +2983,23 @@
STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Kaireje lango dalyje pazymeta tr. priemone bus pakeista tr. priemone, kuri yra pazymeta desineje lango puseje
STR_REPLACE_HELP :{BLACK}Tai leidzia tau keisti viena tr. priemoniu tipa kitu, kai pirmojo tipo traukinys uzsuka i depa
STR_REPLACE_REMOVE_WAGON :{BLACK}Vagono pasalinimas: {ORANGE}{SKIP}{STRING}
+STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Pakeitimo metu išlaikyti traukinio ilgį atjungiant vagonus (pradedant juo priekio), jeigu pakeitus garvežį traukinys pailgėtų.
STR_REPLACE_ENGINE_WAGON_SELECT :{BLACK}Keicima: {ORANGE}{SKIP}{SKIP}{STRING}
+STR_REPLACE_ENGINE_WAGON_SELECT_HELP :{BLACK} EKSPERIMENTINĖ GALIMYBĖ {}Pereidinėti tarp garvežių ir vagonų pakeitimo langų.{}Vagonai bus pakeičiami tik tada, jeigu naujasis vagonas galės gabenti tą patį krovinio tipą kaip ir senasis. Tai atliekama patikrinant kiekvieną vagoną jo keitimo metu.
STR_ENGINE_NOT_BUILDABLE :{WHITE}Variklio neimanoma pagaminti
STR_ENGINES :Varikliai
+STR_WAGONS :Vagonai
+STR_MASS_STOP_DEPOT_TRAIN_TIP :{BLACK}Spragtelėkite norėdami sustabdyti visus traukinius esančius depe
+STR_MASS_STOP_DEPOT_ROADVEH_TIP :{BLACK}Spragtelėkite norėdami sustabdyti visus automobilius esančius depe
+STR_MASS_STOP_DEPOT_SHIP_TIP :{BLACK}Spragtelėkite norėdami sustabdyti visus laivus esančius depe
+STR_MASS_STOP_HANGAR_TIP :{BLACK}Spragtelėkite norėdami sustabdyti visus lėktuvus esančius angare
+STR_MASS_START_DEPOT_TRAIN_TIP :{BLACK}Spragtelėkite norėdami paleisti visus traukinius esančius depe
+STR_MASS_START_DEPOT_ROADVEH_TIP :{BLACK}Spragtelėkite norėdami paleisti visus automobilius esančius depe
+STR_MASS_START_DEPOT_SHIP_TIP :{BLACK}Spragtelėkite norėdami paleisti visus laivus esančius depe
+STR_MASS_START_HANGAR_TIP :{BLACK}Spragtelėkite norėdami paleisti visus lėktuvus esančius angare
STR_MASS_STOP_LIST_TIP :{BLACK}Paspauskite noredami sustabdyti automobilius is saraso
STR_MASS_START_LIST_TIP :{BLACK}Paspauskite noredami paleisti automobilius is saraso
@@ -2855,6 +3007,7 @@
STR_SHORT_DATE :{WHITE}{DATE_TINY}
STR_SIGN_LIST_CAPTION :{WHITE}Zenklu sarasas - {COMMA} Zenklai
+STR_ORDER_REFIT_FAILED :{WHITE}Klaida pakeitimo metu {STRING} {COMMA}
############ Lists rail types
@@ -2879,16 +3032,23 @@
STR_PURCHASE_INFO_COST_SPEED :{BLACK}Kaina: {GOLD}{CURRENCY}{BLACK} Greitis: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_AIRCRAFT_CAPACITY :{BLACK}Talpa: {GOLD}{COMMA} keleiviu, {COMMA} pasto maisu
STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Pajungta vagonu: {GOLD}+{POWER}{BLACK} Svoris: {GOLD}+{WEIGHT_S}
+STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Pakeičiami į: {GOLD}
+STR_PURCHASE_INFO_ALL_TYPES :Visus krovinių tipus
+STR_PURCHASE_INFO_ALL_BUT :Visus, išskyrus {GOLD}
+STR_PURCHASE_INFO_MAX_TE :{BLACK}Did. traukiamoji galia: {GOLD}{FORCE}
########### String for New Landscape Generator
STR_GENERATE :{WHITE}Generuoti
STR_RANDOM :{BLACK}Bet kaip
STR_RANDOM_HELP :{BLACK}Pakeisti i bet koki Pasaulio Generavima
+STR_WORLD_GENERATION_CAPTION :{WHITE}Pasaulio kūrimas
STR_RANDOM_SEED :{BLACK}Bet koks:
STR_RANDOM_SEED_HELP :{BLACK}Paspauskite noredami ivesti bet koki seed
STR_LAND_GENERATOR :{BLACK}Pasaulio generatorius:
+STR_TREE_PLACER :{BLACK}Medžių algoritmas:
STR_HEIGHTMAP_ROTATION :{BLACK}Zemelapio rotacija:
+STR_TERRAIN_TYPE :{BLACK}Vietovės tipas:
STR_QUANTITY_OF_SEA_LAKES :{BLACK}Juros lygis:
STR_SMOOTHNESS :{BLACK}Jautrumas:
STR_SNOW_LINE_HEIGHT :{BLACK}Sniego linijos aukstis:
@@ -2928,13 +3088,16 @@
STR_FLAT_WORLD_HEIGHT_UP :{BLACK}Pakelti lygios zemes lygi vienu lygiu
STR_FLAT_WORLD_HEIGHT_QUERY_CAPT :{WHITE}Keisti lygumos auksti
STR_FLAT_WORLD_HEIGHT :{BLACK}Lygumos aukstis:
+STR_FLAT_WORLD_HEIGHT_NUM :{NUM}
STR_SMALLMAP_CENTER :{BLACK}Centruoti maza zemelapi i sita vieta
########### String for new airports
STR_SMALL_AIRPORT :{BLACK}Mazas
+STR_CITY_AIRPORT :{BLACK}Miestas
STR_METRO_AIRPORT :{BLACK}Metropoliteno orouostas
STR_INTERNATIONAL_AIRPORT :{BLACK}Internacionalinis orouostas
+STR_COMMUTER_AIRPORT :{BLACK}Rajonas
STR_INTERCONTINENTAL_AIRPORT :{BLACK}Tarpkontinentinis
STR_HELIPORT :{BLACK}Heliportas
STR_HELIDEPOT :{BLACK}Helidepas
@@ -2947,5 +3110,9 @@
############ Tooltip measurment
+STR_MEASURE_LENGTH :{BLACK}Atstumas: {NUM}
+STR_MEASURE_AREA :{BLACK}Sritis: {NUM} x {NUM}
+STR_MEASURE_LENGTH_HEIGHTDIFF :{BLACK}Atstumas: {NUM}{}Aukščių skirtumas: {NUM} m
+STR_MEASURE_AREA_HEIGHTDIFF :{BLACK}Sritis: {NUM} x {NUM}{}Aukščių skirtumas: {NUM} m
########
--- a/lang/unfinished/slovenian.txt Tue Jan 02 18:40:37 2007 +0000
+++ b/lang/unfinished/slovenian.txt Wed Jan 03 08:32:17 2007 +0000
@@ -21,16 +21,16 @@
STR_000E :
STR_000F_PASSENGERS :Potniki
STR_0010_COAL :Premog
-STR_0011_MAIL :Posta
+STR_0011_MAIL :Pošta
STR_0012_OIL :Nafta
-STR_0013_LIVESTOCK :Zivina
+STR_0013_LIVESTOCK :Živina
STR_0014_GOODS :Dobrine
-STR_0015_GRAIN :Zito
+STR_0015_GRAIN :Žito
STR_0016_WOOD :Les
-STR_0017_IRON_ORE :Zelezova ruda
+STR_0017_IRON_ORE :Železova ruda
STR_0018_STEEL :Jeklo
STR_0019_VALUABLES :Dragocenosti
-STR_001A_COPPER_ORE :Bakrena ruda
+STR_001A_COPPER_ORE :Bakrova ruda
STR_001B_MAIZE :Koruza
STR_001C_FRUIT :Sadje
STR_001D_DIAMONDS :Diamanti
@@ -38,31 +38,31 @@
STR_001F_PAPER :Papir
STR_0020_GOLD :Zlato
STR_0021_WATER :Voda
-STR_0022_WHEAT :Psenica
+STR_0022_WHEAT :Pšenica
STR_0023_RUBBER :Guma
STR_0024_SUGAR :Sladkor
-STR_0025_TOYS :Igrace
+STR_0025_TOYS :Igrače
STR_0026_CANDY :Bonboni
STR_0027_COLA :Cockta
STR_0028_COTTON_CANDY :Sladkorna pena
-STR_0029_BUBBLES :Mehurcki
-STR_002A_TOFFEE :Karamele
+STR_0029_BUBBLES :Mehurčki
+STR_002A_TOFFEE :Karamela
STR_002B_BATTERIES :Baterije
STR_002C_PLASTIC :Plastika
-STR_002D_FIZZY_DRINKS :Gazirane pijace
+STR_002D_FIZZY_DRINKS :Gazirane pijače
STR_002E :
STR_002F_PASSENGER :Potnik
STR_0030_COAL :Premog
-STR_0031_MAIL :Posta
+STR_0031_MAIL :Pošta
STR_0032_OIL :Nafta
-STR_0033_LIVESTOCK :Zivina
-STR_0034_GOODS :Izdelki
-STR_0035_GRAIN :Zito
+STR_0033_LIVESTOCK :Živina
+STR_0034_GOODS :Dobrine
+STR_0035_GRAIN :Žito
STR_0036_WOOD :Les
-STR_0037_IRON_ORE :Zelezova ruda
+STR_0037_IRON_ORE :Železova ruda
STR_0038_STEEL :Jeklo
STR_0039_VALUABLES :Dragocenosti
-STR_003A_COPPER_ORE :Bakrena ruda
+STR_003A_COPPER_ORE :Bakrova ruda
STR_003B_MAIZE :Koruza
STR_003C_FRUIT :Sadje
STR_003D_DIAMOND :Diamanti
@@ -70,18 +70,18 @@
STR_003F_PAPER :Papir
STR_0040_GOLD :Zlato
STR_0041_WATER :Voda
-STR_0042_WHEAT :psenica
+STR_0042_WHEAT :Pšenica
STR_0043_RUBBER :Guma
STR_0044_SUGAR :Sladkor
-STR_0045_TOY :Igrace
+STR_0045_TOY :Igrače
STR_0046_CANDY :Bombon
STR_0047_COLA :Cockta
STR_0048_COTTON_CANDY :Sladkorna pena
-STR_0049_BUBBLE :Mehurcki
+STR_0049_BUBBLE :Mehurčki
STR_004A_TOFFEE :Karamela
STR_004B_BATTERY :Baterija
STR_004C_PLASTIC :Plastika
-STR_004D_FIZZY_DRINK :Gazirana pijaca
+STR_004D_FIZZY_DRINK :Gazirana pijača
STR_QUANTITY_NOTHING :
STR_QUANTITY_PASSENGERS :{COMMA} potnikov
STR_QUANTITY_COAL :{WEIGHT} ton premoga
@@ -90,6 +90,7 @@
STR_QUANTITY_LIVESTOCK :{COMMA} glav zivine
STR_QUANTITY_GOODS :{COMMA} paketov dobrin
STR_QUANTITY_GRAIN :{WEIGHT} ton zita
+STR_QUANTITY_WOOD :{WEIGHT} lesa
STR_QUANTITY_IRON_ORE :{WEIGHT} ton zelezove rude
STR_QUANTITY_STEEL :{WEIGHT} ton jekla
STR_QUANTITY_VALUABLES :{COMMA} vrec dragocenosti
@@ -119,17 +120,17 @@
STR_ABBREV_MAIL :{TINYFONT}PS
STR_ABBREV_OIL :{TINYFONT}NF
STR_ABBREV_LIVESTOCK :{TINYFONT}ZV
-STR_ABBREV_GOODS :{TINYFONT}TO
+STR_ABBREV_GOODS :{TINYFONT}DO
STR_ABBREV_GRAIN :{TINYFONT}ZT
STR_ABBREV_WOOD :{TINYFONT}LS
-STR_ABBREV_IRON_ORE :{TINYFONT}ZZ
+STR_ABBREV_IRON_ORE :{TINYFONT}ZR
STR_ABBREV_STEEL :{TINYFONT}JK
STR_ABBREV_VALUABLES :{TINYFONT}DR
STR_ABBREV_COPPER_ORE :{TINYFONT}BK
STR_ABBREV_MAIZE :{TINYFONT}KZ
STR_ABBREV_FRUIT :{TINYFONT}SJ
STR_ABBREV_DIAMONDS :{TINYFONT}DM
-STR_ABBREV_FOOD :{TINYFONT}HR
+STR_ABBREV_FOOD :{TINYFONT}ZI
STR_ABBREV_PAPER :{TINYFONT}PR
STR_ABBREV_GOLD :{TINYFONT}ZL
STR_ABBREV_WATER :{TINYFONT}VO
@@ -137,25 +138,28 @@
STR_ABBREV_RUBBER :{TINYFONT}GU
STR_ABBREV_SUGAR :{TINYFONT}SK
STR_ABBREV_TOYS :{TINYFONT}IG
-STR_ABBREV_SWEETS :{TINYFONT}BB
-STR_ABBREV_COLA :{TINYFONT}CL
+STR_ABBREV_SWEETS :{TINYFONT}SL
+STR_ABBREV_COLA :{TINYFONT}CK
STR_ABBREV_CANDYFLOSS :{TINYFONT}SP
-STR_ABBREV_BUBBLES :{TINYFONT}BL
-STR_ABBREV_TOFFEE :{TINYFONT}KA
+STR_ABBREV_BUBBLES :{TINYFONT}MH
+STR_ABBREV_TOFFEE :{TINYFONT}TF
STR_ABBREV_BATTERIES :{TINYFONT}BA
STR_ABBREV_PLASTIC :{TINYFONT}PL
STR_ABBREV_FIZZY_DRINKS :{TINYFONT}GP
+STR_ABBREV_NONE :{TINYFONT}NO
+STR_ABBREV_ALL :{TINYFONT}VSE
STR_00AE :{WHITE}{DATE_SHORT}
STR_00AF :{WHITE}{DATE_LONG}
-STR_00B0_MAP :{WHITE}Mapa - {STRING}
-STR_00B1_GAME_OPTIONS :{WHITE}Moznosti Igre
-STR_00B2_MESSAGE :{YELLOW}Sporocilo
-STR_00B3_MESSAGE_FROM :{YELLOW}Sporocilo od {STRING}
-STR_00B4_CAN_T_DO_THIS :{WHITE}Ne mores narediti tega...
-STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Ne mores ocistit tega podrocje...
-STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Prvotne avtorske pravice {COPYRIGHT} 1995 Chris Sawyer, Vse pravice pridrzane
-STR_00B7_VERSION :{BLACK}OpenTTD verzija {REV}
-STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2005 OpenTTD ekipa
+STR_00B0_MAP :{WHITE}Zemljevid - {STRING}
+STR_00B1_GAME_OPTIONS :{WHITE}Možnosti Igre
+STR_00B2_MESSAGE :{YELLOW}Sporočilo
+STR_00B3_MESSAGE_FROM :{YELLOW}Sporočilo od {STRING}
+STR_POPUP_CAUTION_CAPTION :{WHITE}Pozor!
+STR_00B4_CAN_T_DO_THIS :{WHITE}Ne morem narediti tega ...
+STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Ne morem očistiti tega področja ...
+STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Prvotne avtorske pravice {COPYRIGHT} 1995 Chris Sawyer, Vse pravice pridržane
+STR_00B7_VERSION :{BLACK}OpenTTD različica {REV}
+STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2006 ekipa OpenTTD
STR_TRANSLATED_BY :{BLACK} Prevod - seba
STR_00C5 :{BLACK}{CROSS}
@@ -163,42 +167,42 @@
STR_00C7_QUIT :{WHITE}Izhod
STR_00C8_YES :{BLACK}Da
STR_00C9_NO :{BLACK}Ne
-STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Ali ste prepricani, da zelite zapustiti to igro in se vrniti v {STRING}?
+STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Ali ste prepričani, da želite zapustiti igro in se vrniti v {STRING}?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
STR_00CE_4 :{BLACK}4
STR_00CF_5 :{BLACK}5
-STR_00D0_NOTHING :Nic
+STR_00D0_NOTHING :Nič
STR_00D1_DARK_BLUE :Temno modra
STR_00D2_PALE_GREEN :Svetlo zelena
-STR_00D3_PINK :Roza
+STR_00D3_PINK :Rožnata
STR_00D4_YELLOW :Rumena
-STR_00D5_RED :Rdeca
+STR_00D5_RED :Rdeča
STR_00D6_LIGHT_BLUE :Svetlo modra
STR_00D7_GREEN :Zelena
STR_00D8_DARK_GREEN :Temno zelena
STR_00D9_BLUE :Modra
STR_00DA_CREAM :Kremna
STR_00DB_MAUVE :Slezenasta
-STR_00DC_PURPLE :Vijola
-STR_00DD_ORANGE :Oranzna
+STR_00DC_PURPLE :Vijolična
+STR_00DD_ORANGE :Oranžna
STR_00DE_BROWN :Rjava
STR_00DF_GREY :Siva
STR_00E0_WHITE :Bela
-STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Prevec vozil v igri
+STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Preveč vozil v igri
STR_00E2 :{BLACK}{COMMA}
STR_00E3 :{RED}{COMMA}
STR_00E4_LOCATION :{BLACK}Lokacija
-STR_00E5_CONTOURS :Nacrt
+STR_00E5_CONTOURS :Načrt
STR_00E6_VEHICLES :Vozila
STR_00E7_INDUSTRIES :Industrije
STR_00E8_ROUTES :Poti
STR_00E9_VEGETATION :Vegetacija
STR_00EA_OWNERS :Lastniki
STR_00EB_ROADS :{BLACK}{TINYFONT}Ceste
-STR_00EC_RAILROADS :{BLACK}{TINYFONT}Zeleznice
-STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Postaje/Letalisca/Pristanisca
+STR_00EC_RAILROADS :{BLACK}{TINYFONT}Železnice
+STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Postaje/Letališča/Pristanišča
STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Stavbe/Industrije
STR_00EF_VEHICLES :{BLACK}{TINYFONT}Vozila
STR_00F0_100M :{BLACK}{TINYFONT}100m
@@ -214,42 +218,42 @@
STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Rudnik premoga
STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Termoelektrarna
STR_00FC_FOREST :{BLACK}{TINYFONT}Gozd
-STR_00FD_SAWMILL :{BLACK}{TINYFONT}Zaga
+STR_00FD_SAWMILL :{BLACK}{TINYFONT}Žaga
STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Naftna rafinerija
STR_00FF_FARM :{BLACK}{TINYFONT}Kmetija
STR_0100_FACTORY :{BLACK}{TINYFONT}Tovarna
STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Tiskarna
-STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Naftni izvir
-STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Rudnik zeleza
+STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Naftno polje
+STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Rudnik železa
STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Jeklarna
STR_0105_BANK :{BLACK}{TINYFONT}Banka
STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Papirnica
STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Rudnik zlata
-STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Zivilska tovarna
+STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Predelava hrane
STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Rudnik diamantov
STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Rudnik bakra
STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Sadovnjak
-STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Plantaza gume
+STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Plantaža gume
STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Vodni izvir
STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vodni stolp
-STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Zaga
+STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Žaga
STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Gozd sladkorne pene
-STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Tovarna slascic
+STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Tovarna slaščic
STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Farma baterij
-STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Izvir cockte
-STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Trgovina z igracami
-STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Tovarna igrac
+STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Izvir Cockte
+STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Trgovina z igračami
+STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Tovarna igrač
STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Vodnjaki plastike
-STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Tovarna gaziranih pijac
-STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Generator balonckov
+STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Tovarna gaziranih pijač
+STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Generator balončkov
STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Jama karamele
STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Rudnik sladkorja
-STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Zelezniska postaja
-STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Distribucijsko obmocje za tovornjake
+STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Železniška postaja
+STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Distribucijsko območje za tovornjake
STR_011D_BUS_STATION :{BLACK}{TINYFONT}Avtobusna postaja
-STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Letalisce/Heliport
-STR_011F_DOCK :{BLACK}{TINYFONT}Pristanisce
-STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Neravna tla
+STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Letališče/Heliport
+STR_011F_DOCK :{BLACK}{TINYFONT}Pristanišče
+STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Groba tla
STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Travnata tla
STR_0122_BARE_LAND :{BLACK}{TINYFONT}Gola tla
STR_0123_FIELDS :{BLACK}{TINYFONT}Polja
@@ -259,15 +263,15 @@
STR_0127_NO_OWNER :{BLACK}{TINYFONT}Brez lastnika
STR_0128_TOWNS :{BLACK}{TINYFONT}Mesta
STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrije
-STR_012A_DESERT :{BLACK}{TINYFONT}Puscava
+STR_012A_DESERT :{BLACK}{TINYFONT}Puščava
STR_012B_SNOW :{BLACK}{TINYFONT}Sneg
-STR_012C_MESSAGE :{WHITE}Sporocilo
+STR_012C_MESSAGE :{WHITE}Sporočilo
STR_012D :{WHITE}{STRING}
-STR_012E_CANCEL :{BLACK}Preklici
+STR_012E_CANCEL :{BLACK}Prekliči
STR_012F_OK :{BLACK}Potrdi
STR_0130_RENAME :{BLACK}Preimenuj
-STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Prevec definiranih imen
-STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Izbrano ime je ze v uporabi
+STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Preveč definiranih imen
+STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Izbrano ime je že v uporabi
STR_0133_WINDOWS :Windows
STR_0134_UNIX :Unix
@@ -277,16 +281,18 @@
STR_OSNAME_AMIGAOS :AmigaOS
STR_OSNAME_OS2 :OS/2
-STR_013B_OWNED_BY :{WHITE}...pripada {STRING}
+STR_013B_OWNED_BY :{WHITE} ... pripada {STRING}
STR_013C_CARGO :{BLACK}Tovor
STR_013D_INFORMATION :{BLACK}Informacije
-STR_013E_CAPACITIES :{BLACK}Sposobnost
+STR_013E_CAPACITIES :{BLACK}Kapacitete
STR_013E_TOTAL_CARGO :{BLACK}Skupni tovor
-STR_013F_CAPACITY :{BLACK}Sposobnost: {LTBLUE}{CARGO}
-STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Skupna tovorna sposobnost tega vlaka:
+STR_013F_CAPACITY :{BLACK}Kapaciteta: {LTBLUE}{CARGO}
+STR_CAPACITY_MULT :{BLACK}Kapaciteta: {LTBLUE}{CARGO} (x{NUM})
+STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Skupna tovorna kapaciteta tega vlaka:
STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO})
+STR_TOTAL_CAPACITY_MULT :{LTBLUE}- {CARGO} ({SHORTCARGO}) (x{NUM})
STR_0140_NEW_GAME :{BLACK}Nova igra
-STR_0141_LOAD_GAME :{BLACK}Nalozi igro
+STR_0141_LOAD_GAME :{BLACK}Naloži igro
STR_SINGLE_PLAYER :{BLACK}En igralec
STR_MULTIPLAYER :{BLACK}Vec igralcev
@@ -298,10 +304,10 @@
STR_2048 :2048
STR_MAPSIZE :{BLACK}Velikost mape:
STR_BY :{BLACK}*
-STR_0148_GAME_OPTIONS :{BLACK}Moznosti
+STR_0148_GAME_OPTIONS :{BLACK}Možnosti
STR_0150_SOMEONE :nekdo{SKIP}{SKIP}
-STR_0151_MAP_OF_WORLD :Mapa sveta
+STR_0151_MAP_OF_WORLD :Zemljevid sveta
STR_0152_TOWN_DIRECTORY :Imenik mest
STR_0153_SUBSIDIES :Subvencije
@@ -321,36 +327,39 @@
STR_UNITS_WEIGHT_SHORT_METRIC :{COMMA}t
STR_UNITS_WEIGHT_SHORT_SI :{COMMA}kg
-STR_UNITS_WEIGHT_LONG_IMPERIAL :{COMMA} ton{P "" s}
-STR_UNITS_WEIGHT_LONG_METRIC :{COMMA} ton{P "" s}
+STR_UNITS_WEIGHT_LONG_IMPERIAL :{COMMA} ton
+STR_UNITS_WEIGHT_LONG_METRIC :{COMMA} ton
STR_UNITS_WEIGHT_LONG_SI :{COMMA} kg
STR_UNITS_VOLUME_SHORT_IMPERIAL :{COMMA}gal
STR_UNITS_VOLUME_SHORT_METRIC :{COMMA}l
STR_UNITS_VOLUME_SHORT_SI :{COMMA}m³
-STR_UNITS_VOLUME_LONG_IMPERIAL :{COMMA} galon{P "" s}
-STR_UNITS_VOLUME_LONG_METRIC :{COMMA} litrov{P "" s}
+STR_UNITS_VOLUME_LONG_IMPERIAL :{COMMA} galonov
+STR_UNITS_VOLUME_LONG_METRIC :{COMMA} litrov
STR_UNITS_VOLUME_LONG_SI :{COMMA} m³
+STR_UNITS_FORCE_IMPERIAL :{COMMA}x10³ lbf
+STR_UNITS_FORCE_METRIC :{COMMA} ton sile
+STR_UNITS_FORCE_SI :{COMMA} kN
############ range for menu starts
-STR_0154_OPERATING_PROFIT_GRAPH :Graf dobicka
+STR_0154_OPERATING_PROFIT_GRAPH :Graf dobička
STR_0155_INCOME_GRAPH :Graf prihodkov
STR_0156_DELIVERED_CARGO_GRAPH :Graf dostavljenega tovora
STR_0157_PERFORMANCE_HISTORY_GRAPH :Graf zgodovine dela
STR_0158_COMPANY_VALUE_GRAPH :Graf vrednosti podjetja
-STR_0159_CARGO_PAYMENT_RATES :Graf placila tovora
+STR_0159_CARGO_PAYMENT_RATES :Graf plačila za tovor
STR_015A_COMPANY_LEAGUE_TABLE :Tabela lige podjetij
STR_PERFORMANCE_DETAIL_MENU :Podrobna delavna ocena
############ range for menu ends
STR_015B_OPENTTD :{WHITE}O OpenTTD
STR_015C_SAVE_GAME :Shrani igro
-STR_015D_LOAD_GAME :Nalozi igro
+STR_015D_LOAD_GAME :Naloži igro
STR_015E_QUIT_GAME :Zapusti igro
STR_015F_QUIT :Izhod
-STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Ali ste prepricani, da hocete zapustiti to igro?
+STR_ABANDON_GAME_QUERY :{YELLOW}Ali ste prepričani, da želite zapustiti igro?
STR_0161_QUIT_GAME :{WHITE}Zapusti igro
STR_SORT_ORDER_TIP :{BLACK}Izberi nacin sortiranja (padajoce/narascujoce)
STR_SORT_CRITERIA_TIP :{BLACK}Izberi kriterij za sortiranje
@@ -370,6 +379,22 @@
STR_SORT_BY_RELIABILITY :Zanesljivost
STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE :Skupna sposobnost po tipu tovora
STR_SORT_BY_MAX_SPEED :Najvecja hitrost
+STR_SORT_BY_MODEL :Model
+STR_SORT_BY_VALUE :Vrednost
+STR_SORT_BY_FACILITY :Tip postaje
+STR_SORT_BY_WAITING :Čakanje vrednosti tovora
+STR_SORT_BY_RATING_MAX :Ocene tovora
+STR_ENGINE_SORT_ENGINE_ID :ID motorja (klasično urejanje)
+STR_ENGINE_SORT_COST :Cena
+STR_ENGINE_SORT_POWER :Moč
+STR_ENGINE_SORT_INTRO_DATE :Datum vstopa
+STR_ENGINE_SORT_RUNNING_COST :Stroški obratovanja
+STR_ENGINE_SORT_POWER_VS_RUNNING_COST :Moč/Stroški obratovanja
+STR_ENGINE_SORT_CARGO_CAPACITY :Kapaciteta tovora
+STR_NO_WAITING_CARGO :{BLACK}Noben tovor ne čaka
+STR_SELECT_ALL_FACILITIES :{BLACK}Izberi vse pripomočke
+STR_SELECT_ALL_TYPES :{BLACK}Izberi vse vrste tovora (vključno z nobenega čakanja)
+STR_AVAILABLE_ENGINES_TIP :{BLACK}Prikaži seznam motorjev na voljo za ta tip vozila.
############ range for months starts
STR_0162_JAN :Jan
@@ -391,48 +416,48 @@
STR_0170 :{TINYFONT}{STRING}-
STR_0171_PAUSE_GAME :{BLACK}Pavza
STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Shrani igro, zapusti igro, izhod
-STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikazi seznam postaj podjetja
-STR_0174_DISPLAY_MAP :{BLACK}Prikazi mapo
-STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Prikazi mapo, imenik mest
-STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Prikazi imenik mest
-STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Prikazi financne podatke podjetja
-STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Prikazi splosne podatke podjetja
-STR_0179_DISPLAY_GRAPHS :{BLACK}Prikazi grafe
-STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Prikazi tabelo lige podjetij
-STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikazi seznam vlakov podjetja
-STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikazi seznam cestnih vozil podjetja
-STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikazi seznam ladij podjetja
-STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikazi seznam letal podjetja
-STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Priblizaj pogled
+STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikaži seznam postaj podjetja
+STR_0174_DISPLAY_MAP :{BLACK}Prikaži zemljevid
+STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Prikaži zemljevid, imenik mest
+STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Prikaži imenik mest
+STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Prikaži finančne podatke podjetja
+STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Prikaži splošne podatke podjetja
+STR_0179_DISPLAY_GRAPHS :{BLACK}Prikaži grafe
+STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Prikaži tabelo lige podjetij
+STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikaži seznam vlakov podjetja
+STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikaži seznam cestnih vozil podjetja
+STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikaži seznam ladij podjetja
+STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Prikaži seznam letal podjetja
+STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Približaj pogled
STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Oddalji pogled
-STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Postavi zelezniske tire
+STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Postavi železniške tire
STR_0182_BUILD_ROADS :{BLACK}Zgradi ceste
-STR_0183_BUILD_SHIP_DOCKS :{BLACK}Zgradi pristanisca
-STR_0184_BUILD_AIRPORTS :{BLACK}Zgradi letalisca
+STR_0183_BUILD_SHIP_DOCKS :{BLACK}Zgradi pristanišča
+STR_0184_BUILD_AIRPORTS :{BLACK}Zgradi letališča
STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Posadi drevesa, postavi znake ipd.
STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Informacije o terenu
-STR_0187_OPTIONS :{BLACK}Moznosti
+STR_0187_OPTIONS :{BLACK}Možnosti
STR_0188 :{BLACK}{SMALLUPARROW}
STR_0189 :{BLACK}{SMALLDOWNARROW}
-STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Ne morem spremeniti interval servisiranja...
+STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Ne morem spremeniti intervala servisiranja ...
STR_018B_CLOSE_WINDOW :{BLACK}Zapri okno
-STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Naslov okna - premakni to, da premaknes okno
+STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Naslov okna - primi in vleci, da premakneš okno
STR_STICKY_BUTTON :{BLACK}Oznaci to okno za nezapirljivo z 'Zapri vsa okna' tipko
STR_RESIZE_BUTTON :{BLACK}Klikni in dragaj to, da zmanjsas okno
STR_SAVELOAD_HOME_BUTTON :{BLACK}Klikni tukaj za skok na mapo shrani/naloži
-STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Podri zgradbe itd. na kvadratu zemlje
-STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Znizaj rob teren
-STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Zvisaj rob teren
+STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Podri zgradbe itd. na kvadratku zemlje
+STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Znižaj rob terena
+STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Zvišaj rob terena
STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Drsnik - premakne seznam gor/dol
STR_HSCROLL_BAR_SCROLLS_LIST :{BLACK}Skrol-bar - skrolaj seznam levo/desno
-STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Pokazi nacrt terena na zemljevidu
-STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Pokazi vozila na zemljevidu
-STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Pokazi industrije na zemljevidu
-STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Pokazi transportne poti na zemljevidu
-STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Pokazi vegetacijo na zemljevidu
-STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Pokazi lastnike terena na zemljevidu
-STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Vkljuci/izkljuci imena mest na zemljevidu
-STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Prihodek to leto: {CURRENCY} (prejsnje leto: {CURRENCY})
+STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Pokaži načrt terena na zemljevidu
+STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Pokaži vozila na zemljevidu
+STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Pokaži industrije na zemljevidu
+STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Pokaži transportne poti na zemljevidu
+STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Pokaži vegetacijo na zemljevidu
+STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Pokaži lastnike terena na zemljevidu
+STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Vključi/izključi imena mest na zemljevidu
+STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Prihodki to leto: {CURRENCY} (prejšnje leto: {CURRENCY})
############ range for service numbers starts
STR_AGE :{COMMA} let{P o ""} ({COMMA})
@@ -445,14 +470,14 @@
STR_019F_TRAIN :Vlak
STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA} postaja staro
STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA} postaja zelo staro
-STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} postaja zelo star in nujno rabi zamenjavo
-STR_01A3_LAND_AREA_INFORMATION :{WHITE}Informacije o zemlji
-STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Cena za ocistit: {LTBLUE}N/A
-STR_01A5_COST_TO_CLEAR :{BLACK}Cena za ocistit: {LTBLUE}{CURRENCY}
-STR_01A6_N_A :N/A
+STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA} postaja zelo staro in nujno potrebuje zamenjavo
+STR_01A3_LAND_AREA_INFORMATION :{WHITE}Informacije o zemljišču
+STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Cena za čiščenje: {LTBLUE}N/A
+STR_01A5_COST_TO_CLEAR :{BLACK}Cena za čiščenje: {LTBLUE}{CURRENCY}
+STR_01A6_N_A :Ni na voljo
STR_01A7_OWNER :{BLACK}Lastnik: {LTBLUE}{STRING}
STR_01A8_LOCAL_AUTHORITY :{BLACK}Lokalna oblast: {LTBLUE}{STRING}
-STR_01A9_NONE :Noben
+STR_01A9_NONE :Nihče
STR_01AA_NAME :{BLACK}Ime
STR_01AB :{BLACK}{TINYFONT}{STRING}
@@ -497,7 +522,7 @@
STR_01D1_8 :({COMMA}/8 {STRING})
STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox
STR_01D3_SOUND_MUSIC :Zvok/glasba
-STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Pokaži okno za zvok/glasbo
+STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Prikaži okno za zvok/glasbo
STR_01D5_ALL :{TINYFONT}Vsi
STR_01D6_OLD_STYLE :{TINYFONT}Star stil
STR_01D7_NEW_STYLE :{TINYFONT}Novi stil
@@ -507,23 +532,23 @@
STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Glasnost glasbe
STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Glasnost zvokov
STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX
-STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Skoci na prejsno skladbo v izboru
-STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Presckoci na naslednjo skladbo v izboru
+STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Skoči na prejšnjo skladbo v izboru
+STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Preskoči na naslednjo skladbo v izboru
STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Ustavi glasbo
STR_01E1_START_PLAYING_MUSIC :{BLACK}Predvajaj glasbo
-STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Povleci drsnike za nastavitev glasnosti glasbe in zvokov
+STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Premikaj drsnike za nastavitev glasnosti glasbe in zvokov
STR_01E3 :{DKGREEN}{TINYFONT}--
STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA}
STR_01E5 :{DKGREEN}{TINYFONT}{COMMA}
STR_01E6 :{DKGREEN}{TINYFONT}------
STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}"
-STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Skladba{SETX 88}Title
-STR_01E9_SHUFFLE :{TINYFONT}Mesaj
+STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Skladba{SETX 88}Naslov
+STR_01E9_SHUFFLE :{TINYFONT}Zmešaj
STR_01EA_PROGRAM :{TINYFONT}{BLACK}Program
STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Izbor glasbenega programa
STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA} "{STRING}"
STR_01ED :{TINYFONT}{LTBLUE}{COMMA} "{STRING}"
-STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Spisek skladb
+STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Seznam skladb
STR_01EF_PROGRAM :{TINYFONT}{BLACK}Program - '{STRING}'
STR_01F0_CLEAR :{TINYFONT}{BLACK}Zbriši
STR_01F1_SAVE :{TINYFONT}{BLACK}Shrani
@@ -533,39 +558,48 @@
STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Izberi glasbeni program 'novi stil'
STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Izberi glasbeni program 'po meri 1'
STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Izberi glasbeni program 'po meri 2'
-STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Zbriši trenuten glasbeni program (samo po meri 1 in 2)
+STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Zbriši trenutni glasbeni program (samo po meri 1 in 2)
STR_01F9_SAVE_MUSIC_SETTINGS :{BLACK}Shrani glasbene nastavitve
-STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klikni na skladbo da jo dodats na trenutni program (samo po meri 1 in 2)
-STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Preklapljaj Mesaj on/off
+STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Kliknite na skladbo, če jo želite dodati na trenutni program (samo po meri 1 in 2)
+STR_CLICK_ON_TRACK_TO_REMOVE :{BLACK}Kliknite na skladbo, če jo želite odstraniti iz programa (samo Poljubno1 ali Poljubno2)
+STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Preklapljaj zmešan program vključeno/izključeno
STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Pokaži okno z izborom glasbe
-STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klikni na servis za centrirat pogled na industrijo/mesto
+STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Kliknite na storitev za pogled na industrijo/mesto
STR_01FE_DIFFICULTY :{BLACK}Težavnost ({STRING})
STR_01FF :{TINYFONT}{BLACK}{DATE_LONG}
-STR_0200_LAST_MESSAGE_NEWS_REPORT :Zadnje sporocilo/novica
-STR_0201_MESSAGE_SETTINGS :Nastavitve sporocil
-STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Prikazi zadnje sporocilo/novico, prikazi moznosti sporocil
-STR_0204_MESSAGE_OPTIONS :{WHITE}Moznosti Sporocil
-STR_0205_MESSAGE_TYPES :{BLACK}
-STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Prihod prvega vozila na igralcevo postajo
+STR_0200_LAST_MESSAGE_NEWS_REPORT :Zadnje sporočilo/novica
+STR_0201_MESSAGE_SETTINGS :Nastavitve sporočil
+STR_MESSAGE_HISTORY_MENU :Zgodovina sporočil
+STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Prikaži zadnje sporočilo/novico, prikaži možnosti sporočil
+STR_0204_MESSAGE_OPTIONS :{WHITE}Možnosti Sporočil
+STR_0205_MESSAGE_TYPES :{BLACK}Tipi sporočil:
+STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Prihod prvega vozila na igralčevo postajo
STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Prihod prvega vozila na nasprotnikovo postajo
+STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Nesreče / katastrofe
STR_0209_COMPANY_INFORMATION :{YELLOW}Informacije o podjetju
STR_020A_ECONOMY_CHANGES :{YELLOW}Ekonomske spremembe
-STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Nasvet / informacija o igralcevem vozilu
-STR_020C_NEW_VEHICLES :{YELLOW}Novo vozilo
-STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Spremebe sprejemanja tovora
+STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Nasveti / informacije o igralčevem vozilu
+STR_020C_NEW_VEHICLES :{YELLOW}Odkrito novo vozilo
+STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Spremebe v sprejemanju tovora
STR_020E_SUBSIDIES :{YELLOW}Subvencije
-STR_020F_GENERAL_INFORMATION :{YELLOW}Glavne Informacije
-STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...predalec od prejsne destinacije
-STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Najboljsa podjetja, ki so dosegla {NUM}{}({STRING} stopnjo)
+STR_020F_GENERAL_INFORMATION :{YELLOW}Splošne Informacije
+STR_MESSAGES_ALL :{YELLOW}Nastavi prikaz vseh sporočil na: Izključen / Povzetek / Poln
+STR_MESSAGE_SOUND :{YELLOW}Zaigraj zvok ob povzetku novega sporočila
+STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE} ... predaleč od prejšnjega cilja
+STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Najboljša podjetja, ki so dosegla {NUM}{}({STRING} stopnjo)
+STR_TOP_COMPANIES_NETWORK_GAME :{BIGFONT}{BLACK}Seznam najboljših podjetij v {NUM}
STR_0212 :{BIGFONT}{COMMA}.
-STR_0213_BUSINESSMAN :Poslovnez
+STR_0213_BUSINESSMAN :Poslovnež
STR_0214_ENTREPRENEUR :Podjetnik
-STR_0215_INDUSTRIALIST :Industrijalist
+STR_0215_INDUSTRIALIST :Industrijalec
STR_0216_CAPITALIST :Kapitalist
STR_0217_MAGNATE :Magnat
STR_0218_MOGUL :Vladar
-STR_021B_ACHIEVES_STATUS :{BLACK}{BIGFONT}{COMPANY} doseze '{STRING}' status!
-STR_021C_OF_ACHIEVES_STATUS :{WHITE}{BIGFONT}{PLAYERNAME} iz {COMPANY} je dosegel '{STRING}' status!
+STR_0219_TYCOON_OF_THE_CENTURY :Velekapitalist stoletja
+STR_HIGHSCORE_NAME :{BIGFONT}{PLAYERNAME}, {COMPANY}
+STR_HIGHSCORE_STATS :{BIGFONT}'{STRING}' ({COMMA})
+STR_021B_ACHIEVES_STATUS :{BLACK}{BIGFONT}{COMPANY} doseže naslov '{STRING}'!
+STR_021C_OF_ACHIEVES_STATUS :{WHITE}{BIGFONT}{PLAYERNAME} iz podjetja {COMPANY} je dosegel naslov '{STRING}'!
STR_021F :{BLUE}{COMMA}
STR_0220_CREATE_SCENARIO :{BLACK}Ustvari Scenarij
STR_0221_OPENTTD :{YELLOW}OpenTTD
@@ -573,211 +607,247 @@
STR_0223_LAND_GENERATION :{WHITE}Generator terena
STR_0224 :{BLACK}{UPARROW}
STR_0225 :{BLACK}{DOWNARROW}
-STR_0226_RANDOM_LAND :{BLACK}Nakljucna zemlja
+STR_0226_RANDOM_LAND :{BLACK}Naključni teren
STR_0227_RESET_LAND :{BLACK}Ponastavi teren
-STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Povecaj obmocje za nizanje/visanje terena
-STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Zmanjsaj obmocje za nizanje/visanje terena
-STR_022A_GENERATE_RANDOM_LAND :{BLACK}Zgeneriraj nakljucni teren
+STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Povečaj območje za nižanje/višanje terena
+STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Zmanjšaj območje za nižanje/višanje terena
+STR_022A_GENERATE_RANDOM_LAND :{BLACK}Zgeneriraj naključni teren
STR_022B_RESET_LANDSCAPE :{BLACK}Ponastavi pokrajino
STR_022C_RESET_LANDSCAPE :{WHITE}Ponastavi pokrajino
-STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Ali si preprican, da hoces ponastaviti pokrajino
+STR_LOAD_GAME_HEIGHTMAP :{WHITE}Uporabi višinsko karto
+STR_LOAD_SCEN_HEIGHTMAP :{BLACK}Uporabi višinsko karto
+STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Ali ste prepričani, da želite ponastaviti pokrajino?
STR_022E_LANDSCAPE_GENERATION :{BLACK}Generator pokrajine
STR_022F_TOWN_GENERATION :{BLACK}Generator mest
STR_0230_INDUSTRY_GENERATION :{BLACK}Generator industrije
-STR_0231_ROAD_CONSTRUCTION :{BLACK}Grajenje cest
+STR_0231_ROAD_CONSTRUCTION :{BLACK}Gradnja cest
STR_0233_TOWN_GENERATION :{WHITE}Generator mest
STR_0234_NEW_TOWN :{BLACK}Novo mesto
STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Zgradi novo mesto
-STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Nemores graditi mesta tukaj...
-STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...preblizu robu mape
-STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...preblizu drugemu mestu
-STR_023A_TOO_MANY_TOWNS :{WHITE}...preveliko stevilo mest
-STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Povecaj velikost mesta
-STR_023C_EXPAND :{BLACK}Povecaj
-STR_023D_RANDOM_TOWN :{BLACK}Nakljucno mesto
-STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Zgradi mesto na nakljucni lokaciji
+STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Ne morete zgraditi mesta tukaj ...
+STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE} ... preblizu roba zemljevida
+STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE} ... preblizu drugemu mestu
+STR_0239_SITE_UNSUITABLE :{WHITE} ... neprimerna lokacija
+STR_023A_TOO_MANY_TOWNS :{WHITE} ... preveliko število mest
+STR_CANNOT_GENERATE_TOWN :{WHITE}Ni mogoče zgraditi mest
+STR_NO_SPACE_FOR_TOWN :{WHITE} ... ni več prostora na zemljevidu
+STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Povečaj velikost mesta
+STR_023C_EXPAND :{BLACK}Razširi
+STR_023D_RANDOM_TOWN :{BLACK}Naključno mesto
+STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Zgradi mesto na naključni lokaciji
STR_023F_INDUSTRY_GENERATION :{WHITE}Generator indrustrij
STR_0240_COAL_MINE :{BLACK}Rudnik Premoga
STR_0241_POWER_STATION :{BLACK}Termoelektrarna
-STR_0242_SAWMILL :{BLACK}Zaga
+STR_0242_SAWMILL :{BLACK}Žaga
STR_0243_FOREST :{BLACK}Gozd
STR_0244_OIL_REFINERY :{BLACK}Naftna rafinerija
STR_0245_OIL_RIG :{BLACK}Naftne vrtine
STR_0246_FACTORY :{BLACK}Tovarna
STR_0247_STEEL_MILL :{BLACK}Jeklarna
STR_0248_FARM :{BLACK}Kmetija
-STR_0249_IRON_ORE_MINE :{BLACK}Rudnik zeleza
+STR_0249_IRON_ORE_MINE :{BLACK}Rudnik železa
STR_024A_OIL_WELLS :{BLACK}Naftni Vrelci
STR_024B_BANK :{BLACK}Banka
STR_024C_PAPER_MILL :{BLACK}Papirnica
-STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Zivilska tovarna
+STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Predelava živil
STR_024E_PRINTING_WORKS :{BLACK}Tiskarna
STR_024F_GOLD_MINE :{BLACK}Rudnik Zlata
-STR_0250_LUMBER_MILL :{BLACK}Zaga
+STR_0250_LUMBER_MILL :{BLACK}Žaga
STR_0251_FRUIT_PLANTATION :{BLACK}Sadovnjak
-STR_0252_RUBBER_PLANTATION :{BLACK}Plantaza kavcuka
+STR_0252_RUBBER_PLANTATION :{BLACK}Plantaža kavčuka
STR_0253_WATER_SUPPLY :{BLACK}Vodni izvir
-STR_0254_WATER_TOWER :{BLACK}Vodni Stolp
+STR_0254_WATER_TOWER :{BLACK}Vodovodni Stolp
STR_0255_DIAMOND_MINE :{BLACK}Rudnik Diamantov
STR_0256_COPPER_ORE_MINE :{BLACK}Rudnik bakra
STR_0257_COTTON_CANDY_FOREST :{BLACK}Gozd sladkorne pene
-STR_0258_CANDY_FACTORY :{BLACK}Tovarna slascic
+STR_0258_CANDY_FACTORY :{BLACK}Tovarna slaščic
STR_0259_BATTERY_FARM :{BLACK}Farma baterij
-STR_025A_COLA_WELLS :{BLACK}Vrelci cocte
-STR_025B_TOY_SHOP :{BLACK}Trgovina z igracami
-STR_025C_TOY_FACTORY :{BLACK}Tovarna Igrac
+STR_025A_COLA_WELLS :{BLACK}Vrelci Cockte
+STR_025B_TOY_SHOP :{BLACK}Trgovina z igračami
+STR_025C_TOY_FACTORY :{BLACK}Tovarna Igrač
STR_025D_PLASTIC_FOUNTAINS :{BLACK}Vodnjaki plastike
-STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Tovarna gaziranih pijac
-STR_025F_BUBBLE_GENERATOR :{BLACK}Generator mehurckov
+STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Tovarna gaziranih pijač
+STR_025F_BUBBLE_GENERATOR :{BLACK}Generator mehurčkov
STR_0260_TOFFEE_QUARRY :{BLACK}Jama karamele
-STR_0261_SUGAR_MINE :{BLACK}Rudnik Sladkorja
-STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Zgradi Rudnik Premoga
+STR_0261_SUGAR_MINE :{BLACK}Rudnik sladkorja
+STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Zgradi rudnik premoga
STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Zgradi termoelektrarno
-STR_0264_CONSTRUCT_SAWMILL :{BLACK}Zgradi zago
+STR_0264_CONSTRUCT_SAWMILL :{BLACK}Zgradi žago
STR_0265_PLANT_FOREST :{BLACK}Posadi gozd
STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Zgradi naftno rafinerijo
-STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Zgradi naftno ploscad (Lahko je zgrajena samo blizu robu zemljevida)
+STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Zgradi naftno ploščad (Lahko je zgrajena samo blizu robu zemljevida)
STR_0268_CONSTRUCT_FACTORY :{BLACK}Zgradi tovarno
STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Zgradi jeklarno
STR_026A_CONSTRUCT_FARM :{BLACK}Zgradi kmetijo
-STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Zgradi rudnik zeleza
+STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Zgradi rudnik železa
STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Zgradi naftne vrelce
-STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Zgradi banko (Lahko je zgrajena samo mestih s populacijo vecjo od 1200)
+STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Zgradi banko (Lahko je zgrajena samo v mestih s populacijo večjo od 1200 ljudi)
STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Zgradi papirnico
-STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Zgradi zivilsko tovarno
+STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Zgradi tovarno predelave hrane
STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Zgradi tiskarno
STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Zgradi rudnik zlata
STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Zgradi banko (Samo v mestih)
-STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Zgradi zago (za izrabo dezevnega gozda in predelovanja lesa)
+STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Zgradi žago (za zmanjševanje deževnega gozda in predelavo lesa)
STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Zgradi sadovnjak
-STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Zgradi plantazo kavcuka
+STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Zgradi plantažo kavčuka
STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Zgradi vodno zajetje
-STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Zgradi vodni stolp (Samo v mestih)
+STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Zgradi vodovodni stolp (Samo v mestih)
STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Zgradi rudnik diamantov
STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Zgradi rudnik bakra
STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Posadi gozd sladkorne pene
-STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Zgradi tovarno slascic
+STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Zgradi tovarno slaščic
STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Zgradi farmo baterij
-STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Zgradi vrelce cocte
-STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Zgradi prodajalno z igracami
-STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Zgradi tovarno Igrac
+STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Zgradi vrelce Cockte
+STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Zgradi trgovino z igračami
+STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Zgradi tovarno igrač
STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Zgradi vodnjake plastike
-STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Zgradi tovarno gaziranih pijac
-STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Zgradi generator mehurckov
+STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Zgradi tovarno gaziranih pijač
+STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Zgradi generator mehurčkov
STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Zgradi jamo karamele
-STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK} Zgradi rudnik sladkorja
-STR_0285_CAN_T_BUILD_HERE :{WHITE}Tukaj ni mozno zgraditi {STRING}
-STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...najprej je potrebno zgraditi mesto
-STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...samo en dovoljen v mestu
+STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Zgradi rudnik sladkorja
+STR_0285_CAN_T_BUILD_HERE :{WHITE}Tukaj ni možno zgraditi {STRING}
+STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE} ... najprej je potrebno zgraditi mesto
+STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE} ... samo ena dovoljena v mestu
STR_0288_PLANT_TREES :{BLACK}Posadi drevesa
STR_0289_PLACE_SIGN :{BLACK}Postavi znak
-STR_028A_RANDOM_TREES :{BLACK}Nakljucna drevesa
-STR_028D_PLACE_LIGHTHOUSE :{BLACK}Zgradi svetilnik
-STR_0290_DELETE :{BLACK}Izbrisi
-STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Popolnoma izbrisi mesto
+STR_028A_RANDOM_TREES :{BLACK}Naključna drevesa
+STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Posadi drevesa naključno po ozemlju
+STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Ustvari kamnita območja naključno po ozemlju
+STR_028D_PLACE_LIGHTHOUSE :{BLACK}Postavi svetilnik
+STR_028E_PLACE_TRANSMITTER :{BLACK}Postavi oddajnik
+STR_028F_DEFINE_DESERT_AREA :{BLACK}Določi območja puščave.{}Pritisnite in držite CTRL za odstranitev
+STR_CREATE_LAKE :{BLACK}Določi vodno območje.{}Voda bo poplavila okolico, če bo na višini morja
+STR_0290_DELETE :{BLACK}Izbriši
+STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Popolnoma izbriši mesto
STR_0292_SAVE_SCENARIO :Shrani scenarij
-STR_0293_LOAD_SCENARIO :Nalozi scenarij
+STR_0293_LOAD_SCENARIO :Naloži scenarij
STR_0294_QUIT_EDITOR :Izhod iz urejevalnika
STR_0295 :
STR_0296_QUIT :Izhod
-STR_0298_LOAD_SCENARIO :{WHITE}Nalozi scenarij
+STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Shrani, naloži scenarij, zapusti urejevalnik scenarijev, izhod
+STR_0298_LOAD_SCENARIO :{WHITE}Naloži scenarij
STR_0299_SAVE_SCENARIO :{WHITE}Shrani scenarij
STR_029A_PLAY_SCENARIO :{BLACK}Igraj scenarij
+STR_PLAY_HEIGHTMAP :{BLACK}Igraj višinsko karto
+STR_PLAY_HEIGHTMAP_HINT :{BLACK}Začni novo igro z uporabo višinske karte za pokrajino
+STR_QUIT_SCENARIO_QUERY :{YELLOW}Ali ste prepričani, da želite zapustiti ta scenarij?
STR_029C_QUIT_EDITOR :{WHITE}Izhod iz urejevalnika
-STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Premakni zacetni datum za 1. leto nazaj
-STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Premakni zacetni datum za 1. leto naprej
-STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...oba prikljucka mosta morata biti na kopnem
+STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE} ... lahko zgrajen samo v mestih s populacijo 1200 ali več ljudi
+STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Premakni začetni datum za 1 leto nazaj
+STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Premakni začetni datum za 1 leto naprej
+STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE} ... oba priključka mostu morata biti na kopnem
STR_02A1_SMALL :{BLACK}Majhno
STR_02A2_MEDIUM :{BLACK}Srednje
STR_02A3_LARGE :{BLACK}Veliko
-STR_02A4_SELECT_TOWN_SIZE :{BLACK}Izberi velikost mesta
+STR_02A4_SELECT_TOWN_SIZE :{BLACK}Izberite velikost mesta
STR_02A5_TOWN_SIZE :{YELLOW}Velikost mesta:
STR_02B6 :{STRING} - {STRING}
-STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Prikazi zadnje sporocilo oziroma porocilo novice
+STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Prikaži zadnje sporočilo oziroma novico
+STR_OFF :Izključeno
+STR_SUMMARY :Povzetek
+STR_FULL :Polno
STR_02BA :{SILVER}- - {COMPANY} - -
+STR_02BB_TOWN_DIRECTORY :Imenik mest
+STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Imena oblike vozil
STR_02BD :{BLACK}{STRING}
STR_02BE_DEFAULT :Privzeto
STR_02BF_CUSTOM :Po meri
-STR_02C0_SAVE_CUSTOM_NAMES :{BLACK}Shrani
+STR_02C0_SAVE_CUSTOM_NAMES :{BLACK}Shrani poljubna imena
+STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Izbira imen oblik vozil
+STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Shrani poljubna imena oblik vozil
+STR_CHECKMARK :{CHECKMARK}
############ range for menu starts
-STR_02C3_GAME_OPTIONS :Moznosti igre
-STR_02C5_DIFFICULTY_SETTINGS :Nastavitve tezavnosti
-STR_02C7_CONFIG_PATCHES :Urejevanje popravkov
+STR_02C3_GAME_OPTIONS :Možnosti igre
+STR_02C5_DIFFICULTY_SETTINGS :Nastavitve težavnosti
+STR_02C7_CONFIG_PATCHES :Urejanje popravkov
+STR_NEWGRF_SETTINGS :NewGRF nastavitve
STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Imena mest prikazana
STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Imena postaj prikazana
-STR_02CE_SIGNS_DISPLAYED :{SETX 12}Sporocila prikazana
+STR_02CE_SIGNS_DISPLAYED :{SETX 12}Sporočila prikazana
STR_WAYPOINTS_DISPLAYED2 :{SETX 12}Smerokazi prikazani
-STR_02D0_FULL_ANIMATION :{SETX 12}Polna animacija
-STR_02D2_FULL_DETAIL :{SETX 12}Vse podrobnisti
-STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Prozorne stavbe
+STR_02D0_FULL_ANIMATION :{SETX 12}Polne animacije
+STR_02D2_FULL_DETAIL :{SETX 12}Vse podrobnosti
+STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Prosojne stavbe
+STR_TRANSPARENT_SIGNS :{SETX 12}Prosojni napisi postaj
############ range ends here
############ range for menu starts
-STR_02D5_LAND_BLOCK_INFO :Informacija o terenu
+STR_02D5_LAND_BLOCK_INFO :Informacije o terenu
STR_02D6 :
-STR_02D7_SCREENSHOT_CTRL_S :Zaslonska slika (Ctrl-S)
-STR_02D8_GIANT_SCREENSHOT_CTRL_G :Ogromna zaslonska slika (Ctrl-G)
+STR_CONSOLE_SETTING :Vklopi/Izklopi konzolo
+STR_02D7_SCREENSHOT_CTRL_S :Zajemi sliko (Ctrl-S)
+STR_02D8_GIANT_SCREENSHOT_CTRL_G :Zajemi celostno slika (Ctrl-G)
STR_02D9_ABOUT_OPENTTD :O 'OpenTTD'
############ range ends here
-STR_02DB_OFF :{BLACK}Izklopljeno
-STR_02DA_ON :{BLACK}Vklopljeno
-STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Prikazi subvencije
+STR_02DB_OFF :{BLACK}Izključeno
+STR_02DA_ON :{BLACK}Vključeno
+STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Prikaži subvencije
STR_02DD_SUBSIDIES :Subvencije
STR_02DE_MAP_OF_WORLD :Zemljevid sveta
-STR_02DF_TOWN_DIRECTORY :Direktorij mest
+STR_EXTRA_VIEW_PORT :Dodaten pogled
+STR_SIGN_LIST :Seznam napisov
+STR_02DF_TOWN_DIRECTORY :Imenik mest
STR_TOWN_POPULATION :{BLACK}Svetovna populacija: {COMMA}
+STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Pogled {COMMA}
+STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Kopiraj na pogled
-STR_02E0_CURRENCY_UNITS :{BLACK}Denarne valute
+STR_02E0_CURRENCY_UNITS :{BLACK}Valute
STR_02E1 :{BLACK}{SKIP}{STRING}
-STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Izbira denarnih valut
+STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Izbira valut
+STR_MEASURING_UNITS :{BLACK}Merske enote
STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING}
STR_02E6_ROAD_VEHICLES :{BLACK}Cestna vozila
STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING}
-STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Izberi stran ceste na kateri vozijo cestna vozila
-STR_02E9_DRIVE_ON_LEFT :Voznja po levi
-STR_02EA_DRIVE_ON_RIGHT :Voznja po desni
+STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Izberite smer vožnje cestnih vozil
+STR_02E9_DRIVE_ON_LEFT :Vožnja po levi
+STR_02EA_DRIVE_ON_RIGHT :Vožnja po desni
STR_02EB_TOWN_NAMES :{BLACK}Imena mest
STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
-STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Izberi stil imena mest
+STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Izberite slog imena mest
STR_02F4_AUTOSAVE :{BLACK}Shrani
STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
-STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Izberi interval med samodejnim shranjevanjem igre
+STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Izberite časovni interval samodejnega shranjevanja igre
STR_02F7_OFF :Izklopljeno
-STR_02F8_EVERY_3_MONTHS :vsake 3 mesece
-STR_02F9_EVERY_6_MONTHS :vsakih 6 mesecev
-STR_02FA_EVERY_12_MONTHS :vsakih 12 mesecev
-STR_02FB_START_A_NEW_GAME :{BLACK}Zacni novo igro
-STR_02FC_LOAD_A_SAVED_GAME :{BLACK}Nalozi shranjeno igro
+STR_02F8_EVERY_3_MONTHS :Vsake 3 mesece
+STR_02F9_EVERY_6_MONTHS :Vsakih 6 mesecev
+STR_02FA_EVERY_12_MONTHS :Vsakih 12 mesecev
+STR_02FB_START_A_NEW_GAME :{BLACK}Začni novo igro
+STR_02FC_LOAD_A_SAVED_GAME :{BLACK}Naloži shranjeno igro
STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Ustvari poljubni svet/scenarij
STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Izberi igro za enega igralca
-STR_0300_SELECT_MULTIPLAYER_GAME :{BLACK}Izberi igro za vec igralcev 2-8
-STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Prikazi moznosti igre
-STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Prikazi nastavitve tezavnosti
-STR_0303_START_A_NEW_GAME_USING :{BLACK}Zacni novo igro z uporabo scenarija
+STR_0300_SELECT_MULTIPLAYER_GAME :{BLACK}Izberi igro za 2-8 igralcev
+STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Prikaži možnosti igre
+STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Prikaži nastavitve težavnosti
+STR_0303_START_A_NEW_GAME_USING :{BLACK}Začni novo igro po scenariju
STR_0304_QUIT :{BLACK}Izhod
STR_0305_QUIT_OPENTTD :{BLACK}Izhod iz 'OpenTTD'
STR_0307_OPENTTD :{WHITE}OpenTTD {REV}
-STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...samo v mestih
-STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Podpri izgradnjo nove industrije
+STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE} ... samo v mestih
+STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Izberi običajen slog ozemlja
+STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Izberi stepski slog ozemlja
+STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Izberi subtropski slog ozemlja
+STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Izberi ozemlje sveta igrač
+STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Financiraj izgradnjo nove industrije
############ range for menu starts
+STR_INDUSTRY_DIR :Imenik tovarn
STR_0313_FUND_NEW_INDUSTRY :Odpri novo industrijo
############ range ends here
STR_0314_FUND_NEW_INDUSTRY :{WHITE}Odpri novo industrijo
-STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...gradnja mogoca samo v mestih
-STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}...gradnja mogoca samo v dezevnem gozdu
-STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...gradnja mogoca samo v puscavi
+STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE} ... gradnja mogoča samo v mestih
+STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE} ... gradnja mogoča samo v območju deževnega gozda
+STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE} ... gradnja mogoča samo v puščavi
STR_0319_PAUSED :{YELLOW}* * ZAUSTAVLJENO * *
-STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Zaslonska slika je uspesno shranjena kot {} '{STRING}'
-STR_031C_SCREENSHOT_FAILED :{WHITE}Jemanje zaslonske slike je {}SPODLETELO!!!
+STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Slika je uspešno zajeta kot {} '{STRING}'
+STR_031C_SCREENSHOT_FAILED :{WHITE}Zajemanje slike je {}SPODLETELO!!!
-STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Kupi zemljisce za prihodnjo rabo
+STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Kupi zemljišče za prihodnjo rabo
STR_032F_AUTOSAVE :{RED}Samodejno shranjevanje
STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Izberi 'Ezy Street' glasbeni program
@@ -836,6 +906,7 @@
STR_AUTOSAVE_1_MONTH :Vsak mesec
+STR_AUTOSAVE_FAILED :{WHITE}Samodejno shranjevanje spodletelo
STR_MONTH_JAN :Januar
STR_MONTH_FEB :Februar
@@ -851,9 +922,12 @@
STR_MONTH_DEC :December
+STR_BAGS :vreč
STR_TONS :tone
+STR_CANT_SHARE_ORDER_LIST :{WHITE}Ni mogoče deliti navodil ...
+STR_CANT_COPY_ORDER_LIST :{WHITE}Ni mogoče skopirati navodil ...
STR_TRAIN_IS_LOST :{WHITE}Vlak {COMMA} se je izgubil
STR_TRAIN_IS_UNPROFITABLE :{WHITE}Vlak {COMMA} je imel {CURRENCY} lansko leto
@@ -863,11 +937,17 @@
STR_TRAIN_HAS_TOO_FEW_ORDERS :{WHITE}Vlak {COMMA} ima premalo narocil na svojem seznamu
STR_TRAIN_HAS_DUPLICATE_ENTRY :{WHITE}Vlak {COMMA} ima podvojena narocila
STR_TRAIN_HAS_INVALID_ENTRY :{WHITE}Vlak {COMMA} ima nepravilno zaporedje narocil
+STR_AIRCRAFT_HAS_TOO_FEW_ORDERS :{WHITE}Letalo {COMMA} ima premalo ukazov v navodilih
+STR_AIRCRAFT_HAS_VOID_ORDER :{WHITE}Letalo {COMMA} ima ničen ukaz
+STR_AIRCRAFT_HAS_DUPLICATE_ENTRY :{WHITE}Letalo {COMMA} ima podvojene ukaze
+STR_AIRCRAFT_HAS_INVALID_ENTRY :{WHITE}Letalo {COMMA} ima neveljavne postaje v navodilih
# end of order system
STR_TRAIN_AUTORENEW_FAILED :{WHITE}Avtomatska zamenjava je spodletela na vlaku {COMMA} (denarni problemi)
+STR_AIRCRAFT_AUTORENEW_FAILED :{WHITE}Samoprenova neuspela na letalu {COMMA} (omejitev z denarjem)
STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}Vlak {COMMA} je predolg po zamenjavi
+STR_CONFIG_PATCHES :{BLACK}Nastavitve popravkov
STR_CONFIG_PATCHES_OFF :Izklopi
STR_CONFIG_PATCHES_ON :Vklopi
@@ -880,6 +960,9 @@
+
+STR_CONFIG_PATCHES_AI :{BLACK}Tekmeci
+
STR_CONFIG_PATCHES_DISABLED :dizejblano
STR_CONFIG_PATCHES_INT32 :{NUM}
STR_CONFIG_PATCHES_CURRENCY :{CURRENCY}
@@ -888,6 +971,18 @@
STR_TEMPERATE_LANDSCAPE :Zmerno podnebje
STR_TOYLAND_LANDSCAPE :Igracarsko pokrajina
+STR_CHEATS :{WHITE}Goljufije
+STR_CHEATS_TIP :{BLACK}Kljukice kažejo, če so bile goljufije že kdaj uporabljene
+STR_CHEATS_WARNING :{BLACK}Pozor! Nameravate izdati svoje tekmece. Tako sramotno dejanje bo zapomnjeno za vselej.
+STR_CHEAT_MONEY :{LTBLUE}Povečaj denar za {CURRENCY64}
+STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Igra se kot igralec: {ORANGE}{COMMA}
+STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Čarobni buldožer (odstrani tovarne, neodstranljive objekte): {ORANGE}{STRING}
+STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tuneli se lahko križajo pod zemljo: {ORANGE}{STRING}
+STR_CHEAT_BUILD_IN_PAUSE :{LTBLUE}Zgrajeno med pavzo: {ORANGE}{STRING}
+STR_CHEAT_NO_JETCRASH :{LTBLUE}Reaktivci ne bodo strmoglavili (pogostokrat) na malih letališčih: {ORANGE} {STRING}
+STR_CHEAT_SWITCH_CLIMATE :{LTBLUE}Spreminjanje klime: {ORANGE} {STRING}
+STR_CHEAT_CHANGE_DATE :{LTBLUE}Spremeni datum: {ORANGE} {DATE_SHORT}
+STR_CHEAT_SETUP_PROD :{LTBLUE}Omogoči spreminjanje vrednosti produktov: {ORANGE}{STRING}
@@ -901,8 +996,29 @@
STR_WAYPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{WAYPOINT}
STR_WAYPOINT_RAW :{WAYPOINT}
+STR_CANT_CHANGE_WAYPOINT_NAME :{WHITE}Ni mogoče preimenovati kažipota ...
+STR_CANT_BUILD_TRAIN_WAYPOINT :{WHITE}Ni mogoče postaviti kažipotov tukaj ...
+STR_CANT_REMOVE_TRAIN_WAYPOINT :{WHITE}Ni mogoče odstraniti kažipota tukaj ...
+
+STR_BUILD_AUTORAIL_TIP :{BLACK}Gradi železnico s pomočjo Samodejne gradnje
+STR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Ni mogoče zgraditi industrij ...
+
+
+
+
+STR_CANT_BUILD_CANALS :{WHITE}Ni mogoče zgraditi kanalov tukaj ...
+STR_BUILD_CANALS_TIP :{BLACK}Gradnja kanalov. CTRL+klik za postavitev morskih kvadratkov (samo na nadmorski višini morja)
+
+STR_CANT_BUILD_LOCKS :{WHITE}Ni mogoče zgraditi zapornic tukaj ...
+STR_BUILD_LOCKS_TIP :{BLACK}Gradnja zapornic
+
+STR_BUOY_IS_IN_USE :{WHITE} ... boja v uporabi!
+
+
+STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Ni mogoče odstraniti dela postaje ...
+STR_CANT_CONVERT_RAIL :{WHITE}Ni mogoče spremeniti železnice tukaj ...
@@ -910,15 +1026,7 @@
-
-
-
-
-
-
-
-
-
+STR_CONFIG_GAME_PRODUCTION :{WHITE}Spremeni produkcijo
TEMP_AI_IN_PROGRESS :{WHITE}Dobrodosli v UI v razvoju. Ce boste prisli do problemov, posnamite zaslonsko sliko in jo prilepite na forum.
TEMP_AI_ACTIVATED :{WHITE}Opozorilo: Nova UI je se vedno alfa razlicica! Zaenkrat, samo tovornjaki in avtobusi delujejo!
@@ -963,69 +1071,94 @@
+
+##### PNG-MAP-Loader
+
+
+STR_BMPMAP_ERROR :{WHITE}Ni mogoče naložiti pokrajine iz formata BMP ...
+STR_BMPMAP_ERR_IMAGE_TYPE :{WHITE} ... ni mogoče spremeniti tipa slike.
+
##id 0x0800
-STR_0800_COST :{TINYFONT}{RED}Stroski: {CURRENCY}
-STR_0801_COST :{RED}Stroski: {CURRENCY}
-STR_0802_INCOME :{TINYFONT}{GREEN}Prihodek: {CURRENCY}
-STR_0803_INCOME :{GREEN}Prihodek: {CURRENCY}
-STR_0805_ESTIMATED_COST :{WHITE}Ocenjeni strosek: {CURRENCY}
-STR_0807_ESTIMATED_INCOME :{WHITE}Predviden prihodek: {CURRENCY}
-STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Tukaj nemore?dvigniti terena...
-STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Tukaj nemore?znizati terena...
+STR_0800_COST :{TINYFONT}{RED}Stroški: {CURRENCY}
+STR_0801_COST :{RED}Stroški: {CURRENCY}
+STR_0802_INCOME :{TINYFONT}{GREEN}Prihodki: {CURRENCY}
+STR_0803_INCOME :{GREEN}Prihodki: {CURRENCY}
+STR_0805_ESTIMATED_COST :{WHITE}Ocenjeni stroški: {CURRENCY}
+STR_0807_ESTIMATED_INCOME :{WHITE}Predvideni prihodki: {CURRENCY}
+STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Tukaj ne morete dvigniti terena ...
+STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Tukaj ne morete znižati terena ...
STR_080A_ROCKS :Kamenje
-STR_080C_BARE_LAND :Gol teren
+STR_080B_ROUGH_LAND :Groba tla
+STR_080C_BARE_LAND :Gola tla
STR_080D_GRASS :Trava
STR_080E_FIELDS :Polja
-STR_080F_SNOW_COVERED_LAND :S snegom pokrit teren
-STR_0810_DESERT :Puscava
+STR_080F_SNOW_COVERED_LAND :Zasnežen teren
+STR_0810_DESERT :Puščava
##id 0x1000
-STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren nagnjen v napacno smer
-STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Nemogoca kombinacija tracnic
-STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Premikanje bi lahko poskodovalo tunel
-STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Ze na nadmorski visini
+STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren nagnjen v napačno smer
+STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Nemogoča kombinacija tirnic
+STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Premikanje bi lahko poškodovalo tunel
+STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Že na nadmorski višini
STR_1004_TOO_HIGH :{WHITE}Previsoko
-STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Nobene uporabne tracnice
-STR_1007_ALREADY_BUILT :{WHITE}...ze zgrajeno
-STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Najprej moras odstraniti tracnice
+STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Nobene uporabne tračnice
+STR_1007_ALREADY_BUILT :{WHITE} ... že zgrajeno
+STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Najprej morate odstraniti tračnice
STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Gradnja železnice
STR_TITLE_ELRAIL_CONSTRUCTION :{WHITE}Elektrificirana Zeleznica
-STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Izberi zelezniski most
-STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Tu ne morete zgraditi zelezniskega skladisca...
-STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Tu ne morete zgraditi zelezniske postaje...
-STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Tu ne morete zgraditi signalov...
-STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Tu ne morete zgraditi zelezniskih tirov...
-STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Tu ne morete odstraniti zelezniskih tirov...
-STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Tu ne morete odstraniti signalov...
-STR_1015_RAILROAD_CONSTRUCTION :Gradnja zeleznice
+STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Gradnja enotirne železnice
+STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Gradnja magnetne železnice
+STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Izberi železniški most
+STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Tu ne morete zgraditi železniškega skladišča ...
+STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Tu ne morete zgraditi železniške postaje ...
+STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Tu ne morete zgraditi semaforjev ...
+STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Tu ne morete zgraditi železniških tirov ...
+STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Tu ne morete odstraniti železniških tirov ...
+STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Tu ne morete odstraniti semaforjev ...
+STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Smer železniškega skladišča
+STR_1015_RAILROAD_CONSTRUCTION :Gradnja železnice
STR_TOOLB_ELRAIL_CONSTRUCTION :Elektrificirana zeleznica
-STR_1016_MONORAIL_CONSTRUCTION :Enotirna zeleznica
-STR_1017_MAGLEV_CONSTRUCTION :Magnetna zeleznica
-STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Zgradi tracnice
-STR_101A_BUILD_RAILROAD_STATION :{BLACK}Zgradi zelezznisko postajo
-STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Zgradi zelezniske semaforje
-STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Zgradi zelezniski most
-STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Zgradi zelezniski tunel
-STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Preklopi gradi/rusi za zelezniske semaforje
-STR_1021_RAILROAD_TRACK :Zelezniska proga
-STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...zemljisce je last neke druge druzbe
+STR_1016_MONORAIL_CONSTRUCTION :Enotirna železnica
+STR_1017_MAGLEV_CONSTRUCTION :Magnetna železnica
+STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Zgradi tračnice
+STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Zgradi železniško skladišče (za izgradnjo in servis vlakov)
+STR_101A_BUILD_RAILROAD_STATION :{BLACK}Zgradi železniško postajo
+STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Zgradi železniške semaforje
+STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Zgradi železniški most
+STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Zgradi železniški tunel
+STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Preklopi gradnjo/rušenje železniških semaforjev
+STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Izbira mostu - kliknite na željeni most za izgradnjo
+STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}Izberi smer železniškega skladišča
+STR_1021_RAILROAD_TRACK :Železniška proga
+STR_1023_RAILROAD_TRAIN_DEPOT :Železniško skladišče
+STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE} ... zemljišče je last nekega drugega podjetja
##id 0x1800
-STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Najprej zgradi cesto
+STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Najprej odstrani cesto
STR_1802_ROAD_CONSTRUCTION :{WHITE}Cestne gradnje
STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Izberi cestni most
-STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Tu ne mores zgraditi ceste...
-STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Tu ne mores odstraniti ceste...
-STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Ne mores zgraditi avtobusne postaje...
+STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Tu ne morete zgraditi ceste ...
+STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Tu ne morete odstraniti ceste ...
+STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Smer garaže
+STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Ne morete zgraditi garaže tukaj ...
+STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Ne morete zgraditi avtobusne postaje ...
+STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Ne morete zgraditi tovorne postaje tukaj ...
+STR_180A_ROAD_CONSTRUCTION :Gradnja ceste
+STR_180B_BUILD_ROAD_SECTION :{BLACK}Zgradi cestni odsek
+STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Zgradi garažo (za izgradnjo in servis vozil)
STR_180D_BUILD_BUS_STATION :{BLACK}Zgradi avtobusno postajo
+STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Zgradi tovorno postajo
STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Zgradi cestni most
STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Zgradi cestni predor
+STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Preklapljaj gradnjo/rušenje cestnih konstrukcij
+STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Izberi smer garaže
STR_1814_ROAD :Cesta
-STR_1815_ROAD_WITH_STREETLIGHTS :Cesta s cestnimi lucmi
+STR_1815_ROAD_WITH_STREETLIGHTS :Cesta s cestnimi lučmi
STR_1816_TREE_LINED_ROAD :Cesta z drevoredom
-STR_1818_ROAD_RAIL_LEVEL_CROSSING :Cestno/zeleznisko krizisce
+STR_1817_ROAD_VEHICLE_DEPOT :Garaža
+STR_1818_ROAD_RAIL_LEVEL_CROSSING :Cestno/železniško križišče
##id 0x2000
STR_2000_TOWNS :{WHITE}Mesta
@@ -1034,181 +1167,221 @@
STR_TOWN_LABEL_TINY_BLACK :{TINYFONT}{BLACK}{TOWN}
STR_TOWN_LABEL_TINY_WHITE :{TINYFONT}{WHITE}{TOWN}
STR_2002 :{TINYFONT}{BLACK}{STRING}
-STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Najprej mora bit porusena stavba
+STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Najprej mora biti stavba porušena
STR_2005 :{WHITE}{TOWN}
-STR_2006_POPULATION :{BLACK}Populacija: {ORANGE}{COMMA}{BLACK} His: {ORANGE}{COMMA}
+STR_2006_POPULATION :{BLACK}Populacija: {ORANGE}{COMMA}{BLACK} Število stavb: {ORANGE}{COMMA}
STR_2007_RENAME_TOWN :Preimenuj mesto
-STR_2008_CAN_T_RENAME_TOWN :{WHITE}Nemores preimenovati mesta...
+STR_2008_CAN_T_RENAME_TOWN :{WHITE}Ne morete preimenovati mesta ...
STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} lokalna oblast tega ne dovoli
+STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Imena mest - kliknite na ime za pogled na mesto
+STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Premakni celotni pogled na mesto
STR_200C_CHANGE_TOWN_NAME :{BLACK}Spremeni ime mesta
-STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Potnikov prejsni mesec: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
-STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Poste prejsni mesec: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
-STR_200F_TALL_OFFICE_BLOCK :Visoka pisarniska hisa
-STR_2010_OFFICE_BLOCK :Pisarniska hisa
+STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Potnikov prejšnji mesec: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
+STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Pošte prejšnji mesec: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
+STR_200F_TALL_OFFICE_BLOCK :Visok pisarniški blok
+STR_2010_OFFICE_BLOCK :Pisarniški blok
STR_2011_SMALL_BLOCK_OF_FLATS :Majhen blok
STR_2012_CHURCH :Cerkev
-STR_2013_LARGE_OFFICE_BLOCK :Velika pisarniska hisa
-STR_2014_TOWN_HOUSES :Mestna hisa
+STR_2013_LARGE_OFFICE_BLOCK :Velik pisarniški blok
+STR_2014_TOWN_HOUSES :Meščanske hiše
STR_2015_HOTEL :Hotel
-STR_2016_STATUE :Kip
+STR_2016_STATUE :Spomenik
STR_2017_FOUNTAIN :Vodnjak
STR_2018_PARK :Park
-STR_2019_OFFICE_BLOCK :Pisarniska hisa
+STR_2019_OFFICE_BLOCK :Pisarniški blok
STR_201A_SHOPS_AND_OFFICES :Trgovine in pisarne
-STR_201B_MODERN_OFFICE_BUILDING :Moderna pisarniska hisa
-STR_201C_WAREHOUSE :Skladisce
-STR_201D_OFFICE_BLOCK :Pisarniska hisa
+STR_201B_MODERN_OFFICE_BUILDING :Moderna pisarniška hiša
+STR_201C_WAREHOUSE :Skladišče
+STR_201D_OFFICE_BLOCK :Pisarniška hiša
STR_201E_STADIUM :Stadion
-STR_201F_OLD_HOUSES :Stare hise
+STR_201F_OLD_HOUSES :Stare hiše
STR_2020_LOCAL_AUTHORITY :{BLACK}Mestni svet
-STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Pokazi informacije o lokalni oblasti
-STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} Mestni svet
-STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}
+STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Pokaži informacije o lokalni oblasti
+STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} mestni svet
+STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Ocene podjetja:
STR_2024 :{YELLOW}{COMPANY}{PLAYERNAME}: {ORANGE}{STRING}
STR_2025_SUBSIDIES :{WHITE}Subvencije
-STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Ponudba subvencij:
+STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Ponudba subvencije za storitev:
STR_2027_FROM_TO :{ORANGE}{STRING} iz {STRING} v {STRING}
STR_2028_BY :{YELLOW} (do {DATE_SHORT})
-STR_202A_NONE :{ORANGE}Noben
-STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Subvencionirane storitve
+STR_202A_NONE :{ORANGE}Nihče
+STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Že subvencionirane storitve:
STR_202C_FROM_TO :{ORANGE}{STRING} od {STATION} do {STATION}{YELLOW} ({COMPANY}
-STR_202D_UNTIL :{YELLOW},do {DATE_SHORT})
-STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Ponudba za subvencijo umaknjena:{}{}{STRING} od {STRING} do {STRING} od sedaj ne bo prinesla subvencije.
-STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subvencija je potekla:{}{}{STRING} storitev od {STATION} do {STATION} ni vec subvencionirana is no longer subsidised.
-STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Ponudena subvencija:{}{}Prva {STRING} storitev od {STRING} do {STRING} bo subvencionirana s strani mestnega sveta!
-STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvencija podeljena {COMPANY}!{}{}{STRING} storitev od {STATION} do {STATION} bo prinesla 50% vecji prihodek za naslednje leto!
+STR_202D_UNTIL :{YELLOW}, do {DATE_SHORT})
+STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Subvencioniranje zaključeno: storitev {}{}{STRING} od {STRING} do {STRING} ne bo subvencionirana.
+STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subvencija je potekla:{}{}{STRING} storitev od {STATION} do {STATION} ni več subvencionirana.
+STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Nova subvencija:{}{}Prva {STRING} storitev od {STRING} do {STRING} bo subvencionirana s strani mestnega sveta!
+STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvencija podeljena {COMPANY}!{}{}{STRING} storitev od {STATION} do {STATION} bo prinesla 50% večji prihodek za naslednje leto!
STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvencija podeljena {COMPANY}!{}{}{STRING} storitev od {STATION} do {STATION} bo prinesla dvakratni prihodek
STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvencija podeljena {COMPANY}!{}{}{STRING} storitev od {STATION} do {STATION} bo prinesla trikratni prihodek za naslednje leto!
-STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvencija podeljena {COMPANY}!{}{}{STRING} storitev od {STATION} do {STATION} bo prinesla stirikratni prihodek za naslednje leto!
-STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} mestni svet prepoveduje granjo se enega letalisca v tem mestu
-STR_2036_COTTAGES :Koce
-STR_2037_HOUSES :Hise
+STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvencija podeljena {COMPANY}!{}{}{STRING} storitev od {STATION} do {STATION} bo prinesla štirikratni prihodek za naslednje leto!
+STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} mestni svet prepoveduje gradnjo še enega letališča v tem mestu
+STR_2036_COTTAGES :Koče
+STR_2037_HOUSES :Hiše
STR_2038_FLATS :Stanovanja
-STR_2039_TALL_OFFICE_BLOCK :Visoka poslovna hisa
-STR_203A_SHOPS_AND_OFFICES :Trgovince in pisarne
-STR_203B_SHOPS_AND_OFFICES :Trgovince in pisarne
-STR_203C_THEATER :Gledalisce
+STR_2039_TALL_OFFICE_BLOCK :Visoka poslovna hiša
+STR_203A_SHOPS_AND_OFFICES :Trgovine in pisarne
+STR_203B_SHOPS_AND_OFFICES :Trgovine in pisarne
+STR_203C_THEATER :Gledališče
STR_203D_STADIUM :Stadion
STR_203E_OFFICES :Pisarne
-STR_203F_HOUSES :Hise
+STR_203F_HOUSES :Hiše
STR_2040_CINEMA :Kino
STR_2041_SHOPPING_MALL :Trgovski center
STR_2042_DO_IT :{BLACK}Stori to
-STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Seznam stvari, ki jih lahko naredis v tem mestu - klikni stvar za vec podrobnosti
-STR_2046_SMALL_ADVERTISING_CAMPAIGN :Majhna reklamna kampanja
-STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Srednja reklamna kampanja
-STR_2048_LARGE_ADVERTISING_CAMPAIGN :Velik reklamna kampanja
-STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Podpri obnovo cest
-STR_204A_BUILD_STATUE_OF_COMPANY :Zgradi kip lastnikafirme
+STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Seznam stvari, ki jih lahko naredite v tem mestu - kliknite na predmet za podrobnosti
+STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Izvrši izbrano storitev na zgornjem seznamu
+STR_2045_ACTIONS_AVAILABLE :{BLACK}Storitve na voljo:
+STR_2046_SMALL_ADVERTISING_CAMPAIGN :Majhna reklamna kampanija
+STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Srednje velika reklamna kampanija
+STR_2048_LARGE_ADVERTISING_CAMPAIGN :Velika reklamna kampanija
+STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Financiraj obnovo cest
+STR_204A_BUILD_STATUE_OF_COMPANY :Zgradi spomenik lastniku podjetja
STR_204B_FUND_NEW_BUILDINGS :Sponzoriraj nove stavbe
-STR_204C_BUY_EXCLUSIVE_TRANSPORT :Kupi eksluzivne transportne novice
+STR_204C_BUY_EXCLUSIVE_TRANSPORT :Kupi eksluzivne transportne pravice
STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Podkupi lokalno oblast
+STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Izvrši majhno reklamno kampanijo z namenom privabiti več potnikov in tovora podjetju.{} Cena: {CURRENCY}
+STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Izvrši srednje-veliko reklamno kampanijo z namenom privabiti več potnikov in tovora podjetju.{} Cena: {CURRENCY}
+STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Izvrši veliko reklamno kampanijo z namenom privabiti več potnikov in tovora podjetju.{} Cena: {CURRENCY}
+STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Financiraj obnovo cest z namenom motnje cestnega prometa tudi do 6 mesecev.{} Cena: {CURRENCY}
+STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Zgradi spomenik v čast podjetju.{} Cena: {CURRENCY}
+STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Financiraj izgradnjo novih poslovnih stavb v mestu.{} Cena: {CURRENCY}
+STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Kupi enoletno izključno pravico do transporta v mestu. Lokalne oblasti bodo dovolile potnikom in tovoru do izključno vaše uporabe transportnih storitev.{} Cena: {CURRENCY}
STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Podkupi lokalno oblast za izboljsavo svojih rating ob tveganju resnih kazni ob caught.{} Stane: {CURRENCY}
+STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING :{BIGFONT}{BLACK}Prometni kaos v mestu {TOWN}!{}{}Obnovitvena dela, ki jih financira podjetje {COMPANY}, bodo prinesla 6 mesecev nočnih mor voznikom motornih vozil!
STR_2056 :{TINYFONT}{WHITE}{TOWN}
STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA})
-STR_2058_UNDER_CONSTRUCTION :{STRING} (v gradnji)
+STR_2058_UNDER_CONSTRUCTION :{STRING} (v izgradnji)
STR_2059_IGLOO :Iglu
+STR_205B_TEAPOT_HOUSE :Čajna hiša
+STR_205C_PIGGY_BANK :Prašičkova banka
##id 0x2800
STR_2800_PLANT_TREES :Posadi drevesa
STR_2801_PLACE_SIGN :Postavi znak
STR_2802_TREES :{WHITE}Drevesa
-STR_2803_TREE_ALREADY_HERE :{WHITE}...drevo ze posajeno
-STR_2804_SITE_UNSUITABLE :{WHITE}...sajenje nemogoce
-STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Nemores posaditi drevesa tukaj...
+STR_2803_TREE_ALREADY_HERE :{WHITE} ... drevo že posajeno
+STR_2804_SITE_UNSUITABLE :{WHITE} ... sajenje nemogoče
+STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Ne morete posaditi drevesa tukaj ...
STR_2806 :{WHITE}{STRING}
-STR_2808_TOO_MANY_SIGNS :{WHITE}...prevec znakov
-STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Nemores postaviti znaka tukaj
+STR_2808_TOO_MANY_SIGNS :{WHITE} ... preveč znakov
+STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Ne morete postaviti znaka tukaj
STR_280A_SIGN :Znak
STR_280B_EDIT_SIGN_TEXT :{WHITE}Uredi znak
-STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Nemores spremeniti ime znaka...
-STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Izberi vrsto drevesa za posaditev
+STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Ne morete spremeniti imena znaka ...
+STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Izberite vrsto drevesa za posaditev
STR_280E_TREES :Drevesa
-STR_280F_RAINFOREST :Dezevni gozd
+STR_280F_RAINFOREST :Deževni gozd
STR_2810_CACTUS_PLANTS :Kaktusi
##id 0x3000
-STR_3000_RAIL_STATION_SELECTION :{WHITE}Izbira zelezniske postaje
-STR_3001_AIRPORT_SELECTION :{WHITE}Izbira letalisca
+STR_3000_RAIL_STATION_SELECTION :{WHITE}Izbira železniške postaje
+STR_3001_AIRPORT_SELECTION :{WHITE}Izbira letališča
STR_3002_ORIENTATION :{BLACK}Orientacija
-STR_3003_NUMBER_OF_TRACKS :{BLACK}Stevilo peronov
-STR_3004_PLATFORM_LENGTH :{BLACK}Dolzina perona
-STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Preblizu druge zelezniske postaje
-STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Zdruzi dve postaji
-STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Prevec postaj v tem mestu
-STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Prevec postaj na zemljevidu
-STR_3008A_TOO_MANY_BUS_STOPS :{WHITE}Prevec avtobusnih postaj
-STR_3008B_TOO_MANY_TRUCK_STOPS :{WHITE}Prevec tovornih postaj
+STR_3003_NUMBER_OF_TRACKS :{BLACK}Število peronov
+STR_3004_PLATFORM_LENGTH :{BLACK}Dolžina perona
+STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Preblizu druge železniške postaje
+STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Združi dve postaji
+STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Preveč postaj v tem mestu
+STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Preveč postaj na zemljevidu
+STR_3008A_TOO_MANY_BUS_STOPS :{WHITE}Preveč avtobusnih postaj
+STR_3008B_TOO_MANY_TRUCK_STOPS :{WHITE}Preveč tovornih postaj
STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Preblizu druge postaje
STR_300A_0 :{WHITE}{STATION} {STATIONFEATURES}
-STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Najprej je potrebno zrusiti postajo
-STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Preblizu sosednjemu letaliscu
-STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Najprej je potrebno zrusiti letalisce
+STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Najprej je potrebno porušiti postajo
+STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Preblizu sosednjemu letališču
+STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Najprej je potrebno porušiti letališče
STR_3030_RENAME_STATION_LOADING :Preimenuj postajo
-STR_3031_CAN_T_RENAME_STATION :{WHITE}Ni mozno preimenovati postaje
-STR_3032_RATINGS :{BLACK}Ugled
+STR_3031_CAN_T_RENAME_STATION :{WHITE}Ni mogoče preimenovati postaje
+STR_3032_RATINGS :{BLACK}Ocene
STR_3033_ACCEPTS :{BLACK}Sprejema
+STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Lokalne ocene transportne storitve:
############ range for rating starts
-STR_3035_APPALLING :Strasen
+STR_3035_APPALLING :Strašen
STR_3036_VERY_POOR :Zelo slab
STR_3037_POOR :Slab
-STR_3038_MEDIOCRE :Sreden
+STR_3038_MEDIOCRE :Srednji
STR_3039_GOOD :Dober
STR_303A_VERY_GOOD :Zelo dober
STR_303B_EXCELLENT :Izvrsten
-STR_303C_OUTSTANDING :Sijajno
+STR_303C_OUTSTANDING :Sijajen
############ range for rating ends
STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA}%)
-STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} ne sprejema vec {STRING}
-STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} ne sprejema vec {STRING} in {STRING}
-STR_3040_NOW_ACCEPTS :{WHITE}{STATION} sprejema {STRING}
-STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} sprejema {STRING} in {STRING}
+STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} ne sprejema več {STRING}
+STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} ne sprejema več {STRING} in {STRING}
+STR_3040_NOW_ACCEPTS :{WHITE}{STATION} sedaj sprejema {STRING}
+STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} sedaj sprejema {STRING} in {STRING}
+STR_3042_BUS_STATION_ORIENTATION :{WHITE}Orientacija avtobusne postaje
+STR_3043_TRUCK_STATION_ORIENT :{WHITE}Orientacija tovorne postaje.
+STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Najprej morate porušiti avtobusno postajo
+STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Najprej morate porušiti tovorno postajo
STR_3048_STATIONS :{WHITE}{COMPANY} - {COMMA} Postaja{P "" s}
STR_3049_0 :{YELLOW}{STATION} {STATIONFEATURES}
STR_304A_NONE :{YELLOW}- Nobeno -
-STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Preblizu drugemu pristaniscu
-STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Najprej moras porusiti pristanisce
-STR_3054_SHOW_STATION_RATINGS :{BLACK}Prikaz rangov postaje
+STR_304B_SITE_UNSUITABLE :{WHITE} ... neprimerna lokacija
+STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Preblizu drugemu pristanišču
+STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Najprej morate porušiti pristanišče
+STR_304E_SELECT_RAILROAD_STATION :{BLACK}Izberite orientacijo železniške postaje
+STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Izberite število peronov železniške postaje
+STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Izberite dolžino železniške postaje
+STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Izberite orientacijo železniške postaje
+STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Izberite orientacijo tovorne postaje
+STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Pogled na postajo
+STR_3054_SHOW_STATION_RATINGS :{BLACK}Prikaz ocen postaje
STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Spremeni ime postaje
+STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Prikaži seznam sprejetega tovora
+STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Imena postaj - kliknite na ime za pogled na postajo
+STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Izbira velikosti/tipa letališča
STR_305C_0 :{STATION} {STATIONFEATURES}
-STR_305E_RAILROAD_STATION :Zelezniska postaja
+STR_305E_RAILROAD_STATION :Železniška postaja
STR_305F_AIRCRAFT_HANGAR :Hangar
-STR_3060_AIRPORT :Letalisce
+STR_3060_AIRPORT :Letališče
STR_3061_TRUCK_LOADING_AREA :Tovorna postaja
STR_3062_BUS_STATION :Avtobusna postaja
-STR_3063_SHIP_DOCK :Pristanisce
-STR_3068_DOCK :{WHITE}Pristanisce
+STR_3063_SHIP_DOCK :Pristanišče
+STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Osvetli pokritost območja
+STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Ne osvetli pokritosti območja
+STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Osvetlitev pokritosti območja
+STR_3068_DOCK :{WHITE}Pristanišče
STR_3069_BUOY :Boja
-STR_306A_BUOY_IN_THE_WAY :{WHITE}...boja na poti
+STR_306A_BUOY_IN_THE_WAY :{WHITE} ... boja na poti
+STR_306C_STATION_TOO_SPREAD_OUT :{WHITE} ... postaja preveč razširjena
+STR_306D_NONUNIFORM_STATIONS_DISALLOWED :{WHITE} ... nehomogene postaje izklopljene
##id 0x3800
-STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...potrebno je zgraditi na vodi
+STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Orientacija ladjedelnice
+STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE} ... zgrajeno mora biti na vodi
+STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Ne morem zgraditi ladjedelnice tukaj ...
+STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Izberite orientacijo ladjedelnice
STR_3804_WATER :Voda
-STR_3805_COAST_OR_RIVERBANK :Obala ali recni breg
-STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Ni mozno graditi na vodi
+STR_3805_COAST_OR_RIVERBANK :Obala ali nabrežje
+STR_3806_SHIP_DEPOT :Ladjedelnica
+STR_3807_CAN_T_BUILD_ON_WATER :{WHITE} ... Ni mogoče graditi na vodi
##id 0x4000
STR_4000_SAVE_GAME :{WHITE}Shrani igro
-STR_4001_LOAD_GAME :{WHITE}Nalozi igro
+STR_4001_LOAD_GAME :{WHITE}Naloži igro
STR_4002_SAVE :{BLACK}Shrani
-STR_4003_DELETE :{BLACK}Izbrisi
+STR_4003_DELETE :{BLACK}Izbriši
STR_4004 :{COMPANY}, {DATE_LONG}
STR_4005_BYTES_FREE :{BLACK}{COMMA} megabajtov{P "" s} prosto
-STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Ni mozno brati diska
+STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Ni mogoče brati pogona
STR_4007_GAME_SAVE_FAILED :{WHITE}Shranjevanje igre ni uspelo
-STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Ni mozno izbrisati datoteko
+STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Ni mogoče izbrisati datoteke
STR_4009_GAME_LOAD_FAILED :{WHITE}Nalaganje igre ni uspelo
-STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Seznam diskov, map in shranjenih iger
+STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Seznam pogonov, zemljevidov in shranjenih iger
STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Trenutno izbrano ime za shranjevanje
-STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Izbrisi trenutno izbrano shranjeno igro
-STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Shrani trenutno igro, z izbranim imenom
+STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Izbriši trenutno izbrano shranjeno igro
+STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Shrani trenutno igro z izbranim imenom
STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Izberi tip nove igre
-STR_4010_GENERATE_RANDOM_NEW_GAME :Ustvari nakljucno novo igro
+STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Izberite scenarij (zeleno), prednastavljeno igro (modro) ali naključno novo igro
+STR_4010_GENERATE_RANDOM_NEW_GAME :Ustvari naključno novo igro
+STR_4011_LOAD_HEIGHTMAP :{WHITE}Naloži višinsko karto
##id 0x4800
STR_4800_IN_THE_WAY :{WHITE}{STRING} na poti
@@ -1218,36 +1391,36 @@
STR_4804_SAWMILL :Žaga
STR_4805_FOREST :Gozd
STR_4806_OIL_REFINERY :Naftna rafinerija
-STR_4807_OIL_RIG :Naftna ploscad
+STR_4807_OIL_RIG :Naftna ploščad
STR_4808_FACTORY :Tovarna
STR_4809_PRINTING_WORKS :Tiskarna
-STR_480A_STEEL_MILL :Zelezarna
+STR_480A_STEEL_MILL :Železarna
STR_480B_FARM :Kmetija
STR_480C_COPPER_ORE_MINE :Rudnik bakra
STR_480D_OIL_WELLS :Naftni izviri
STR_480E_BANK :Banka
-STR_480F_FOOD_PROCESSING_PLANT :Zivilska tovarna
+STR_480F_FOOD_PROCESSING_PLANT :Predelava živil
STR_4810_PAPER_MILL :Papirnica
STR_4811_GOLD_MINE :Rudnik zlata
STR_4812_BANK :Banka
STR_4813_DIAMOND_MINE :Rudnik diamantov
-STR_4814_IRON_ORE_MINE :Rudnik zeleza
+STR_4814_IRON_ORE_MINE :Rudnik železa
STR_4815_FRUIT_PLANTATION :Sadovnjak
-STR_4816_RUBBER_PLANTATION :Plantaza kavcuka
+STR_4816_RUBBER_PLANTATION :Plantaža kavčuka
STR_4817_WATER_SUPPLY :Vodno zajetje
-STR_4818_WATER_TOWER :Vodni stolp
+STR_4818_WATER_TOWER :Vodovodni stolp
STR_4819_FACTORY :Tovarna
STR_481A_FARM :Kmetija
-STR_481B_LUMBER_MILL :Zaga
+STR_481B_LUMBER_MILL :Žaga
STR_481C_COTTON_CANDY_FOREST :Gozd sladkorne pene
-STR_481D_CANDY_FACTORY :Tovarna slascic
+STR_481D_CANDY_FACTORY :Tovarna slaščic
STR_481E_BATTERY_FARM :Farma baterij
-STR_481F_COLA_WELLS :Izviri cockte
-STR_4820_TOY_SHOP :Trgovina z igracami
-STR_4821_TOY_FACTORY :Tovarna igrac
+STR_481F_COLA_WELLS :Izvir Cockte
+STR_4820_TOY_SHOP :Trgovina z igračami
+STR_4821_TOY_FACTORY :Tovarna igrač
STR_4822_PLASTIC_FOUNTAINS :Vodnjaki plastike
-STR_4823_FIZZY_DRINK_FACTORY :Tovarna gaziranih pijac
-STR_4824_BUBBLE_GENERATOR :Generator mehurckov
+STR_4823_FIZZY_DRINK_FACTORY :Tovarna gaziranih pijač
+STR_4824_BUBBLE_GENERATOR :Generator mehurčkov
STR_4825_TOFFEE_QUARRY :Jama karamele
STR_4826_SUGAR_MINE :Rudnik sladkorja
@@ -1257,52 +1430,73 @@
STR_4829_REQUIRES :{BLACK}Potrebuje:: {YELLOW}{STRING}, {STRING}, {STRING}
############ range for requires ends
-STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Proizvodnja prejsnega meseca:
-STR_482B_TRANSPORTED :{YELLOW}{CARGO}{BLACK} ({COMMA}% transportirano)
+STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Proizvodnja prejšnjega meseca:
+STR_482B_TRANSPORTED :{YELLOW}{CARGO}{BLACK} ({COMMA}% oddano)
+STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Pogled na industrijo
+STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Nov {STRING} v izgradnji blizu mesta {TOWN}!
+STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Nov {STRING} v izgradnji blizu mesta {TOWN}!
STR_482F_COST :{BLACK}Cena: {YELLOW}{CURRENCY}
-STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Tukaj ni mozno zgraditi tega tipa industrije...
-STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... gozd je mozno nasaditi samo nad snezno mejo
-STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...mozno je samo zgraditi ob robu zemljevida
+STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Tukaj ni mogoče zgraditi tega tipa industrije ...
+STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE} ... gozd je mogoče posaditi samo nad snežno mejo
+STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{INDUSTRY} napoveduje takojšnje zaprtje!
+STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Zaradi težav z zalogami {INDUSTRY} napoveduje takojšnje zaprtje!
+STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Zaradi pomanjkanja bližnjih dreves {INDUSTRY} napoveduje takojšnje zaprtje!
+STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{INDUSTRY} povečuje proizvodnjo!
+STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Nova žila premoga najdena v {INDUSTRY}!{}Proizvodnja se bo podvojila!
+STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nove rezerve nafte odkrite v {INDUSTRY}!{}Proizvodnja se bo podvojila!
+STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Izboljšane metode pridelovanja v {INDUSTRY} bodo podvojile proizvodnjo!
+STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{INDUSTRY} proizvodnja zmanjšana za 50%
+STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Insekti povzročili opustošenje v {INDUSTRY}!{}Proizvodnja zmanjšana za 50%
+STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE} ... mogoče zgraditi samo ob robu zemljevida
##id 0x5000
STR_5000_TRAIN_IN_TUNNEL :{WHITE}Vlak v tunelu
STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Cestno vozilo v tunelu
-STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Potrebno je najprej zakopati drugi tunel
-STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Potebno je najprej porusiti most
-STR_5008_CANNOT_START_AND_END_ON :{WHITE}Ni mozno zaceti in koncati v isti tocki
-STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Potrebno je izravnati teren ali vodo pod mostom
-STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Zacetek in konec morata biti na enaki visini
+STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Obstoječi tunel v napoto
+STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Ni mogoče izkopati zaključka tunela na drugem koncu
+STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Potrebno je najprej podreti drugi tunel
+STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Potebno je najprej porušiti most
+STR_5008_CANNOT_START_AND_END_ON :{WHITE}Ni mogoče začeti in končati v isti točki
+STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Raven teren ali vodovje zahtevano pod mostom
+STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Začetek in konec morata biti na isti višini
+STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Lokacija neprimerna za vhod v tunel
STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY}
-STR_500E_SUSPENSION_STEEL :Viseci, Zelezni
-STR_500F_GIRDER_STEEL :Nosilni, Zelezni
-STR_5010_CANTILEVER_STEEL :Nosilni, Zelezni
-STR_5011_SUSPENSION_CONCRETE :Viseci, Betonski
+STR_500E_SUSPENSION_STEEL :Viseči, Jekleni
+STR_500F_GIRDER_STEEL :Nosilni, Jekleni
+STR_5010_CANTILEVER_STEEL :Nosilen, Jeklen
+STR_5011_SUSPENSION_CONCRETE :Viseč, Betonski
STR_5012_WOODEN :Lesen
STR_5013_CONCRETE :Betonski
-STR_5014_TUBULAR_STEEL :Cevast, Zelezen
-STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Tukaj ni mozno zgraditi most...
-STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Tukaj ni mozno zgraditi tunel
-STR_5017_RAILROAD_TUNNEL :Zelezniski tunel
-STR_5018_ROAD_TUNNEL :Cestni tunel
-STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Obeseni zelezni zelezniski most
-STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Nosilni zelezni zelezniski most
-STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Nosilni zelezni zelezniski most
-STR_501E_REINFORCED_CONCRETE_SUSPENSION :Obeseni betonsko okrepljeni zelezniski most
-STR_501F_WOODEN_RAIL_BRIDGE :Lesen zelezniski most
-STR_5020_CONCRETE_RAIL_BRIDGE :Betonski zelezniski most
-STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Obeseni zelezni cestni most
-STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Nosilni zelezni cestni most
-STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Nosilni zelezni cestni most
-STR_5024_REINFORCED_CONCRETE_SUSPENSION :Obeseni betonsko okrepljeni cestni most
+STR_5014_TUBULAR_STEEL :Cevast, Jeklen
+STR_BRIDGE_TUBULAR_SILICON :Cevast, Silicijev
+STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Tukaj ni mogoče zgraditi mostu ...
+STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Tukaj ni mogoče zgraditi tunela ...
+STR_5017_RAILROAD_TUNNEL :Železniški predor
+STR_5018_ROAD_TUNNEL :Cestni predor
+STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Viseč jekleni železniški most
+STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Nosilen jeklen železniški most
+STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Nosilen jeklen železniški most
+STR_501E_REINFORCED_CONCRETE_SUSPENSION :Ojačan viseč betonski železniški most
+STR_501F_WOODEN_RAIL_BRIDGE :Lesen železniški most
+STR_5020_CONCRETE_RAIL_BRIDGE :Betonski železniški most
+STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Viseč jeklen cestni most
+STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Nosilen jeklen cestni most
+STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Jeklen cestni most na nosilcih
+STR_5024_REINFORCED_CONCRETE_SUSPENSION :Ojačan viseč betonski cestni most
STR_5025_WOODEN_ROAD_BRIDGE :Lesen cestni most
STR_5026_CONCRETE_ROAD_BRIDGE :Betonski cestni most
-STR_5027_TUBULAR_RAIL_BRIDGE :Cevni zelezniski most
-STR_5028_TUBULAR_ROAD_BRIDGE :Cevni cestni most
+STR_5027_TUBULAR_RAIL_BRIDGE :Cevast železniški most
+STR_5028_TUBULAR_ROAD_BRIDGE :Cevast cestni most
##id 0x5800
STR_5800_OBJECT_IN_THE_WAY :{WHITE}Objekt na poti
STR_5801_TRANSMITTER :Oddajnik
STR_5802_LIGHTHOUSE :Svetilnik
+STR_5803_COMPANY_HEADQUARTERS :Sedež podjetja
+STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE} ... sedež podjetja na poti
+STR_5805_COMPANY_OWNED_LAND :Ozemlje v lasti podjetja
+STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Ni mogoče kupiti tega zemljišča ...
+STR_5807_YOU_ALREADY_OWN_IT :{WHITE} ... ste že lastnik!
############ WARNING, using range 0x6000 for strings that are stored in the savegame
@@ -1319,43 +1513,44 @@
############ end of savegame specific region!
##id 0x6800
-STR_6800_DIFFICULTY_LEVEL :{WHITE}Tezavnostna stopnja
+STR_6800_DIFFICULTY_LEVEL :{WHITE}Težavnostna stopnja
############ range for difficulty levels starts
STR_6801_EASY :{BLACK}Preprosto
STR_6802_MEDIUM :{BLACK}Srednje
-STR_6803_HARD :{BLACK}Tezko
+STR_6803_HARD :{BLACK}Težko
STR_6804_CUSTOM :{BLACK}Po meri
############ range for difficulty levels ends
############ range for difficulty settings starts
-STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Najvecje stevilo nasprotnikov: {ORANGE}{COMMA}
-STR_6806_COMPETITOR_START_TIME :{LTBLUE}Nasportnikov zacetni cas: {ORANGE}{STRING}
-STR_6807_NO_OF_TOWNS :{LTBLUE}St. mest: {ORANGE}{STRING}
-STR_6808_NO_OF_INDUSTRIES :{LTBLUE}St. industrije: {ORANGE}{STRING}
-STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Najvisje mozno posojilo: {ORANGE}{CURRENCY}
+STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Največje število nasprotnikov: {ORANGE}{COMMA}
+STR_6806_COMPETITOR_START_TIME :{LTBLUE}Nasportnikov začetni čas: {ORANGE}{STRING}
+STR_6807_NO_OF_TOWNS :{LTBLUE}Št. mest: {ORANGE}{STRING}
+STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Št. industrij: {ORANGE}{STRING}
+STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Najvišje možno posojilo: {ORANGE}{CURRENCY}
STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Obrestna mera: {ORANGE}{COMMA}%
-STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Cena vzdrzevanja vozil: {ORANGE}{STRING}
-STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR :{LTBLUE}Hitrost grajenja nasportnikov: {ORANGE}{STRING}
-STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intiligenca naspornikov: {ORANGE}{STRING}
+STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Cena vzdrževanja vozil: {ORANGE}{STRING}
+STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR :{LTBLUE}Nasprotnikova hitrost gradnje: {ORANGE}{STRING}
+STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Inteligenca nasprotnikov: {ORANGE}{STRING}
STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Okvare vozil: {ORANGE}{STRING}
+STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Večkratnik subvencij: {ORANGE}{STRING}
STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Cena gradnje: {ORANGE}{STRING}
STR_6811_TERRAIN_TYPE :{LTBLUE}Tip terena: {ORANGE}{STRING}
-STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Kolicina vode in morij: {ORANGE}{STRING}
+STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Količina vodovij: {ORANGE}{STRING}
STR_6813_ECONOMY :{LTBLUE}Ekonomija: {ORANGE}{STRING}
-STR_6814_TRAIN_REVERSING :{LTBLUE}Obracanje vlakov: {ORANGE}{STRING}
+STR_6814_TRAIN_REVERSING :{LTBLUE}Obračanje vlakov: {ORANGE}{STRING}
STR_6815_DISASTERS :{LTBLUE}Katastrofe: {ORANGE}{STRING}
-STR_16816_CITY_APPROVAL :{LTBLUE}Odnos mestnega sveta glede restrukturiranja: {ORANGE}{STRING}
+STR_16816_CITY_APPROVAL :{LTBLUE}Odnos mestnega sveta do rekonstrukcije: {ORANGE}{STRING}
############ range for difficulty settings ends
-STR_26816_NONE :Noben
+STR_26816_NONE :Nič
STR_6816_LOW :Nizko
STR_6817_NORMAL :Normalno
STR_6818_HIGH :Visoko
STR_6819 :{BLACK}{SMALLLEFTARROW}
STR_681A :{BLACK}{SMALLRIGHTARROW}
-STR_681B_VERY_SLOW :Zelo pocasno
-STR_681C_SLOW :Pocasno
+STR_681B_VERY_SLOW :Zelo počasno
+STR_681C_SLOW :Počasno
STR_681D_MEDIUM :Srednje
STR_681E_FAST :Hitro
STR_681F_VERY_FAST :Zelo hitro
@@ -1364,141 +1559,337 @@
STR_6821_MEDIUM :Srednje
STR_6822_HIGH :Visoko
STR_6823_NONE :Nobeno
-STR_6824_REDUCED :Zmanjsano
+STR_6824_REDUCED :Zmanjšano
STR_6825_NORMAL :Normalno
STR_6826_X1_5 :x1,5
STR_6827_X2 :x2
STR_6828_X3 :x3
STR_6829_X4 :x4
-STR_682A_VERY_FLAT :Zelo polozno
-STR_682B_FLAT :Polozno
+STR_682A_VERY_FLAT :Zelo položno
+STR_682B_FLAT :Položno
STR_682C_HILLY :Hribovito
STR_682D_MOUNTAINOUS :Gorato
STR_682E_STEADY :Stalno
-STR_682F_FLUCTUATING :Fluktacija
-STR_6830_IMMEDIATE :Takojsno
+STR_682F_FLUCTUATING :Fluktuacija
+STR_6830_IMMEDIATE :Takojšnje
STR_6831_3_MONTHS_AFTER_PLAYER :3 mesece za igralcem
STR_6832_6_MONTHS_AFTER_PLAYER :6 mesecev za igralcem
STR_6833_9_MONTHS_AFTER_PLAYER :9 mesecev za igralcem
-STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Na koncu linije, in na postajah
+STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Na koncu linije in na postajah
STR_6835_AT_END_OF_LINE_ONLY :Samo na koncu linije
STR_6836_OFF :Izklopljeno
STR_6837_ON :Vklopljeno
-STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Pokazi tabelo najboljsih
+STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Pokaži tabelo najboljših
STR_6839_PERMISSIVE :Dopustno
STR_683A_TOLERANT :Tolerantno
-STR_683B_HOSTILE :Sovrazno
+STR_683B_HOSTILE :Sovražno
##id 0x7000
STR_7000 :
STR_7001 :{WHITE}{COMPANY} {BLACK}{PLAYERNAME}
-STR_7002_PLAYER :(Igralce {COMMA})
+STR_7002_PLAYER :(Igralec {COMMA})
STR_7004_NEW_FACE :{BLACK}Nov obraz
+STR_7005_COLOR_SCHEME :{BLACK}Barva
+STR_7006_COLOR_SCHEME :{GOLD}Barva:
+STR_7007_NEW_COLOR_SCHEME :{WHITE}Nova barva
+STR_7008_COMPANY_NAME :{BLACK}Ime podjetja
+STR_7009_PRESIDENT_NAME :{BLACK}Ime lastnika
+STR_700A_COMPANY_NAME :Ime podjetja
+STR_700B_PRESIDENT_S_NAME :Ime lastnika
+STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Ni mogoče spremeniti imena podjetja ...
+STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Ni mogoče spremeniti imena lastnika ...
+STR_700E_FINANCES :{WHITE}{COMPANY} Finance {BLACK}{PLAYERNAME}
+STR_700F_EXPENDITURE_INCOME :{WHITE}Izdatki/Prilivi
+STR_7011_CONSTRUCTION :{GOLD}Konstrukcija
+STR_7012_NEW_VEHICLES :{GOLD}Nova vozila
+STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Cena delovanja vlakov
+STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Cena delovanja cestnih vozil
+STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Cena delovanja letal
+STR_7016_SHIP_RUNNING_COSTS :{GOLD}Cena delovanja ladij
+STR_7017_PROPERTY_MAINTENANCE :{GOLD}Vzdrževanje
+STR_7018_TRAIN_INCOME :{GOLD}Priliv vlakov
+STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Priliv cestnih vozil
+STR_701A_AIRCRAFT_INCOME :{GOLD}Priliv letal
+STR_701B_SHIP_INCOME :{GOLD}Priliv ladij
+STR_701C_LOAN_INTEREST :{GOLD}Obresti posojila
+STR_701D_OTHER :{GOLD}Drugo
+STR_7020_TOTAL :{WHITE}Skupaj:
+STR_7022_INCOME_GRAPH :{WHITE}Graf priliva
+STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Graf čistega dobička
+STR_7026_BANK_BALANCE :{WHITE}Stanje na banki
+STR_7027_LOAN :{WHITE}Posojilo
+STR_7029_BORROW :{BLACK}Sposodi {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
+STR_702A_REPAY :{BLACK}Odplačaj {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
+STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE} ... najvišje posojilo je {CURRENCY}
+STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Ni si mogoče izposoditi več denarja ...
+STR_702D_LOAN_ALREADY_REPAYED :{WHITE} ... ni posojila za odplačati
+STR_702E_REQUIRED :{WHITE}...{CURRENCY} potrebno
+STR_702F_CAN_T_REPAY_LOAN :{WHITE}Ni mogoče odplačati posojila ...
+STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Izberi nov obraz za lastnika
+STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Spremeni barvo vozil podjetja
+STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Spremeni ime lastnika
+STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Spremeni ime podjetja
+STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Kliknite na željeno barvo
+STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Povečaj višino posojila
+STR_7036_REPAY_PART_OF_LOAN :{BLACK}Odplačaj del posojila
+STR_7037_PRESIDENT :{WHITE}{PLAYERNAME}{}{GOLD}(Lastnik)
+STR_7038_INAUGURATED :{GOLD}Postavljen spomenik: {WHITE}{NUM}
+STR_7039_VEHICLES :{GOLD}Vozila:
STR_TRAINS :{WHITE}{COMMA} vlak{P "" s}
-STR_7049_SELECT_MALE_FACES :{BLACK}Izberi mosko sliko
-STR_704A_SELECT_FEMALE_FACES :{BLACK}Izberi zensko sliko
-STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Naredi nakljucno novo sliko
-STR_704C_KEY :{BLACK}Kljuc
-STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankrotiral si!
-STR_7060_CAN_T_BUY_COMPANY :{WHITE}Ne mores kupiti podjetja...
+STR_AIRCRAFT :{WHITE}{COMMA} letalo
+STR_7042_NONE :{WHITE}Nič
+STR_7043_FACE_SELECTION :{WHITE}Izbira obraza
+STR_7044_MALE :{BLACK}Moški
+STR_7045_FEMALE :{BLACK}Ženska
+STR_7046_NEW_FACE :{BLACK}Nov obraz
+STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Prekliči izbiro novega obraza
+STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Sprejmi nov obraz
+STR_7049_SELECT_MALE_FACES :{BLACK}Izberi moške slike
+STR_704A_SELECT_FEMALE_FACES :{BLACK}Izberi ženske slike
+STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Naredi naključno novo sliko
+STR_704C_KEY :{BLACK}Ključ
+STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Prikaži ključe grafov
+STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Ključi grafov podjetij
+STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Kliknite sem za napise podjetja na grafu vključeno/izključeno
+STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Enot tovora dostavljenega
+STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Ocene podjetja (max=1000)
+STR_7052_COMPANY_VALUES :{WHITE}Vrednosti podjetij
+STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Seznam najboljših podjetij
+STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Podjetje v težavah!
+STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :Podjetje {BLACK}{BIGFONT}{COMPANY} bo prodano ali prisiljeno v stečajni postopek, če se stanje kmalu ne izboljša!
+STR_7058_PRESIDENT :{BLACK}{PLAYERNAME}{}(Lastnik)
+STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Združevalec podjetij!
+STR_705A_HAS_BEEN_SOLD_TO_FOR :Podjetje {BLACK}{BIGFONT}{COMPANY} je bilo prodano podejtju {COMPANY} za {CURRENCY}!
+STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Iščemo novega lastnika, ki bi prevzel naše podjetje.{}{}Ali bi želeli kupiti podjetje {COMPANY} za {CURRENCY}?
+STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankrotirali ste!
+STR_705D_HAS_BEEN_CLOSED_DOWN_BY :Investitorji so zaprli podjetje {BLACK}{BIGFONT}{COMPANY} in prodali vse imetje!
+STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Ustanoveljno novo podjetje!
+STR_705F_STARTS_CONSTRUCTION_NEAR :Podjetje {BLACK}{BIGFONT}{COMPANY} začenja gradnjo blizu mesta {TOWN}!
+STR_7060_CAN_T_BUY_COMPANY :{WHITE}Ne morete kupiti podjetja ...
+STR_7061_CARGO_PAYMENT_RATES :{WHITE}Ocene plačevanja tovora
+STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Dni v prevozu
+STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Plačilo za dostavo 10 enot (ali 10.000 litrov) tovora za razdaljo 20 kvadratkov
+STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Prikaži graf za tip tovora vključen/izključen
STR_7065 :{BLACK}{TINYFONT}{STRING}
-STR_7066_ENGINEER :Inzenir
-STR_7067_TRAFFIC_MANAGER :Upravnik prometa
+STR_7066_ENGINEER :Inženir
+STR_7067_TRAFFIC_MANAGER :Vodja prometa
+STR_7068_TRANSPORT_COORDINATOR :Koordinator transporta
+STR_7069_ROUTE_SUPERVISOR :Nadzornik dostave
STR_706A_DIRECTOR :Direktor
+STR_706B_CHIEF_EXECUTIVE :Vrhovni direktor
STR_706C_CHAIRMAN :Minister
STR_706D_PRESIDENT :Predsednik
STR_706E_TYCOON :Velekapitalist
-STR_706F_BUILD_HQ :{BLACK}Izgradi sedež podjetja
+STR_706F_BUILD_HQ :{BLACK}Zgradi sedež podjetja
+STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Zgradi sedež podjetja / poglej sedež podjetja
+STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Ne morem zgraditi sedeža podjetja
STR_7072_VIEW_HQ :{BLACK}Poglej sedež podjetja
+STR_COMPANY_PASSWORD :{BLACK}Geslo
+STR_COMPANY_PASSWORD_TOOLTIP :{BLACK}Zaščitite svoje podjetje z geslom, da preprečite priključitev drugih uporabnikov k podjetju.
+STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Svetovna recesija!{}{}Ekonomisti se bojijo najhujšega ob trenutnem poteku dogodkov!
+STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Konec recesije!{}{}Izboljšanje trgovanja povečuje zaupanje domače industrije, gospodarstvo napreduje!
+STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Menjaj veliko/majhno velikost okna
+STR_7076_COMPANY_VALUE :{GOLD}Vrednost podjetja: {WHITE}{CURRENCY64}
+STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Kupi 25% delnic podjetja
+STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Prodaj 25% delnic podjetja
+STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Kupi 25% delnic tega podjetja
+STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Prodaj 25% delnic tega podjetja
+STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Ni mogoče kupiti 25% tržnega deleža tega podjetja ...
+STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Ni mogoče prodati 25% tržnega deleža tega podjetja ...
+STR_707D_OWNED_BY :{WHITE}({COMMA}% last podjetja {COMPANY})
+STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA}% last podjetja {COMPANY}{} {COMMA}% last podjetja {COMPANY})
+STR_707F_HAS_BEEN_TAKEN_OVER_BY :Podjetje {BLACK}{BIGFONT}{COMPANY} je bilo prevzeto iz strani podjetja {COMPANY}!
+STR_7080_PROTECTED :{WHITE}Podjetje še ni dovolj staro, da bi lahko trgovalo z lastnimi delnicami ...
+
+
##id 0x8000
-STR_804F_CANDY_VAN :Tovornjak slascic
-STR_8050_TOY_VAN :Tovornjak igrac
+STR_8017_SH_30_ELECTRIC :SH '30' (Električen)
+STR_8018_SH_40_ELECTRIC :SH '40' (Električen)
+STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Električen)
+STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Električen)
+STR_801B_PASSENGER_CAR :Potniški prevoz
+STR_801C_MAIL_VAN :Kamion s pošto
+STR_801D_COAL_CAR :Kamion s premogom
+STR_801E_OIL_TANKER :Naftni tanker
+STR_801F_LIVESTOCK_VAN :Kamion z živino
+STR_8020_GOODS_VAN :Kamion z dobrinami
+STR_8021_GRAIN_HOPPER :Kamion z žitom
+STR_8022_WOOD_TRUCK :Kamion z lesom
+STR_8023_IRON_ORE_HOPPER :Kamion z železovo rudo
+STR_8024_STEEL_TRUCK :Kamion z jeklom
+STR_8025_ARMORED_VAN :Oklepen kamion
+STR_8026_FOOD_VAN :Kamion s hrano
+STR_8027_PAPER_TRUCK :Kamion s papirjem
+STR_8028_COPPER_ORE_HOPPER :Kamion z bakrovo rudo
+STR_8029_WATER_TANKER :Cisterna z vodo
+STR_802A_FRUIT_TRUCK :Kamion s sadjem
+STR_802B_RUBBER_TRUCK :Kamion z gumo
+STR_802C_SUGAR_TRUCK :Kamion s sladkorjem
+STR_802D_COTTON_CANDY_HOPPER :Kamion s sladkorno peno
+STR_802E_TOFFEE_HOPPER :Kamion s toffee
+STR_802F_BUBBLE_VAN :Kamion z mehurčki
+STR_8030_COLA_TANKER :Kamion s Cockto
+STR_8031_CANDY_VAN :Kamion s sladkarijami
+STR_8032_TOY_VAN :Kamion z igračami
+STR_8033_BATTERY_TRUCK :Kamion z baterijami
+STR_8034_FIZZY_DRINK_TRUCK :Kamion z gaziranimi pijačami
+STR_8035_PLASTIC_TRUCK :Kamion s plastiko
+STR_8036_X2001_ELECTRIC :'X2001' (Električen)
+STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Električen)
+STR_8039_PASSENGER_CAR :Prevoz potnikov
+STR_803A_MAIL_VAN :Tovornjak pošte
+STR_803B_COAL_CAR :Tovornjak premoga
+STR_803C_OIL_TANKER :Cisterna z nafto
+STR_803D_LIVESTOCK_VAN :Tovornjak živine
+STR_803E_GOODS_VAN :Tovornjak dobrin
+STR_803F_GRAIN_HOPPER :Tovornjak žita
+STR_8040_WOOD_TRUCK :Tovornjak lesa
+STR_8041_IRON_ORE_HOPPER :Tovornjak železove rude
+STR_8042_STEEL_TRUCK :Tovornjak jekla
+STR_8043_ARMORED_VAN :Oklepen tovornjak
+STR_8044_FOOD_VAN :Tovornjak hrane
+STR_8045_PAPER_TRUCK :Tovornjak papirja
+STR_8046_COPPER_ORE_HOPPER :Tovornjak bakrove rude
+STR_8047_WATER_TANKER :Cisterna z vodo
+STR_8048_FRUIT_TRUCK :Tovornjak sadja
+STR_8049_RUBBER_TRUCK :Tovornjak gume
+STR_804A_SUGAR_TRUCK :Tovornjak sladkorja
+STR_804B_COTTON_CANDY_HOPPER :Tovornjak sladkorne pene
+STR_804C_TOFFEE_HOPPER :Tovornjak toffee
+STR_804D_BUBBLE_VAN :Tovornjak mehurčkov
+STR_804E_COLA_TANKER :Tovornjak Cockte
+STR_804F_CANDY_VAN :Tovornjak slaščic
+STR_8050_TOY_VAN :Tovornjak igrač
STR_8051_BATTERY_TRUCK :Tovornjak baterij
-STR_8052_FIZZY_DRINK_TRUCK :Tovornjak gaziranih pijac
+STR_8052_FIZZY_DRINK_TRUCK :Tovornjak gaziranih pijač
STR_8053_PLASTIC_TRUCK :Tovornjak plastike
-STR_8059_PASSENGER_CAR :Potniski vagon
-STR_805A_MAIL_VAN :Postni vagon
+STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Električen)
+STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Električen)
+STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Električen)
+STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Električen)
+STR_8059_PASSENGER_CAR :Potniški vagon
+STR_805A_MAIL_VAN :Poštni vagon
STR_805B_COAL_CAR :Vagon za premog
STR_805C_OIL_TANKER :Vagon za nafto
-STR_805D_LIVESTOCK_VAN :Vagon za zivino
+STR_805D_LIVESTOCK_VAN :Vagon za živino
STR_805E_GOODS_VAN :Vagon za dobrine
-STR_805F_GRAIN_HOPPER :Vagon za zito
+STR_805F_GRAIN_HOPPER :Vagon za žito
STR_8060_WOOD_TRUCK :Vagon za les
-STR_8061_IRON_ORE_HOPPER :Vagon za zelezovo rudo
+STR_8061_IRON_ORE_HOPPER :Vagon za železovo rudo
STR_8062_STEEL_TRUCK :Vagon za jeklo
STR_8063_ARMORED_VAN :Oklepni vagon
STR_8064_FOOD_VAN :Vagon za hrano
STR_8065_PAPER_TRUCK :Vagon za papir
-STR_8066_COPPER_ORE_HOPPER :Vagon za bakreno rudo
-STR_8067_WATER_TANKER :Vodni tanker
+STR_8066_COPPER_ORE_HOPPER :Vagon za bakrovo rudo
+STR_8067_WATER_TANKER :Vodna cisterna
STR_8068_FRUIT_TRUCK :Vagon za sadje
-STR_8069_RUBBER_TRUCK :Vagon za kavcuk
+STR_8069_RUBBER_TRUCK :Vagon za gumo
STR_806A_SUGAR_TRUCK :Vagon za sladkor
STR_806B_COTTON_CANDY_HOPPER :Vagon za sladkorno peno
STR_806C_TOFFEE_HOPPER :Vagon za karamelo
-STR_806D_BUBBLE_VAN :Vagon za mehurcke
-STR_806E_COLA_TANKER :Tank za cockto
-STR_806F_CANDY_VAN :Vagon za slascice
-STR_8070_TOY_VAN :Vagon za igrace
+STR_806D_BUBBLE_VAN :Vagon za mehurčke
+STR_806E_COLA_TANKER :Cisterna za Cockto
+STR_806F_CANDY_VAN :Vagon za slaščice
+STR_8070_TOY_VAN :Vagon za igrače
STR_8071_BATTERY_TRUCK :Tovornjak za baterije
-STR_8072_FIZZY_DRINK_TRUCK :Tovornjak za gazirane pijace
+STR_8072_FIZZY_DRINK_TRUCK :Tovornjak za gazirane pijače
STR_8073_PLASTIC_TRUCK :Tovornjak za plastiko
-STR_807B_BALOGH_COAL_TRUCK :Balogh kamion premoga
-STR_807C_UHL_COAL_TRUCK :Uhl kamion premoga
-STR_807D_DW_COAL_TRUCK :DW kamion premoga
-STR_8084_WITCOMBE_OIL_TANKER :Witcombe naftni tanker
-STR_8085_FOSTER_OIL_TANKER :Foster naftni tanker
-STR_8086_PERRY_OIL_TANKER :Perry naftni tanker
-STR_808A_BALOGH_GOODS_TRUCK :Balogh kamion blaga
-STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead kamion blaga
-STR_808C_GOSS_GOODS_TRUCK :Goss kamion blaga
-STR_808D_HEREFORD_GRAIN_TRUCK :Hereford kamion zita
-STR_808E_THOMAS_GRAIN_TRUCK :Thomas kamion zita
-STR_808F_GOSS_GRAIN_TRUCK :Goss kamion zita
-STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe kamion lesa
-STR_8091_FOSTER_WOOD_TRUCK :Fooster kamion lesa
-STR_8092_MORELAND_WOOD_TRUCK :Moreland kamion lesa
-STR_8093_MPS_IRON_ORE_TRUCK :MPS kamion zelezne rude
-STR_8094_UHL_IRON_ORE_TRUCK :Uhl kamion zelezne rude
-STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy kamion zelezne rude
-STR_8096_BALOGH_STEEL_TRUCK :Balogh kamion jekla
-STR_8097_UHL_STEEL_TRUCK :Uhl kamion jekla
-STR_8098_KELLING_STEEL_TRUCK :Kelling kamion jekla
-STR_8099_BALOGH_ARMORED_TRUCK :Balogh oklepni kamion
-STR_809A_UHL_ARMORED_TRUCK :Uhl oklepni kamion
-STR_809B_FOSTER_ARMORED_TRUCK :Foster oklepni kamion
-STR_809C_FOSTER_FOOD_VAN :Foster kamion živil
-STR_809D_PERRY_FOOD_VAN :Perry kamion živil
-STR_809E_CHIPPY_FOOD_VAN :Chippy kamion živil
-STR_809F_UHL_PAPER_TRUCK :Uhl kamion papirja
-STR_80A0_BALOGH_PAPER_TRUCK :Balogh kamion papirja
-STR_80A1_MPS_PAPER_TRUCK :MPS kamion papirja
-STR_80A2_MPS_COPPER_ORE_TRUCK :MPS kamion bakrove rude
-STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl kamion bakrove rude
-STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss kamion bakrove rude
-STR_80A5_UHL_WATER_TANKER :Uhl tanker mineralne vode
-STR_80A6_BALOGH_WATER_TANKER :Balogh tanker mineralne vode
-STR_80A7_MPS_WATER_TANKER :MPS tanker mineralne vode
-STR_80A8_BALOGH_FRUIT_TRUCK :Balogh kamion sadja
-STR_80A9_UHL_FRUIT_TRUCK :Uhl kamion sadja
-STR_80AA_KELLING_FRUIT_TRUCK :Kelling kamion sadja
-STR_80AB_BALOGH_RUBBER_TRUCK :Balogh kamion kavcuka
-STR_80AC_UHL_RUBBER_TRUCK :Uhl kamion kavcuka
-STR_80AD_RMT_RUBBER_TRUCK :RMT kamion kavcuka
-STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover kamion sladkorja
-STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught kamion sladkorja
-STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow kamion sladkorja
-STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover kamion Cockte
-STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught kamion Cockte
-STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow kamion Cockte
+STR_8074_MPS_REGAL_BUS :MPS regionalni avtobus
+STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard avtobus
+STR_8076_FOSTER_BUS :Foster avtobus
+STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus
+STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI avtobus
+STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII avtobus
+STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII avtobus
+STR_807B_BALOGH_COAL_TRUCK :Balogh tovornjak za premog
+STR_807C_UHL_COAL_TRUCK :Uhl tovornjak za premog
+STR_807D_DW_COAL_TRUCK :DW tovornjak za premog
+STR_807E_MPS_MAIL_TRUCK :MPS tovornjak za pošto
+STR_807F_REYNARD_MAIL_TRUCK :Reynard tovornjak za pošto
+STR_8080_PERRY_MAIL_TRUCK :Perry tovornjak za pošto
+STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover tovornjak za pošto
+STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught tovornjak za pošto
+STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow tovornjak za pošto
+STR_8084_WITCOMBE_OIL_TANKER :Witcombe cisterna za nafto
+STR_8085_FOSTER_OIL_TANKER :Foster cisterna za nafto
+STR_8086_PERRY_OIL_TANKER :Perry cisterna za nafto
+STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott tovornjak za živino
+STR_8088_UHL_LIVESTOCK_VAN :Uhl tovornjak za živino
+STR_8089_FOSTER_LIVESTOCK_VAN :Foster tovornjak za živino
+STR_808A_BALOGH_GOODS_TRUCK :Balogh tovornjak za dobrine
+STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead tovornjak za dobrine
+STR_808C_GOSS_GOODS_TRUCK :Goss tovornjak za dobrine
+STR_808D_HEREFORD_GRAIN_TRUCK :Hereford tovornjak za žito
+STR_808E_THOMAS_GRAIN_TRUCK :Thomas tovornjak za žito
+STR_808F_GOSS_GRAIN_TRUCK :Goss tovornjak za žito
+STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe tovornjak za les
+STR_8091_FOSTER_WOOD_TRUCK :Fooster tovornjak za les
+STR_8092_MORELAND_WOOD_TRUCK :Moreland tovornjak za les
+STR_8093_MPS_IRON_ORE_TRUCK :MPS tovornjak za železovo rudo
+STR_8094_UHL_IRON_ORE_TRUCK :Uhl tovornjak za železovo rudo
+STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy tovornjak za železovo rudo
+STR_8096_BALOGH_STEEL_TRUCK :Balogh tovornjak za jeklo
+STR_8097_UHL_STEEL_TRUCK :Uhl tovornjak za jeklo
+STR_8098_KELLING_STEEL_TRUCK :Kelling tovornjak za jeklo
+STR_8099_BALOGH_ARMORED_TRUCK :Balogh oklepni tovornjak
+STR_809A_UHL_ARMORED_TRUCK :Uhl oklepni tovornjak
+STR_809B_FOSTER_ARMORED_TRUCK :Foster oklepni tovornjak
+STR_809C_FOSTER_FOOD_VAN :Foster tovornjak za živila
+STR_809D_PERRY_FOOD_VAN :Perry tovornjak za živila
+STR_809E_CHIPPY_FOOD_VAN :Chippy tovornjak za živila
+STR_809F_UHL_PAPER_TRUCK :Uhl tovornjak za papir
+STR_80A0_BALOGH_PAPER_TRUCK :Balogh tovornjak za papir
+STR_80A1_MPS_PAPER_TRUCK :MPS tovornjak za papir
+STR_80A2_MPS_COPPER_ORE_TRUCK :MPS tovornjak za bakrovo rudo
+STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl tovornjak za bakrovo rudo
+STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss tovornjak za bakrovo rudo
+STR_80A5_UHL_WATER_TANKER :Uhl cisterna za vodo
+STR_80A6_BALOGH_WATER_TANKER :Balogh cisterna za vodo
+STR_80A7_MPS_WATER_TANKER :MPS cisterna za vodo
+STR_80A8_BALOGH_FRUIT_TRUCK :Balogh tovornjak za sadje
+STR_80A9_UHL_FRUIT_TRUCK :Uhl tovornjak za sadje
+STR_80AA_KELLING_FRUIT_TRUCK :Kelling tovornjak za sadje
+STR_80AB_BALOGH_RUBBER_TRUCK :Balogh tovornjak za gumo
+STR_80AC_UHL_RUBBER_TRUCK :Uhl tovornjak za gumo
+STR_80AD_RMT_RUBBER_TRUCK :RMT tovornjak za gumo
+STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover tovornjak za sladkor
+STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught tovornjak za sladkor
+STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow tovornjak za sladkor
+STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover cisterna za Cockto
+STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught cisterna za Cockto
+STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow cisterna za Cockto
+STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover tovornjak za sladkorno peno
+STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught tovornjak za sladkorno peno
+STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow tovornjak za sladkorno peno
+STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover tovornjak za toffee
+STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught tovornjak za toffee
+STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow tovornjak za toffee
+STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover tovornjak za igrače
+STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught tovornjak za igrače
+STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow tovornjak za igrače
+STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover tovornjak za sladkarije
+STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught tovornjak za sladkarije
+STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow tovornjak za sladkarije
+STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover tovornjak za baterije
+STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught tovornjak za baterije
+STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow tovornjak za baterije
+STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover tovornjak za gazirane pijače
+STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught tovornjak za gazirane pijače
+STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow tovornjak za gazirane pijače
+STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover tovornjak za plastiko
+STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught tovornjak za plastiko
+STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow tovornjak za plastiko
+STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover tovornjak za mehurčke
+STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught tovornjak za mehurčke
+STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow tovornjak za mehurčke
STR_80CC_MPS_OIL_TANKER :MPS naftni tanker
STR_80CD_CS_INC_OIL_TANKER :CS-Inc. naftni tanker
-STR_80CE_MPS_PASSENGER_FERRY :MPS potniski trajekt
-STR_80CF_FFP_PASSENGER_FERRY :FFP potniski trajekt
+STR_80CE_MPS_PASSENGER_FERRY :MPS potniški trajekt
+STR_80CF_FFP_PASSENGER_FERRY :FFP potniški trajekt
STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Hovercraft
-STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug potniski trajekt
-STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake potniski trajekt
+STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug potniški trajekt
+STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake potniški trajekt
STR_80D3_YATE_CARGO_SHIP :Yate tovorna ladja
STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell tovorna ladja
STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover tovorna ladja
@@ -1544,118 +1935,336 @@
STR_80FD_TRICARIO_HELICOPTER :Tricario helikopter
STR_80FE_GURU_X2_HELICOPTER :Guru X2 helikopter
STR_80FF_POWERNAUT_HELICOPTER :Powernaut helikopter
-STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE :{WHITE}Sporocilo od proizvajalca vozila
-STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Pravkar smo izdelali novi {STRING} - ali te zanima enoletna ekskluzivna pravica do uporabe tega vozila, preden ga ponudimo na trgu?
-STR_8102_RAILROAD_LOCOMOTIVE :lokomotiva
+STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE :{WHITE}Sporočilo od proizvajalca vozila
+STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Pravkar smo izdelali novi {STRING} - ali vas zanima enoletna ekskluzivna pravica do uporabe tega vozila, preden ga ponudimo na trgu?
+STR_8102_RAILROAD_LOCOMOTIVE :železniška lokomotiva
STR_8103_ROAD_VEHICLE :cestno vozilo
STR_8104_AIRCRAFT :letalo
STR_8105_SHIP :ladja
-STR_8106_MONORAIL_LOCOMOTIVE :enotirni vlak
-STR_8107_MAGLEV_LOCOMOTIVE :magnetni vlak
+STR_8106_MONORAIL_LOCOMOTIVE :enotirna lokomotiva
+STR_8107_MAGLEV_LOCOMOTIVE :magnetna lokomotiva
##id 0x8800
-STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Zelezniska garaza
-STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Prebivalci praznujejo . . .{}Prvi vlak je pripeljal v {STATION}!
+STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Železniška garaža
+STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Prebivalci praznujejo . . .{}Prvi vlak je pripeljal na postajo {STATION}!
STR_8802_DETAILS :{WHITE}{STRING} (Podrobnosti)
STR_8803_TRAIN_IN_THE_WAY :{WHITE}Vlak na poti
STR_8804 :{SETX 10}{COMMA}: {STRING}
STR_8805 :{RIGHTARROW}{SETX 10}{COMMA}: {STRING}
-STR_8806_GO_TO :Pojdi do {STATION}
-STR_8807_GO_TO_TRANSFER :Pojdi do {STATION} (Prenesi in vzemi tovor)
-STR_8808_GO_TO_UNLOAD :Pojdi do {STATION} (Raztovori)
-STR_8809_GO_TO_TRANSFER_UNLOAD :Pojdi do {STATION} (Prenesi in pusti prazno)
-STR_880A_GO_TO_LOAD :Pojdi do {STATION} (Nalozi)
-STR_880B_GO_TO_TRANSFER_LOAD :Pojdi do {STATION} (Prenesi in pocakaj na polno nalozitev)
-STR_880C_GO_NON_STOP_TO :Pojdi brez postanka do {STATION}
-STR_880D_GO_TO_NON_STOP_TRANSFER :Pojdi brez postanka do {STATION} (Prenesi in vzemi tovor)
-STR_880E_GO_NON_STOP_TO_UNLOAD :Pojdi brez postanka do {STATION} (Raztovori)
-STR_880F_GO_TO_NON_STOP_TRANSFER_UNLOAD :Pojdi brez postanka do {STATION} (Prenesi in pusti prazno)
-STR_8810_GO_NON_STOP_TO_LOAD :Pojdi brez postanka do {STATION} (Nalozi)
-STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Pojdi brez postanka do {TOWN} zelezniske garaze
+STR_8806_GO_TO :Pojdi do postaje {STATION}
+STR_8807_GO_TO_TRANSFER :Pojdi do postaje {STATION} (Prenesi in vzemi tovor)
+STR_8808_GO_TO_UNLOAD :Pojdi do postaje {STATION} (Raztovori)
+STR_8809_GO_TO_TRANSFER_UNLOAD :Pojdi do postaje {STATION} (Prenesi in pusti prazno)
+STR_880A_GO_TO_LOAD :Pojdi do postaje {STATION} (Naloži)
+STR_880B_GO_TO_TRANSFER_LOAD :Pojdi do postaje {STATION} (Prenesi in počakaj na polno breme)
+STR_880C_GO_NON_STOP_TO :Pojdi brez postanka do postaje {STATION}
+STR_880D_GO_TO_NON_STOP_TRANSFER :Pojdi brez postanka do postaje {STATION} (Prenesi in vzemi tovor)
+STR_880E_GO_NON_STOP_TO_UNLOAD :Pojdi brez postanka do postaje {STATION} (Raztovori)
+STR_880F_GO_TO_NON_STOP_TRANSFER_UNLOAD :Pojdi brez postanka do postaje {STATION} (Prenesi in pusti prazno)
+STR_8810_GO_NON_STOP_TO_LOAD :Pojdi brez postanka do postaje {STATION} (Nalozi)
+STR_8811_GO_TO_NON_STOP_TRANSFER_LOAD :Pojdi brez postanka do postaje {STATION} (Prenesi in počakaj na polno breme)
+STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Pojdi brez postanka do garaže {TOWN}
STR_UNKNOWN_DESTINATION :neznana lokacija
STR_8812_EMPTY :{LTBLUE}Prazen
-STR_8813_FROM :{LTBLUE}{CARGO} iz {STATION}
-STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Vlak {COMMA} caka v garazi
+STR_8813_FROM :Tovor {LTBLUE}{CARGO} iz postaje {STATION}
+STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Vlak {COMMA} čaka v garaži
STR_8815_NEW_VEHICLES :{BLACK}Nova vozila
STR_8816 :{BLACK}-
STR_8819_TRAIN_TOO_LONG :{WHITE}Vlak je predolg
-STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nova zelezniska vozila
-STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nov enotirni vlak
-STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nov magnetni vlak
+STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Vlaki so lahko spremenjeni šele, ko stojijo v garaži
+
+STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nova železniška vozila
+STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nova enotirna vozila
+STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nova magnetna vozila
+STR_ALL_AVAIL_RAIL_VEHICLES :{WHITE}Železniška vozila
+
STR_881F_BUILD_VEHICLE :{BLACK}Zgradi vozilo
+STR_CLONE_ROAD_VEHICLE :{BLACK}Kloniraj vozilo
+STR_CLONE_ROAD_VEHICLE_INFO :{BLACK}To bo zgradilo kopijo vozila. CTRL+klik skopira tudi navodila
+STR_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}To bo zgradilo kopijo vozila. Kliknite na ta gumb in nato na vozilo v ali zunaj garaže. CTRL+klik skopira tudi navodila
+STR_CLONE_TRAIN :{BLACK}Kloniraj vlak
+STR_CLONE_TRAIN_INFO :{BLACK}To bo zgradilo kopijo vlaka vključno z vsemi vagoni. CTRL+klik skopira tudi navodila
+STR_CLONE_TRAIN_DEPOT_INFO :{BLACK}To bo zgradilo kopijo vlaka vključno z vsemi vagoni. Kliknite na ta gumb in nato na vlak v ali zunaj garaže. CTRL+klik skopira tudi navodila
STR_8820_RENAME :{BLACK}Preimenuj
-STR_8823_SKIP :{BLACK}Preskoci
-STR_8824_DELETE :{BLACK}Izbrisi
+STR_8823_SKIP :{BLACK}Preskoči
+STR_8824_DELETE :{BLACK}Izbriši
STR_8825_NON_STOP :{BLACK}Brez prestanka
STR_8826_GO_TO :{BLACK}Pojdi do
-STR_8827_FULL_LOAD :{BLACK}Polno natovorjenje
+STR_8827_FULL_LOAD :{BLACK}Naloži polno
STR_8828_UNLOAD :{BLACK}Raztovori
STR_8829_ORDERS :{WHITE}{VEHICLE} (Navodila)
STR_882A_END_OF_ORDERS :{SETX 10}- - Konec navodil - -
-STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Ne mores kupiti vozila...
+STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Ni mogoče kupiti vozila ...
STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Zgrajen: {LTBLUE}{NUM}{BLACK} Vrednost: {LTBLUE}{CURRENCY}
STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Vrednost: {LTBLUE}{CURRENCY}
STR_882E :{WHITE}{VEHICLE}
-STR_882F_LOADING_UNLOADING :{LTBLUE}Natovorjenje / Raztovorjenje
-STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Vlaka ne mores poslati v garazo...
-STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Ni vec prostora za ukaze
-STR_8832_TOO_MANY_ORDERS :{WHITE}Prevec ukazov
-STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Ni mozno vstaviti nov ukaz...
-STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Ni mozno izbrisati ta ukaz...
-STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Ni mozno spreminjati ta ukaz
-STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Ni mozno premakniti vozilo...
-STR_8838_N_A :Ni razpolozljiv{SKIP}
-STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Vlaka ne mores prodati...
-STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vlaki - klikni na vlak za informacije
-STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Obrni smer vlakov
-STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Pokazi podrobnosti vlaka
-STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Zvisaj cas med servisirjanji
-STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Zmanjsaj cas med servisirjanji
-STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Pokazi podrobnosti vagonov na vlaku
-STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Pokazi podrobnosti o vagonih
-STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nov {STRING} je zdaj navoljo!
+STR_882F_LOADING_UNLOADING :{LTBLUE}Natovarjanje / Raztovarjanje
+STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Vlaka ni mogoče poslati v garažo ...
+STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Ni več prostora za navodila
+STR_8832_TOO_MANY_ORDERS :{WHITE}Preveč navodil
+STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Ni moogče vstaviti nov ukaz ...
+STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Ni mogoče izbrisati ukaza ...
+STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Ni mogoče spreminjati ukaza ...
+STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Ni mogoče premakniti vozila ...
+STR_8838_N_A :Ni na voljo{SKIP}
+STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Vlaka ni mogoče prodati ...
+STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Ni mogoče najti poti do najbližje garaže
+STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Ni mogoče ustaviti/zagnati vlaka ...
+STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Interval servisiranja: {LTBLUE}{COMMA}dni{BLACK} Zadnji servis: {LTBLUE}{DATE_LONG}
+STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vlaki - kliknite na vlak za informacije
+STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Zgradi nove vlake (zahteva železniško garažo)
+STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vlaki - kliknite na vlak za informacije, povlecite vozilo za dodajanje/odstranjevanje iz vlaka
+STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Zgradi novo železniško vozilo
+STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Povlecite železniško vozilo sem, če ga želite prodati
+STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Pogled na železniško garažo
+STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Seznam železniških vozil - kliknite na vozilo za informacije
+STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Zgradi izbrano železniško vozilo
+STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Preimenuj železniško vozilo
+STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Trenutno železniško vozilo - kliknite sem za izklop/zagon vozila
+STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Pokaži navodila železniškega vozila
+STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Pogled na železniško vozilo
+STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Pošlji vlak v železniško garažo. CTRL+klik samo na servis
+STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Prisili vlak, naj nadaljuje brez čakanja semaforjev
+STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Obrni smer vlaka
+STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Pokaži podrobnosti vlaka
+STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Podaljšaj čas med servisi
+STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Skrajšaj čas med servisi
+STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Pokaži podrobnosti tovora na vlaku
+STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Pokaži podrobnosti o vagonih
+STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Prikaži kapacitete vsakega vagona
+STR_8852_SHOW_TOTAL_CARGO :{BLACK}Prikaži polno kapaciteto vlaka, razdeli glede na tip tovora
+STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Seznam navodil - kliknite na ukaz, da ga izberete. CTRL+klik prikaže postajo
+STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Preskoči trenuten ukaz in izvrši naslednjega
+STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Zbriši izbran ukaz
+STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Označi izbran ukaz kot brez-postanka
+STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Vstavi nov ukaz pred izbranega ali pa ga dodaj na koncu seznama
+STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Označi izbran ukaz, naj vozilo čaka na polno obremenitev
+STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Označi izbran ukaz, naj se vozilo v celoti raztovori
+STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nov {STRING} je sedaj na voljo!
STR_885A :{BLACK}{BIGFONT}{STRING}
STR_885C_BROKEN_DOWN :{RED}Pokvarjen
+STR_885D_AGE_RUNNING_COST_YR :{BLACK}Starost: {LTBLUE}{STRING}{BLACK} Stroški obratovanja: {LTBLUE}{CURRENCY}/leto
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Teza: {LTBLUE}{WEIGHT_S} {BLACK}Moc: {LTBLUE}{POWER}{BLACK} Max. hitrost: {LTBLUE}{VELOCITY}
-STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Letosnji profit: {LTBLUE}{CURRENCY} (lansko leto: {CURRENCY})
-STR_8861_STOPPED :{RED}Ustavljen
+STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Letošnji profit: {LTBLUE}{CURRENCY} (lansko leto: {CURRENCY})
+STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Zanseljivost: {LTBLUE}{COMMA}% {BLACK}Št. okvar od zadnjega servisa: {LTBLUE}{COMMA}
+STR_8861_STOPPED :{RED}Ustavljeno
+STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Ni mogoče, da vlak v nevarnosti pelje mimo semaforjev ...
+STR_8863_CRASHED :{RED}Nesreča!
STR_8865_NAME_TRAIN :{WHITE}Poimenuj vlak
-STR_8866_CAN_T_NAME_TRAIN :{WHITE}Ni mozno poimenovati vlaka
+STR_8866_CAN_T_NAME_TRAIN :{WHITE}Ni mogoče poimenovati vlaka ...
STR_8867_NAME_TRAIN :{BLACK}Poimenuj vlak
-STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Ni mozno spremeniti smeri vlaka...
-STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Preimenuj tip vozila
+STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Železniška nesreča!{}{COMMA} je umrlo v plamenih ob trku
+STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Ni mogoče spremeniti smeri vlaka ...
+STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Preimenuj železniško vozilo
+STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Ni mogoče preimenovati železniškega vozila ...
+STR_886D_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Nastavi ukaz, naj prisili vozilo, da se raztovori
+STR_886F_TRANSFER :{BLACK}Prenos
STR_TRAIN_STOPPING :{RED}Ustavljam
STR_TRAIN_STOPPING_VEL :{RED}Ustavljam, {VELOCITY}
##id 0x9000
STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Cestno vozilo na poti
+STR_9001_ROAD_VEHICLES :{WHITE}{COMPANY} - {COMMA} Cestna vozila
STR_9002 :{WHITE}{VEHICLE}
-STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nova vozila
+STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Garaža za cestna vozila
+STR_9004_NEW_VEHICLES :{BLACK}Nova vozila
+STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nova cestna vozila
STR_9007_BUILD_VEHICLE :{BLACK}Zgradi vozilo
+STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Ni mogoče zgraditi cestnega vozila ...
STR_900C_DETAILS :{WHITE}{VEHICLE} (Podrobnosti)
-STR_900D_AGE_RUNNING_COST_YR :{BLACK}Starost: {LTBLUE}{STRING}{BLACK} Stroski vzdrzevanja: {LTBLUE}{CURRENCY}/ na leto
-STR_900E_MAX_SPEED :{BLACK}Najvecja hitrost: {LTBLUE}{VELOCITY}
-STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Letosnji profit: {LTBLUE}{CURRENCY} (lansko leto: {CURRENCY})
-STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Zgrajent: {LTBLUE}{NUM}{BLACK} Vrednost: {LTBLUE}{CURRENCY}
-STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Ni mozno prodati cestno vozilo...
+STR_900D_AGE_RUNNING_COST_YR :{BLACK}Starost: {LTBLUE}{STRING}{BLACK} Stroški obratovanja: {LTBLUE}{CURRENCY}/leto
+STR_900E_MAX_SPEED :{BLACK}Max. hitrost: {LTBLUE}{VELOCITY}
+STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Letošnji profit: {LTBLUE}{CURRENCY} (lansko leto: {CURRENCY})
+STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Zanesljivost: {LTBLUE}{COMMA}% {BLACK}Št. okvar od zadnjega servisa: {LTBLUE}{COMMA}
+STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Zgrajen: {LTBLUE}{NUM}{BLACK} Vrednost: {LTBLUE}{CURRENCY}
+STR_9012_CAPACITY :{BLACK}Kapaciteta: {LTBLUE}{CARGO}
+STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE} ... mora biti ustavljen v garaži
+STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Ni mogoče prodati cestnega vozila ...
+STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Ni mogoče ustaviti/zagnati cestnega vozila ...
+STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Cestno vozilo {COMMA} čaka v garaži
+STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Ni mogoče poslati vozila v garažo ...
+STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Ni mogoče najti najbližje garaže
+STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Cestna vozila - kliknite na vozilo za informacije
+STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Zgradi nova cestna vozila (zahteva garažo)
+STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Dejanja trenutnega vozila - kliknite za ustavitev/zagon vozila
+STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Pokaži navodila vozila
+STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Pogled na vozilo
+STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Pošlji vozilo v garažo. CTRL+klik samo na servis
+STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Prisili vozilo, da se obrne okoli
+STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Prikaži podrobnosti cestnega vozila
+STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Vozila - kliknite na vozilo za informacije
+STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Zgradi novo cestno vozilo
+STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Povlecite cestno vozilo sem, če ga želite prodati
+STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Pogled na garažo
+STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Seznam cestnih vozil - kliknite na vozilo za informacije
+STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Zgradi izbrano cestno vozilo
+STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Novo cestno vozilo sedaj na voljo!
+STR_9029 :{BLACK}{BIGFONT}{STRING}
+STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Cena: {CURRENCY}{}Hitrost: {VELOCITY}{}Stroški obratovanja: {CURRENCY}/leto{}Kapaciteta: {CARGO}
+STR_902C_NAME_ROAD_VEHICLE :{WHITE}Poimenuj cestno vozilo
+STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Ni mogoče poimenovati cestnega vozila ...
+STR_902E_NAME_ROAD_VEHICLE :{BLACK}Poimenuj cestno vozilo
+STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Prebivalci praznujejo . . .{}Prihod prvega avtobusa na postajo {STATION}!
+STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Prebivalci praznujejo . . .{}Prihod prvega tovornjaka na postajo {STATION}!
+STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Prometna nesreča!{}Voznik umrl v plamenih ob trku z vlakom
+STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Prometna nesreča!{}{COMMA} umrlo v plamenih ob trku z vlakom
+STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Ni mogoče okoli obrniti vozila ...
+STR_9034_RENAME :{BLACK}Preimenuj
+STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Preimenuj cestno vozilo
+STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Preimenuj cestno vozilo
+STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Ni mogoče preimenovati cestnega vozila ...
+STR_9038_GO_TO_ROADVEH_DEPOT :Pojdi v garažo v mestu {TOWN}
##id 0x9800
+STR_9800_DOCK_CONSTRUCTION :Gradnja pomola
+STR_9801_DOCK_CONSTRUCTION :{WHITE}Gradnja pomola
+STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Ni mogoče zgraditi pomola tukaj ...
+STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Ladjedelnica
+STR_9804_NEW_SHIPS :{BLACK}Nove ladje
+STR_9805_SHIPS :{WHITE}{COMPANY} - {COMMA} Ladje
+STR_9808_NEW_SHIPS :{WHITE}Nove ladje
+STR_9809_BUILD_SHIP :{BLACK}Zgradi ladjo
+STR_CLONE_SHIP :{BLACK}Kloniraj ladjo
+STR_CLONE_SHIP_INFO :{BLACK}To bo zgradilo kopijo ladje. CTRL+klik skopira tudi navodila
+STR_CLONE_SHIP_DEPOT_INFO :{BLACK}To bo zgradilo kopijo ladje. Kliknite na ta gumb in nato na ladjo v ali zunaj ladjedelnice. CTRL+klik skopira tudi navodila
+STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Ladja mora biti ustavljena in v ladjedelnici
+STR_980C_CAN_T_SELL_SHIP :{WHITE}Ni mogoče prodati ladje ...
+STR_980D_CAN_T_BUILD_SHIP :{WHITE}Ni mogoče zgraditi ladje ...
+STR_980E_SHIP_IN_THE_WAY :{WHITE}Ladja v napoto
+STR_980F :{WHITE}{VEHICLE}
+STR_9811_DETAILS :{WHITE}{VEHICLE} (Podrobnosti)
+STR_9812_AGE_RUNNING_COST_YR :{BLACK}Starost: {LTBLUE}{STRING}{BLACK} Stroški obratovanja: {LTBLUE}{CURRENCY}/leto
+STR_9813_MAX_SPEED :{BLACK}Max. hitrost: {LTBLUE}{VELOCITY}
+STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit letos: {LTBLUE}{CURRENCY} (lansko leto: {CURRENCY})
+STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Zanesljivost: {LTBLUE}{COMMA}% {BLACK}Št. okvar od zadnjegea servisa: {LTBLUE}{COMMA}
+STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Zgrajen: {LTBLUE}{NUM}{BLACK} Vrednost: {LTBLUE}{CURRENCY}
+STR_9817_CAPACITY :{BLACK}Kapaciteta: {LTBLUE}{CARGO}
+STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Zgradi ladjedelnico (za izgradnjo in servisiranje ladij)
+STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Ladje - kliknite na ladjo za informacije
+STR_9820_BUILD_NEW_SHIP :{BLACK}Zgradi novo ladjo
+STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Povlecite novo ladjo sem, če jo želite prodati
+STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Pogled na ladjedelnico
+STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Ladje - kliknite na ladjo za informacije
+STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Zgradi nove ladje (zahteva ladjedelnico)
+STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Seznam ladij - kliknite na ladjo za informacije
+STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Zgradi izbrano ladjo
+STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Trenutna ladja - kliknite sem za ustavitev/zagon ladje
+STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Prikaži navodila ladje
+STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Pogled na ladjo
+STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Pošlji ladjo v ladjedelnico. CTRL+klik samo na servis
+STR_982B_SHOW_SHIP_DETAILS :{BLACK}Prikaži podrobnosti ladje
+STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nova ladja na voljo!
+STR_982D :{BLACK}{BIGFONT}{STRING}
+STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Cena: {CURRENCY} Max. hitrost: {VELOCITY}{}Kapaciteta: {CARGO}{}Stroški obratovanja: {CURRENCY}/leto
+STR_982F_NAME_SHIP :{BLACK}Poimenuj ladjo
+STR_9831_NAME_SHIP :{WHITE}Poimenuj ladjo
+STR_9832_CAN_T_NAME_SHIP :{WHITE}Ni mogoče poimenovati ladje ...
+STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Prebivalci praznujejo . . .{}Prva ladja prispela na postajo {STATION}!
+STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Postavi bojo, ki je lahko uporabljena kot smerokaz
+STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Ni mogoče postaviti boje tukaj ...
+STR_9836_RENAME :{BLACK}Preimenuj
+STR_9837_RENAME_SHIP_TYPE :{BLACK}Preimenuj ladjo
+STR_9838_RENAME_SHIP_TYPE :{WHITE}Preimenuj ladjo
+STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Ni mogoče preimeonvati ladje ...
+STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Preuredi tovorni prostor tako, da bo ladja lahko sprejela drug tovor
+STR_983B_REFIT :{WHITE}{VEHICLE} (Preuredi)
+STR_983C_REFIT_SHIP :{BLACK}Preuredi ladjo
+STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Izberite tip tovora
+STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED :{BLACK}Preuredi tovorni prostor ladje za izbrani tovor
+STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Izberite tip tovora:
+STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nova kapaciteta: {GOLD}{CARGO}{}{BLACK}Cena za preureditev: {GOLD}{CURRENCY}
+STR_9841_CAN_T_REFIT_SHIP :{WHITE}Ni mogoče preurediti ladje ...
+STR_9842_REFITTABLE :(spremenljivo)
SERVICE_AT_SHIP_DEPOT :Storitev v {TOWN} doku
##id 0xA000
+STR_A000_AIRPORTS :{WHITE}Letališča
+STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Ni mogoče zgraditi letališča tukaj ...
+STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Hangar
+STR_A003_NEW_AIRCRAFT :{BLACK}Novo letalo
+STR_CLONE_AIRCRAFT :{BLACK}Kloniraj letalo
+STR_CLONE_AIRCRAFT_INFO :{BLACK}To bo zgradilo kopijo letala. CTRL+klik skopira tudi navodila
+STR_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}To bo zgradilo kopijo letala. Kliknite na ta gumb in nato na letalo v ali zunaj hangarja. CTRL+klik skopira tudi navodila
+STR_A005_NEW_AIRCRAFT :{WHITE}Novo letalo
+STR_A006_BUILD_AIRCRAFT :{BLACK}Zgradi letalo
+STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Ni mogoče zgraditi letala ...
+STR_A009_AIRCRAFT :{WHITE}{COMPANY} - {COMMA} Letalo
+STR_A00A :{WHITE}{VEHICLE}
+STR_A00B_ORDERS :{WHITE}{VEHICLE} (Navodila)
+STR_A00C_DETAILS :{WHITE}{VEHICLE} (Podrobnosti)
+STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Starost: {LTBLUE}{STRING}{BLACK} Stroški obratovanja: {LTBLUE}{CURRENCY}/leto
+STR_A00E_MAX_SPEED :{BLACK}Max. hitrost: {LTBLUE}{VELOCITY}
+STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit letos: {LTBLUE}{CURRENCY} (lansko leto: {CURRENCY})
+STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Zanesljivost: {LTBLUE}{COMMA}% {BLACK}Št. okvar od zadnjega servisa: {LTBLUE}{COMMA}
+STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Zgrajen: {LTBLUE}{NUM}{BLACK} Vrednost: {LTBLUE}{CURRENCY}
+STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Ni mogoče poslati letala v hangar ...
+STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Letalo {COMMA} čaka v hangarju
+STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Letalo v napoto
+STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Ni mogoče ustaviti/zagnati letala ...
+STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Letalo v letu
+STR_A019_CAPACITY :{BLACK}Kapaciteta: {LTBLUE}{CARGO}, {CARGO}
+STR_A01A_CAPACITY :{BLACK}Kapaciteta: {LTBLUE}{CARGO}
+STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Letalo mora biti ustavljeno v hangarju
+STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Ni mogoče prodati letala ...
+STR_A01D_AIRPORT_CONSTRUCTION :Gradnja letališča
+STR_A01E_BUILD_AIRPORT :{BLACK}Zgradi letališče
+STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Letalo - kliknite na letalo za informacije
+STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Gradnja novega letala (zahteva letališče s hangarjem)
+STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Letalo - kliknite na letalo za informacije
+STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Zgradi novo letalo
+STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Povlecite letalo sem, če ga želite prodati
+STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Pogled na hangar
+STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Seznam letal - kliknite na letalo za informacije
+STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Zgradi izbrano letalo
+STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Trenutno letalo - kliknite sem za ustavitev/zagon letala
+STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Prikaži navodila letala
+STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Pogled na letalo
+STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Pošlji letalo v hangar. CTRL+klik samo na servis
+STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Prikaži podrobnosti letala
+STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Novo letalo na voljo!
+STR_A02D :{BLACK}{BIGFONT}{STRING}
+STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Cena: {CURRENCY} Max. hitrost: {VELOCITY}{}Kapaciteta: {COMMA} potnikov, {COMMA} vreč pošte{}Stroški obratovanja: {CURRENCY}/leto
+STR_A030_NAME_AIRCRAFT :{WHITE}Poimenuj letalo
+STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Ni mogoče poimenovati letala ...
+STR_A032_NAME_AIRCRAFT :{BLACK}Poimenuj letalo
+STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Prebivalci praznujejo . . .{}Prvo letalo pristalo na postaji {STATION}!
+STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Letalska nesreča!{}{COMMA} umrlo v plamenih na letališču {STATION}
+STR_A036 :{TINYFONT}{BLACK}{STATION}
+STR_A037_RENAME :{BLACK}Preimenuj
+STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Preimenuj letalo
+STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Preimenuj letalo
+STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Ni mogoče preimenovati letala ...
+STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Preuredi tovorni prostor letala, da lahko nosi drugačen tovor
+STR_A03C_REFIT :{WHITE}{VEHICLE} (Preuredi)
+STR_A03D_REFIT_AIRCRAFT :{BLACK}Preuredi letalo
+STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Izberite tip tovora
+STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Preuredi letalo, da lahko nosi izbran tovor
+STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Izberite tip tovora:
+STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nova kapaciteta: {GOLD}{STRING}{}{BLACK}Cena za preureditev: {GOLD}{CURRENCY}
+STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Ni mogoče preurediti letala ...
SERVICE_AT_AIRPORT_HANGAR :Storitev v {STATION} Hangarju
##id 0xB000
+STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Nesreča cepelina na postaji {STATION}!
+STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Cestno vozilo uničeno v trku z 'NLP'!
+STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Eksplozija naftne rafinerije blizu mesta {TOWN}!
+STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS :{BLACK}{BIGFONT}Tovarna uničena v sumljivih okoliščinah blizu mesta {TOWN}!
+STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'NLP' pristal blizu mesta {TOWN}!
+STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Rudnik premoga pušča opustošenje v okolici mesta {TOWN}!
+STR_B006_FLOOD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Poplave!{}Vsaj {COMMA} pogrešanih, najverjetneje mrtvih ob močnih neurjih!
+STR_BRIBE_FAILED :{WHITE}Vaša podkupnina je bila
+STR_BRIBE_FAILED_2 :{WHITE}odkrita s strani lokalnih preiskovalcev
+STR_BUILD_DATE :{BLACK}Zgrajeno: {LTBLUE}{DATE_LONG}
SET_PERFORMANCE_DETAIL_INT :{BLACK}{NUM}
############ Those following lines need to be in this order!!
@@ -1663,7 +2272,18 @@
+
+
+
STR_TRAIN :{BLACK}{TRAIN}
+STR_BUS :{BLACK}{BUS}
+
+
+
+
+### depot strings
+
+
@@ -1671,6 +2291,10 @@
STR_WAGONS :Vagoni
+
+
+
+
############ Lists rail types
@@ -1678,6 +2302,17 @@
+########### String for New Landscape Generator
+
+STR_CLEARING_TILES :{BLACK}Generiranje grobih in skalnatih tal
+
+
########### String for new airports
+STR_CITY_AIRPORT :{BLACK}Mestno
+STR_COMMUTER_AIRPORT :{BLACK}Vozač
+
+
+############ Tooltip measurment
+
########
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lang/unfinished/traditional_chinese.txt Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,2 @@
+##name Chinese (Simplified)
+##isocode zh_TW.UTF-8
--- a/main_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/main_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -23,7 +23,7 @@
#include "vehicle.h"
#include "console.h"
#include "sound.h"
-#include "network.h"
+#include "network/network.h"
#include "signs.h"
#include "waypoint.h"
#include "variables.h"
@@ -37,10 +37,10 @@
#include "vehicle_gui.h"
#include "newgrf_config.h"
-#include "network_data.h"
-#include "network_client.h"
-#include "network_server.h"
-#include "network_gui.h"
+#include "network/network_data.h"
+#include "network/network_client.h"
+#include "network/network_server.h"
+#include "network/network_gui.h"
#include "industry.h"
static int _rename_id = 1;
--- a/misc.c Tue Jan 02 18:40:37 2007 +0000
+++ b/misc.c Wed Jan 03 08:32:17 2007 +0000
@@ -24,7 +24,7 @@
#ifndef MERSENNE_TWISTER
#ifdef RANDOM_DEBUG
-#include "network_data.h"
+#include "network/network_data.h"
uint32 DoRandom(int line, const char *file)
#else // RANDOM_DEBUG
uint32 Random(void)
--- a/misc_cmd.c Tue Jan 02 18:40:37 2007 +0000
+++ b/misc_cmd.c Wed Jan 03 08:32:17 2007 +0000
@@ -11,7 +11,7 @@
#include "window.h"
#include "gui.h"
#include "economy.h"
-#include "network.h"
+#include "network/network.h"
#include "variables.h"
#include "livery.h"
--- a/misc_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/misc_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -22,7 +22,7 @@
#include "player.h"
#include "town.h"
#include "sound.h"
-#include "network.h"
+#include "network/network.h"
#include "string.h"
#include "variables.h"
#include "vehicle.h"
--- a/network.c Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1448 +0,0 @@
-/* $Id$ */
-
-#include "stdafx.h"
-#include "network_data.h"
-
-#if defined(WITH_REV)
- extern const char _openttd_revision[];
-#elif defined(WITH_REV_HACK)
- #define WITH_REV
- const char _openttd_revision[] = WITH_REV_HACK;
-#else
- const char _openttd_revision[] = NOREV_STRING;
-#endif
-
-
-#ifdef ENABLE_NETWORK
-
-#include "openttd.h"
-#include "debug.h"
-#include "functions.h"
-#include "string.h"
-#include "strings.h"
-#include "map.h"
-#include "command.h"
-#include "variables.h"
-#include "date.h"
-#include "table/strings.h"
-#include "network_client.h"
-#include "network_server.h"
-#include "network_udp.h"
-#include "network_gamelist.h"
-#include "network_gui.h"
-#include "console.h" /* IConsoleCmdExec */
-#include <stdarg.h> /* va_list */
-#include "md5.h"
-
-#ifdef __MORPHOS__
-// the library base is required here
-struct Library *SocketBase = NULL;
-#endif
-
-// The listen socket for the server
-static SOCKET _listensocket;
-
-// The amount of clients connected
-static byte _network_clients_connected = 0;
-// The index counter for new clients (is never decreased)
-static uint16 _network_client_index = NETWORK_SERVER_INDEX + 1;
-
-/* Some externs / forwards */
-extern void StateGameLoop(void);
-
-// Function that looks up the CI for a given client-index
-NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index)
-{
- NetworkClientInfo *ci;
-
- for (ci = _network_client_info; ci != endof(_network_client_info); ci++) {
- if (ci->client_index == client_index) return ci;
- }
-
- return NULL;
-}
-
-/** Return the CI for a given IP
- * @param ip IP of the client we are looking for. This must be in string-format
- * @return return a pointer to the corresponding NetworkClientInfo struct or NULL on failure */
-NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip)
-{
- NetworkClientInfo *ci;
- uint32 ip_number = inet_addr(ip);
-
- for (ci = _network_client_info; ci != endof(_network_client_info); ci++) {
- if (ci->client_ip == ip_number) return ci;
- }
-
- return NULL;
-}
-
-// Function that looks up the CS for a given client-index
-NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index)
-{
- NetworkClientState *cs;
-
- for (cs = _clients; cs != &_clients[MAX_CLIENT_INFO]; cs++) {
- if (cs->index == client_index) return cs;
- }
-
- return NULL;
-}
-
-// NetworkGetClientName is a server-safe function to get the name of the client
-// if the user did not send it yet, Client #<no> is used.
-void NetworkGetClientName(char *client_name, size_t size, const NetworkClientState *cs)
-{
- const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
-
- if (ci->client_name[0] == '\0') {
- snprintf(client_name, size, "Client #%4d", cs->index);
- } else {
- ttd_strlcpy(client_name, ci->client_name, size);
- }
-}
-
-byte NetworkSpectatorCount(void)
-{
- const NetworkClientState *cs;
- byte count = 0;
-
- FOR_ALL_CLIENTS(cs) {
- if (DEREF_CLIENT_INFO(cs)->client_playas == PLAYER_SPECTATOR) count++;
- }
-
- return count;
-}
-
-// This puts a text-message to the console, or in the future, the chat-box,
-// (to keep it all a bit more general)
-// If 'self_send' is true, this is the client who is sending the message
-void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...)
-{
- char buf[1024];
- va_list va;
- const int duration = 10; // Game days the messages stay visible
- char message[1024];
- char temp[1024];
-
- va_start(va, str);
- vsnprintf(buf, lengthof(buf), str, va);
- va_end(va);
-
- switch (action) {
- case NETWORK_ACTION_SERVER_MESSAGE:
- color = 1;
- snprintf(message, sizeof(message), "*** %s", buf);
- break;
- case NETWORK_ACTION_JOIN:
- color = 1;
- GetString(temp, STR_NETWORK_CLIENT_JOINED, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s", name, temp);
- break;
- case NETWORK_ACTION_LEAVE:
- color = 1;
- GetString(temp, STR_NETWORK_ERR_LEFT, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s (%s)", name, temp, buf);
- break;
- case NETWORK_ACTION_GIVE_MONEY:
- if (self_send) {
- SetDParamStr(0, name);
- SetDParam(1, atoi(buf));
- GetString(temp, STR_NETWORK_GAVE_MONEY_AWAY, lastof(temp));
- snprintf(message, sizeof(message), "*** %s", temp);
- } else {
- SetDParam(0, atoi(buf));
- GetString(temp, STR_NETWORK_GIVE_MONEY, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s", name, temp);
- }
- break;
- case NETWORK_ACTION_NAME_CHANGE:
- GetString(temp, STR_NETWORK_NAME_CHANGE, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s %s", name, temp, buf);
- break;
- case NETWORK_ACTION_CHAT_COMPANY:
- SetDParamStr(0, name);
- SetDParamStr(1, buf);
- GetString(temp, self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY, lastof(temp));
- ttd_strlcpy(message, temp, sizeof(message));
- break;
- case NETWORK_ACTION_CHAT_CLIENT:
- SetDParamStr(0, name);
- SetDParamStr(1, buf);
- GetString(temp, self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT, lastof(temp));
- ttd_strlcpy(message, temp, sizeof(message));
- break;
- default:
- SetDParamStr(0, name);
- SetDParamStr(1, buf);
- GetString(temp, STR_NETWORK_CHAT_ALL, lastof(temp));
- ttd_strlcpy(message, temp, sizeof(message));
- break;
- }
-
- IConsolePrintF(color, "%s", message);
- AddTextMessage(color, duration, "%s", message);
-}
-
-// Calculate the frame-lag of a client
-uint NetworkCalculateLag(const NetworkClientState *cs)
-{
- int lag = cs->last_frame_server - cs->last_frame;
- // This client has missed his ACK packet after 1 DAY_TICKS..
- // so we increase his lag for every frame that passes!
- // The packet can be out by a max of _net_frame_freq
- if (cs->last_frame_server + DAY_TICKS + _network_frame_freq < _frame_counter)
- lag += _frame_counter - (cs->last_frame_server + DAY_TICKS + _network_frame_freq);
-
- return lag;
-}
-
-
-// There was a non-recoverable error, drop back to the main menu with a nice
-// error
-static void NetworkError(StringID error_string)
-{
- _switch_mode = SM_MENU;
- _switch_mode_errorstr = error_string;
-}
-
-static void ClientStartError(const char *error)
-{
- DEBUG(net, 0, "[client] could not start network: %s",error);
- NetworkError(STR_NETWORK_ERR_CLIENT_START);
-}
-
-static void ServerStartError(const char *error)
-{
- DEBUG(net, 0, "[server] could not start network: %s",error);
- NetworkError(STR_NETWORK_ERR_SERVER_START);
-}
-
-static void NetworkClientError(NetworkRecvStatus res, NetworkClientState* cs)
-{
- // First, send a CLIENT_ERROR to the server, so he knows we are
- // disconnection (and why!)
- NetworkErrorCode errorno;
-
- // We just want to close the connection..
- if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
- cs->has_quit = true;
- NetworkCloseClient(cs);
- _networking = false;
-
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
- return;
- }
-
- switch (res) {
- case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
- case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
- default: errorno = NETWORK_ERROR_GENERAL; break;
- }
- // This means we fucked up and the server closed the connection
- if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
- res != NETWORK_RECV_STATUS_SERVER_BANNED) {
- SEND_COMMAND(PACKET_CLIENT_ERROR)(errorno);
-
- // Dequeue all commands before closing the socket
- NetworkSend_Packets(DEREF_CLIENT(0));
- }
-
- _switch_mode = SM_MENU;
- NetworkCloseClient(cs);
- _networking = false;
-}
-
-/** Retrieve a string representation of an internal error number
- * @param buf buffer where the error message will be stored
- * @param err NetworkErrorCode
- * @return returns a pointer to the error message (buf) */
-char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last)
-{
- /* List of possible network errors, used by
- * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
- static const StringID network_error_strings[] = {
- STR_NETWORK_ERR_CLIENT_GENERAL,
- STR_NETWORK_ERR_CLIENT_DESYNC,
- STR_NETWORK_ERR_CLIENT_SAVEGAME,
- STR_NETWORK_ERR_CLIENT_CONNECTION_LOST,
- STR_NETWORK_ERR_CLIENT_PROTOCOL_ERROR,
- STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED,
- STR_NETWORK_ERR_CLIENT_NOT_EXPECTED,
- STR_NETWORK_ERR_CLIENT_WRONG_REVISION,
- STR_NETWORK_ERR_CLIENT_NAME_IN_USE,
- STR_NETWORK_ERR_CLIENT_WRONG_PASSWORD,
- STR_NETWORK_ERR_CLIENT_PLAYER_MISMATCH,
- STR_NETWORK_ERR_CLIENT_KICKED,
- STR_NETWORK_ERR_CLIENT_CHEATER,
- STR_NETWORK_ERR_CLIENT_SERVER_FULL
- };
-
- if (err >= lengthof(network_error_strings)) err = 0;
-
- return GetString(buf, network_error_strings[err], last);
-}
-
-/* Count the number of active clients connected */
-static uint NetworkCountPlayers(void)
-{
- const NetworkClientState *cs;
- uint count = 0;
-
- FOR_ALL_CLIENTS(cs) {
- const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
- if (IsValidPlayer(ci->client_playas)) count++;
- }
-
- return count;
-}
-
-static bool _min_players_paused = false;
-
-/* Check if the minimum number of players has been reached and pause or unpause the game as appropriate */
-void CheckMinPlayers(void)
-{
- if (!_network_dedicated) return;
-
- if (NetworkCountPlayers() < _network_min_players) {
- if (_min_players_paused) return;
-
- _min_players_paused = true;
- DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (not enough players)", NETWORK_SERVER_INDEX);
- } else {
- if (!_min_players_paused) return;
-
- _min_players_paused = false;
- DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", NETWORK_SERVER_INDEX);
- }
-}
-
-// Find all IP-aliases for this host
-static void NetworkFindIPs(void)
-{
- int i;
-
-#if defined(BEOS_NET_SERVER) /* doesn't have neither getifaddrs or net/if.h */
- /* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */
- int _netstat(int fd, char **output, int verbose);
-
- int seek_past_header(char **pos, const char *header) {
- char *new_pos = strstr(*pos, header);
- if (new_pos == 0) {
- return B_ERROR;
- }
- *pos += strlen(header) + new_pos - *pos + 1;
- return B_OK;
- }
-
- int output_length;
- char *output_pointer = NULL;
- char **output;
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
- i = 0;
-
- // If something fails, make sure the list is empty
- _broadcast_list[0] = 0;
-
- if (sock < 0) {
- DEBUG(net, 0, "[core] error creating socket");
- return;
- }
-
- output_length = _netstat(sock, &output_pointer, 1);
- if (output_length < 0) {
- DEBUG(net, 0, "[core] error running _netstat");
- return;
- }
-
- output = &output_pointer;
- if (seek_past_header(output, "IP Interfaces:") == B_OK) {
- for (;;) {
- uint32 n, fields, read;
- uint8 i1, i2, i3, i4, j1, j2, j3, j4;
- struct in_addr inaddr;
- uint32 ip;
- uint32 netmask;
-
- fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n",
- &n, &i1,&i2,&i3,&i4, &j1,&j2,&j3,&j4, &read);
- read += 1;
- if (fields != 9) {
- break;
- }
-
- ip = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4;
- netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4;
-
- if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) {
- inaddr.s_addr = htonl(ip | ~netmask);
- _broadcast_list[i] = inaddr.s_addr;
- i++;
- }
- if (read < 0) {
- break;
- }
- *output += read;
- }
- /* XXX - Using either one of these crashes openttd heavily? - wber */
- /*free(output_pointer);*/
- /*free(output);*/
- closesocket(sock);
- }
-#elif defined(HAVE_GETIFADDRS)
- struct ifaddrs *ifap, *ifa;
-
- // If something fails, make sure the list is empty
- _broadcast_list[0] = 0;
-
- if (getifaddrs(&ifap) != 0)
- return;
-
- i = 0;
- for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
- if (!(ifa->ifa_flags & IFF_BROADCAST)) continue;
- if (ifa->ifa_broadaddr == NULL) continue;
- if (ifa->ifa_broadaddr->sa_family != AF_INET) continue;
- _broadcast_list[i] = ((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr;
- i++;
- }
- freeifaddrs(ifap);
-
-#else /* not HAVE_GETIFADDRS */
- SOCKET sock;
-#ifdef WIN32
- DWORD len = 0;
- INTERFACE_INFO ifo[MAX_INTERFACES];
- uint j;
-#else
- char buf[4 * 1024]; // Arbitrary buffer size
- struct ifconf ifconf;
- const char* buf_end;
- const char* p;
-#endif
-
- // If something fails, make sure the list is empty
- _broadcast_list[0] = 0;
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock == INVALID_SOCKET) return;
-
-#ifdef WIN32
- memset(&ifo[0], 0, sizeof(ifo));
- if ((WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, &ifo[0], sizeof(ifo), &len, NULL, NULL)) != 0) {
- closesocket(sock);
- return;
- }
-
- i = 0;
- for (j = 0; j < len / sizeof(*ifo); j++) {
- if (ifo[j].iiFlags & IFF_LOOPBACK) continue;
- if (!(ifo[j].iiFlags & IFF_BROADCAST)) continue;
- /* iiBroadcast is unusable, because it always seems to be set to
- * 255.255.255.255.
- */
- _broadcast_list[i++] =
- ifo[j].iiAddress.AddressIn.sin_addr.s_addr |
- ~ifo[j].iiNetmask.AddressIn.sin_addr.s_addr;
- }
-#else
- ifconf.ifc_len = sizeof(buf);
- ifconf.ifc_buf = buf;
- if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1) {
- closesocket(sock);
- return;
- }
-
- i = 0;
- buf_end = buf + ifconf.ifc_len;
- for (p = buf; p < buf_end;) {
- const struct ifreq* req = (const struct ifreq*)p;
-
- if (req->ifr_addr.sa_family == AF_INET) {
- struct ifreq r;
-
- strncpy(r.ifr_name, req->ifr_name, lengthof(r.ifr_name));
- if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 &&
- r.ifr_flags & IFF_BROADCAST &&
- ioctl(sock, SIOCGIFBRDADDR, &r) != -1) {
- _broadcast_list[i++] =
- ((struct sockaddr_in*)&r.ifr_broadaddr)->sin_addr.s_addr;
- }
- }
-
- p += sizeof(struct ifreq);
-#ifdef AF_LINK
- p += req->ifr_addr.sa_len - sizeof(struct sockaddr);
-#endif
- }
-#endif
-
- closesocket(sock);
-#endif /* not HAVE_GETIFADDRS */
-
- _broadcast_list[i] = 0;
-
- DEBUG(net, 3, "Detected broadcast addresses:");
- // Now display to the debug all the detected ips
- for (i = 0; _broadcast_list[i] != 0; i++) {
- DEBUG(net, 3, "%d) %s", i, inet_ntoa(*(struct in_addr *)&_broadcast_list[i]));//inet_ntoa(inaddr));
- }
-}
-
-// Resolve a hostname to a inet_addr
-unsigned long NetworkResolveHost(const char *hostname)
-{
- in_addr_t ip;
-
- // First try: is it an ip address?
- ip = inet_addr(hostname);
-
- // If not try to resolve the name
- if (ip == INADDR_NONE) {
- struct hostent *he = gethostbyname(hostname);
- if (he == NULL) {
- DEBUG(net, 0, "Cannot resolve '%s'", hostname);
- } else {
- struct in_addr addr = *(struct in_addr *)he->h_addr_list[0];
- DEBUG(net, 1, "Resolved '%s' to %s", hostname, inet_ntoa(addr));
- ip = addr.s_addr;
- }
- }
- return ip;
-}
-
-// Converts a string to ip/port/player
-// Format: IP#player:port
-//
-// connection_string will be re-terminated to seperate out the hostname, and player and port will
-// be set to the player and port strings given by the user, inside the memory area originally
-// occupied by connection_string.
-void ParseConnectionString(const char **player, const char **port, char *connection_string)
-{
- char *p;
- for (p = connection_string; *p != '\0'; p++) {
- if (*p == '#') {
- *p = '\0';
- *player = ++p;
- while (IsValidChar(*p, CS_NUMERAL)) p++;
- if (*p == '\0') break;
- } else if (*p == ':') {
- *port = p + 1;
- *p = '\0';
- }
- }
-}
-
-// Creates a new client from a socket
-// Used both by the server and the client
-static NetworkClientState *NetworkAllocClient(SOCKET s)
-{
- NetworkClientState *cs;
- byte client_no = 0;
-
- if (_network_server) {
- // Can we handle a new client?
- if (_network_clients_connected >= MAX_CLIENTS) return NULL;
- if (_network_game_info.clients_on >= _network_game_info.clients_max) return NULL;
-
- // Register the login
- client_no = _network_clients_connected++;
- }
-
- cs = DEREF_CLIENT(client_no);
- memset(cs, 0, sizeof(*cs));
- cs->socket = s;
- cs->last_frame = 0;
- cs->has_quit = false;
-
- cs->last_frame = _frame_counter;
- cs->last_frame_server = _frame_counter;
-
- if (_network_server) {
- NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
- memset(ci, 0, sizeof(*ci));
-
- cs->index = _network_client_index++;
- ci->client_index = cs->index;
- ci->client_playas = PLAYER_INACTIVE_CLIENT;
- ci->join_date = _date;
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
- }
-
- return cs;
-}
-
-// Close a connection
-void NetworkCloseClient(NetworkClientState *cs)
-{
- NetworkClientInfo *ci;
- // Socket is already dead
- if (cs->socket == INVALID_SOCKET) {
- cs->has_quit = true;
- return;
- }
-
- DEBUG(net, 1, "Closed client connection %d", cs->index);
-
- if (!cs->has_quit && _network_server && cs->status > STATUS_INACTIVE) {
- // We did not receive a leave message from this client...
- NetworkErrorCode errorno = NETWORK_ERROR_CONNECTION_LOST;
- char str[100];
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkClientState *new_cs;
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- GetNetworkErrorMsg(str, errorno, lastof(str));
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- // Inform other clients of this... strange leaving ;)
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH && cs != new_cs) {
- SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
- }
- }
- }
-
- /* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
- if (cs->status == STATUS_PRE_ACTIVE && _network_pause_on_join) {
- DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
- }
-
- closesocket(cs->socket);
- cs->writable = false;
- cs->has_quit = true;
-
- // Free all pending and partially received packets
- while (cs->packet_queue != NULL) {
- Packet *p = cs->packet_queue->next;
- free(cs->packet_queue);
- cs->packet_queue = p;
- }
- free(cs->packet_recv);
- cs->packet_recv = NULL;
-
- while (cs->command_queue != NULL) {
- CommandPacket *p = cs->command_queue->next;
- free(cs->command_queue);
- cs->command_queue = p;
- }
-
- // Close the gap in the client-list
- ci = DEREF_CLIENT_INFO(cs);
-
- if (_network_server) {
- // We just lost one client :(
- if (cs->status > STATUS_INACTIVE) _network_game_info.clients_on--;
- _network_clients_connected--;
-
- while ((cs + 1) != DEREF_CLIENT(MAX_CLIENTS) && (cs + 1)->socket != INVALID_SOCKET) {
- *cs = *(cs + 1);
- *ci = *(ci + 1);
- cs++;
- ci++;
- }
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
- }
-
- // Reset the status of the last socket
- cs->socket = INVALID_SOCKET;
- cs->status = STATUS_INACTIVE;
- cs->index = NETWORK_EMPTY_INDEX;
- ci->client_index = NETWORK_EMPTY_INDEX;
-
- CheckMinPlayers();
-}
-
-// A client wants to connect to a server
-static bool NetworkConnect(const char *hostname, int port)
-{
- SOCKET s;
- struct sockaddr_in sin;
-
- DEBUG(net, 1, "Connecting to %s %d", hostname, port);
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == INVALID_SOCKET) {
- ClientStartError("socket() failed");
- return false;
- }
-
- if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = NetworkResolveHost(hostname);
- sin.sin_port = htons(port);
- _network_last_host_ip = sin.sin_addr.s_addr;
-
- /* We failed to connect for which reason what so ever */
- if (connect(s, (struct sockaddr*) &sin, sizeof(sin)) != 0) return false;
-
- if (!SetNonBlocking(s)) DEBUG(net, 0, "Setting non-blocking mode failed"); // XXX should this be an error?
-
- // in client mode, only the first client field is used. it's pointing to the server.
- NetworkAllocClient(s);
-
- _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
- ShowJoinStatusWindow();
-
- return true;
-}
-
-// For the server, to accept new clients
-static void NetworkAcceptClients(void)
-{
- struct sockaddr_in sin;
- NetworkClientState *cs;
- uint i;
- bool banned;
-
- // Should never ever happen.. is it possible??
- assert(_listensocket != INVALID_SOCKET);
-
- for (;;) {
- socklen_t sin_len = sizeof(sin);
- SOCKET s = accept(_listensocket, (struct sockaddr*)&sin, &sin_len);
- if (s == INVALID_SOCKET) return;
-
- SetNonBlocking(s); // XXX error handling?
-
- DEBUG(net, 1, "Client connected from %s on frame %d", inet_ntoa(sin.sin_addr), _frame_counter);
-
- SetNoDelay(s); // XXX error handling?
-
- /* Check if the client is banned */
- banned = false;
- for (i = 0; i < lengthof(_network_ban_list); i++) {
- if (_network_ban_list[i] == NULL) continue;
-
- if (sin.sin_addr.s_addr == inet_addr(_network_ban_list[i])) {
- Packet *p = NetworkSend_Init(PACKET_SERVER_BANNED);
-
- DEBUG(net, 1, "Banned ip tried to join (%s), refused", _network_ban_list[i]);
-
- p->buffer[0] = p->size & 0xFF;
- p->buffer[1] = p->size >> 8;
-
- send(s, p->buffer, p->size, 0);
- closesocket(s);
-
- free(p);
-
- banned = true;
- break;
- }
- }
- /* If this client is banned, continue with next client */
- if (banned) continue;
-
- cs = NetworkAllocClient(s);
- if (cs == NULL) {
- // no more clients allowed?
- // Send to the client that we are full!
- Packet *p = NetworkSend_Init(PACKET_SERVER_FULL);
-
- p->buffer[0] = p->size & 0xFF;
- p->buffer[1] = p->size >> 8;
-
- send(s, p->buffer, p->size, 0);
- closesocket(s);
-
- free(p);
-
- continue;
- }
-
- // a new client has connected. We set him at inactive for now
- // maybe he is only requesting server-info. Till he has sent a PACKET_CLIENT_MAP_OK
- // the client stays inactive
- cs->status = STATUS_INACTIVE;
-
- DEREF_CLIENT_INFO(cs)->client_ip = sin.sin_addr.s_addr; // Save the IP of the client
- }
-}
-
-// Set up the listen socket for the server
-static bool NetworkListen(void)
-{
- SOCKET ls;
- struct sockaddr_in sin;
-
- DEBUG(net, 1, "Listening on %s:%d", _network_server_bind_ip_host, _network_server_port);
-
- ls = socket(AF_INET, SOCK_STREAM, 0);
- if (ls == INVALID_SOCKET) {
- ServerStartError("socket() on listen socket failed");
- return false;
- }
-
- { // reuse the socket
- int reuse = 1;
- // The (const char*) cast is needed for windows!!
- if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) == -1) {
- ServerStartError("setsockopt() on listen socket failed");
- return false;
- }
- }
-
- if (!SetNonBlocking(ls)) DEBUG(net, 0, "Setting non-blocking mode failed"); // XXX should this be an error?
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = _network_server_bind_ip;
- sin.sin_port = htons(_network_server_port);
-
- if (bind(ls, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
- ServerStartError("bind() failed");
- return false;
- }
-
- if (listen(ls, 1) != 0) {
- ServerStartError("listen() failed");
- return false;
- }
-
- _listensocket = ls;
-
- return true;
-}
-
-// Close all current connections
-static void NetworkClose(void)
-{
- NetworkClientState *cs;
-
- FOR_ALL_CLIENTS(cs) {
- if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_QUIT)("leaving");
- NetworkSend_Packets(cs);
- }
- NetworkCloseClient(cs);
- }
-
- if (_network_server) {
- // We are a server, also close the listensocket
- closesocket(_listensocket);
- _listensocket = INVALID_SOCKET;
- DEBUG(net, 1, "Closed listener");
- NetworkUDPClose();
- }
-}
-
-// Inits the network (cleans sockets and stuff)
-static void NetworkInitialize(void)
-{
- NetworkClientState *cs;
-
- _local_command_queue = NULL;
-
- // Clean all client-sockets
- memset(_clients, 0, sizeof(_clients));
- for (cs = _clients; cs != &_clients[MAX_CLIENTS]; cs++) {
- cs->socket = INVALID_SOCKET;
- cs->status = STATUS_INACTIVE;
- cs->command_queue = NULL;
- }
-
- // Clean the client_info memory
- memset(&_network_client_info, 0, sizeof(_network_client_info));
- memset(&_network_player_info, 0, sizeof(_network_player_info));
-
- _sync_frame = 0;
- _network_first_time = true;
-
- _network_reconnect = 0;
-
- NetworkUDPInitialize();
-}
-
-// Query a server to fetch his game-info
-// If game_info is true, only the gameinfo is fetched,
-// else only the client_info is fetched
-NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info)
-{
- if (!_network_available) return NULL;
-
- NetworkDisconnect();
-
- if (game_info) return NetworkUDPQueryServer(host, port);
-
- NetworkInitialize();
-
- _network_server = false;
-
- // Try to connect
- _networking = NetworkConnect(host, port);
-
- // We are connected
- if (_networking) {
- SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)();
- } else { // No networking, close everything down again
- NetworkDisconnect();
- }
-
- return NULL;
-}
-
-/* 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)
-{
- if (*b != '\0') {
- NetworkGameList *item;
- const char *port = NULL;
- const char *player = NULL;
- char host[NETWORK_HOSTNAME_LENGTH];
- uint16 rport;
-
- ttd_strlcpy(host, b, lengthof(host));
-
- ttd_strlcpy(_network_default_ip, b, lengthof(_network_default_ip));
- rport = NETWORK_DEFAULT_PORT;
-
- ParseConnectionString(&player, &port, host);
- if (port != NULL) rport = atoi(port);
-
- item = NetworkQueryServer(host, rport, true);
- item->manually = true;
- }
-}
-
-/* Generates the list of manually added hosts from NetworkGameList and
- * dumps them into the array _network_host_list. This array is needed
- * by the function that generates the config file. */
-void NetworkRebuildHostList(void)
-{
- uint i = 0;
- const NetworkGameList *item = _network_game_list;
- while (item != NULL && i != lengthof(_network_host_list)) {
- if (item->manually) {
- free(_network_host_list[i]);
- _network_host_list[i++] = str_fmt("%s:%i", item->info.hostname, item->port);
- }
- item = item->next;
- }
-
- for (; i < lengthof(_network_host_list); i++) {
- free(_network_host_list[i]);
- _network_host_list[i] = NULL;
- }
-}
-
-// Used by clients, to connect to a server
-bool NetworkClientConnectGame(const char *host, uint16 port)
-{
- if (!_network_available) return false;
-
- if (port == 0) return false;
-
- ttd_strlcpy(_network_last_host, host, sizeof(_network_last_host));
- _network_last_port = port;
-
- NetworkDisconnect();
- NetworkUDPClose();
- NetworkInitialize();
-
- // Try to connect
- _networking = NetworkConnect(host, port);
-
- // We are connected
- if (_networking) {
- IConsoleCmdExec("exec scripts/on_client.scr 0");
- NetworkClient_Connected();
- } else {
- // Connecting failed
- NetworkError(STR_NETWORK_ERR_NOCONNECTION);
- }
-
- return _networking;
-}
-
-static void NetworkInitGameInfo(void)
-{
- NetworkClientInfo *ci;
-
- ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
- ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
- ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_rcon_password));
- if (_network_game_info.server_name[0] == '\0')
- snprintf(_network_game_info.server_name, sizeof(_network_game_info.server_name), "Unnamed Server");
-
- ttd_strlcpy(_network_game_info.server_revision, _openttd_revision, sizeof(_network_game_info.server_revision));
-
- // The server is a client too ;)
- if (_network_dedicated) {
- _network_game_info.clients_on = 0;
- _network_game_info.companies_on = 0;
- _network_game_info.dedicated = true;
- } else {
- _network_game_info.clients_on = 1;
- _network_game_info.companies_on = 1;
- _network_game_info.dedicated = false;
- }
-
- _network_game_info.spectators_on = 0;
-
- _network_game_info.game_date = _date;
- _network_game_info.start_date = ConvertYMDToDate(_patches.starting_year, 0, 1);
- _network_game_info.map_width = MapSizeX();
- _network_game_info.map_height = MapSizeY();
- _network_game_info.map_set = _opt.landscape;
-
- _network_game_info.use_password = (_network_server_password[0] != '\0');
-
- // We use _network_client_info[MAX_CLIENT_INFO - 1] to store the server-data in it
- // The index is NETWORK_SERVER_INDEX ( = 1)
- ci = &_network_client_info[MAX_CLIENT_INFO - 1];
- memset(ci, 0, sizeof(*ci));
-
- ci->client_index = NETWORK_SERVER_INDEX;
- ci->client_playas = _network_dedicated ? PLAYER_SPECTATOR : _local_player;
-
- ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
- ttd_strlcpy(ci->unique_id, _network_unique_id, sizeof(ci->unique_id));
-}
-
-bool NetworkServerStart(void)
-{
- if (!_network_available) return false;
-
- /* Call the pre-scripts */
- IConsoleCmdExec("exec scripts/pre_server.scr 0");
- if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
-
- NetworkInitialize();
- if (!NetworkListen()) return false;
-
- // Try to start UDP-server
- _network_udp_server = true;
- _network_udp_server = NetworkUDPListen(&_udp_server_socket, _network_server_bind_ip, _network_server_port, false);
-
- _network_server = true;
- _networking = true;
- _frame_counter = 0;
- _frame_counter_server = 0;
- _frame_counter_max = 0;
- _last_sync_frame = 0;
- _network_own_client_index = NETWORK_SERVER_INDEX;
-
- /* Non-dedicated server will always be player #1 */
- if (!_network_dedicated) _network_playas = 0;
-
- _network_clients_connected = 0;
-
- NetworkInitGameInfo();
-
- // execute server initialization script
- IConsoleCmdExec("exec scripts/on_server.scr 0");
- // if the server is dedicated ... add some other script
- if (_network_dedicated) IConsoleCmdExec("exec scripts/on_dedicated.scr 0");
-
- _min_players_paused = false;
- CheckMinPlayers();
-
- /* Try to register us to the master server */
- _network_last_advertise_frame = 0;
- _network_need_advertise = true;
- NetworkUDPAdvertise();
- return true;
-}
-
-// The server is rebooting...
-// The only difference with NetworkDisconnect, is the packets that is sent
-void NetworkReboot(void)
-{
- if (_network_server) {
- NetworkClientState *cs;
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_NEWGAME)(cs);
- NetworkSend_Packets(cs);
- }
- }
-
- NetworkClose();
-
- // Free all queued commands
- while (_local_command_queue != NULL) {
- CommandPacket *p = _local_command_queue;
- _local_command_queue = _local_command_queue->next;
- free(p);
- }
-
- _networking = false;
- _network_server = false;
-}
-
-// We want to disconnect from the host/clients
-void NetworkDisconnect(void)
-{
- if (_network_server) {
- NetworkClientState *cs;
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_SHUTDOWN)(cs);
- NetworkSend_Packets(cs);
- }
- }
-
- if (_network_advertise) NetworkUDPRemoveAdvertise();
-
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- NetworkClose();
-
- // Free all queued commands
- while (_local_command_queue != NULL) {
- CommandPacket *p = _local_command_queue;
- _local_command_queue = _local_command_queue->next;
- free(p);
- }
-
- _networking = false;
- _network_server = false;
-}
-
-// Receives something from the network
-static bool NetworkReceive(void)
-{
- NetworkClientState *cs;
- int n;
- fd_set read_fd, write_fd;
- struct timeval tv;
-
- FD_ZERO(&read_fd);
- FD_ZERO(&write_fd);
-
- FOR_ALL_CLIENTS(cs) {
- FD_SET(cs->socket, &read_fd);
- FD_SET(cs->socket, &write_fd);
- }
-
- // take care of listener port
- if (_network_server) FD_SET(_listensocket, &read_fd);
-
- tv.tv_sec = tv.tv_usec = 0; // don't block at all.
-#if !defined(__MORPHOS__) && !defined(__AMIGA__)
- n = select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
-#else
- n = WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
-#endif
- if (n == -1 && !_network_server) NetworkError(STR_NETWORK_ERR_LOSTCONNECTION);
-
- // accept clients..
- if (_network_server && FD_ISSET(_listensocket, &read_fd)) NetworkAcceptClients();
-
- // read stuff from clients
- FOR_ALL_CLIENTS(cs) {
- cs->writable = !!FD_ISSET(cs->socket, &write_fd);
- if (FD_ISSET(cs->socket, &read_fd)) {
- if (_network_server) {
- NetworkServer_ReadPackets(cs);
- } else {
- NetworkRecvStatus res;
-
- // The client already was quiting!
- if (cs->has_quit) return false;
-
- res = NetworkClient_ReadPackets(cs);
- if (res != NETWORK_RECV_STATUS_OKAY) {
- // The client made an error of which we can not recover
- // close the client and drop back to main menu
- NetworkClientError(res, cs);
- return false;
- }
- }
- }
- }
- return true;
-}
-
-// This sends all buffered commands (if possible)
-static void NetworkSend(void)
-{
- NetworkClientState *cs;
- FOR_ALL_CLIENTS(cs) {
- if (cs->writable) {
- NetworkSend_Packets(cs);
-
- if (cs->status == STATUS_MAP) {
- // This client is in the middle of a map-send, call the function for that
- SEND_COMMAND(PACKET_SERVER_MAP)(cs);
- }
- }
- }
-}
-
-// Handle the local-command-queue
-static void NetworkHandleLocalQueue(void)
-{
- CommandPacket *cp, **cp_prev;
-
- cp_prev = &_local_command_queue;
-
- while ( (cp = *cp_prev) != NULL) {
-
- // The queue is always in order, which means
- // that the first element will be executed first.
- if (_frame_counter < cp->frame) break;
-
- if (_frame_counter > cp->frame) {
- // If we reach here, it means for whatever reason, we've already executed
- // past the command we need to execute.
- DEBUG(net, 0, "Trying to execute a packet in the past!");
- assert(0);
- }
-
- // We can execute this command
- NetworkExecuteCommand(cp);
-
- *cp_prev = cp->next;
- free(cp);
- }
-
- // Just a safety check, to be removed in the future.
- // Make sure that no older command appears towards the end of the queue
- // In that case we missed executing it. This will never happen.
- for (cp = _local_command_queue; cp; cp = cp->next) {
- assert(_frame_counter < cp->frame);
- }
-
-}
-
-static bool NetworkDoClientLoop(void)
-{
- _frame_counter++;
-
- NetworkHandleLocalQueue();
-
- StateGameLoop();
-
- // Check if we are in sync!
- if (_sync_frame != 0) {
- if (_sync_frame == _frame_counter) {
-#ifdef NETWORK_SEND_DOUBLE_SEED
- if (_sync_seed_1 != _random_seeds[0][0] || _sync_seed_2 != _random_seeds[0][1]) {
-#else
- if (_sync_seed_1 != _random_seeds[0][0]) {
-#endif
- NetworkError(STR_NETWORK_ERR_DESYNC);
- DEBUG(net, 0, "Sync error detected!");
- NetworkClientError(NETWORK_RECV_STATUS_DESYNC, DEREF_CLIENT(0));
- return false;
- }
-
- // If this is the first time we have a sync-frame, we
- // need to let the server know that we are ready and at the same
- // frame as he is.. so we can start playing!
- if (_network_first_time) {
- _network_first_time = false;
- SEND_COMMAND(PACKET_CLIENT_ACK)();
- }
-
- _sync_frame = 0;
- } else if (_sync_frame < _frame_counter) {
- DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
- _sync_frame = 0;
- }
- }
-
- return true;
-}
-
-// We have to do some UDP checking
-void NetworkUDPGameLoop(void)
-{
- if (_network_udp_server) {
- NetworkUDPReceive(_udp_server_socket);
- if (_udp_master_socket != INVALID_SOCKET) {
- NetworkUDPReceive(_udp_master_socket);
- }
- } else if (_udp_client_socket != INVALID_SOCKET) {
- NetworkUDPReceive(_udp_client_socket);
- if (_network_udp_broadcast > 0) _network_udp_broadcast--;
- }
-}
-
-// The main loop called from ttd.c
-// Here we also have to do StateGameLoop if needed!
-void NetworkGameLoop(void)
-{
- if (!_networking) return;
-
- if (!NetworkReceive()) return;
-
- if (_network_server) {
- bool send_frame = false;
-
- // We first increase the _frame_counter
- _frame_counter++;
- // Update max-frame-counter
- if (_frame_counter > _frame_counter_max) {
- _frame_counter_max = _frame_counter + _network_frame_freq;
- send_frame = true;
- }
-
- NetworkHandleLocalQueue();
-
- // Then we make the frame
- StateGameLoop();
-
- _sync_seed_1 = _random_seeds[0][0];
-#ifdef NETWORK_SEND_DOUBLE_SEED
- _sync_seed_2 = _random_seeds[0][1];
-#endif
-
- NetworkServer_Tick(send_frame);
- } else {
- // Client
-
- // Make sure we are at the frame were the server is (quick-frames)
- if (_frame_counter_server > _frame_counter) {
- while (_frame_counter_server > _frame_counter) {
- if (!NetworkDoClientLoop()) break;
- }
- } else {
- // Else, keep on going till _frame_counter_max
- if (_frame_counter_max > _frame_counter) NetworkDoClientLoop();
- }
- }
-
- NetworkSend();
-}
-
-static void NetworkGenerateUniqueId(void)
-{
- md5_state_t state;
- md5_byte_t digest[16];
- char hex_output[16*2 + 1];
- char coding_string[NETWORK_NAME_LENGTH];
- int di;
-
- snprintf(coding_string, sizeof(coding_string), "%d%s", (uint)Random(), "OpenTTD Unique ID");
-
- /* Generate the MD5 hash */
- md5_init(&state);
- md5_append(&state, (const md5_byte_t*)coding_string, strlen(coding_string));
- md5_finish(&state, digest);
-
- for (di = 0; di < 16; ++di)
- sprintf(hex_output + di * 2, "%02x", digest[di]);
-
- /* _network_unique_id is our id */
- snprintf(_network_unique_id, sizeof(_network_unique_id), "%s", hex_output);
-}
-
-// This tries to launch the network for a given OS
-void NetworkStartUp(void)
-{
- DEBUG(net, 3, "[core] starting network...");
-
-#if defined(__MORPHOS__) || defined(__AMIGA__)
- /*
- * IMPORTANT NOTE: SocketBase needs to be initialized before we use _any_
- * network related function, else: crash.
- */
- DEBUG(net, 3, "[core] loading bsd socket library");
- SocketBase = OpenLibrary("bsdsocket.library", 4);
- if (SocketBase == NULL) {
- DEBUG(net, 0, "[core] can't open bsdsocket.library version 4, network unavailable");
- _network_available = false;
- return;
- }
-
-#if defined(__AMIGA__)
- // for usleep() implementation (only required for legacy AmigaOS builds)
- TimerPort = CreateMsgPort();
- if (TimerPort != NULL) {
- TimerRequest = (struct timerequest*)CreateIORequest(TimerPort, sizeof(struct timerequest);
- if (TimerRequest != NULL) {
- if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest*)TimerRequest, 0) == 0) {
- TimerBase = TimerRequest->tr_node.io_Device;
- if (TimerBase == NULL) {
- // free ressources...
- DEBUG(net, 0, "[core] can't initialize timer, network unavailable");
- _network_available = false;
- return;
- }
- }
- }
- }
-#endif // __AMIGA__
-#endif // __MORPHOS__ / __AMIGA__
-
- // Network is available
- _network_available = true;
- _network_dedicated = false;
- _network_last_advertise_frame = 0;
- _network_need_advertise = true;
- _network_advertise_retries = 0;
-
- /* Load the ip from the openttd.cfg */
- _network_server_bind_ip = inet_addr(_network_server_bind_ip_host);
- /* And put the data back in it in case it was an invalid ip */
- snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
-
- /* Generate an unique id when there is none yet */
- if (_network_unique_id[0] == '\0') NetworkGenerateUniqueId();
-
- {
- byte cl_max = _network_game_info.clients_max;
- byte cp_max = _network_game_info.companies_max;
- byte sp_max = _network_game_info.spectators_max;
-
- memset(&_network_game_info, 0, sizeof(_network_game_info));
- _network_game_info.clients_max = cl_max;
- _network_game_info.companies_max = cp_max;
- _network_game_info.spectators_max = sp_max;
- }
-
- // Let's load the network in windows
- #if defined(WIN32)
- {
- WSADATA wsa;
- DEBUG(net, 3, "[core] loading windows socket library");
- if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {
- DEBUG(net, 0, "[core] WSAStartup failed, network unavailable");
- _network_available = false;
- return;
- }
- }
- #endif // WIN32
-
- NetworkInitialize();
- DEBUG(net, 3, "[core] network online, multiplayer available");
- NetworkFindIPs();
-}
-
-// This shuts the network down
-void NetworkShutDown(void)
-{
- NetworkDisconnect();
- NetworkUDPClose();
-
- DEBUG(net, 3, "[core] shutting down network");
-
- _network_available = false;
-
-#if defined(__MORPHOS__) || defined(__AMIGA__)
- // free allocated ressources
-#if defined(__AMIGA__)
- if (TimerBase != NULL) CloseDevice((struct IORequest*)TimerRequest); // XXX This smells wrong
- if (TimerRequest != NULL) DeleteIORequest(TimerRequest);
- if (TimerPort != NULL) DeleteMsgPort(TimerPort);
-#endif
-
- if (SocketBase != NULL) CloseLibrary(SocketBase);
-#endif
-
-#if defined(WIN32)
- WSACleanup();
-#endif
-}
-
-#endif /* ENABLE_NETWORK */
--- a/network.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_H
-#define NETWORK_H
-
-#define NOREV_STRING "norev000"
-
-#ifdef ENABLE_NETWORK
-
-#include "player.h"
-
-// If this line is enable, every frame will have a sync test
-// this is not needed in normal games. Normal is like 1 sync in 100
-// frames. You can enable this if you have a lot of desyncs on a certain
-// game.
-// Remember: both client and server have to be compiled with this
-// option enabled to make it to work. If one of the two has it disabled
-// nothing will happen.
-//#define ENABLE_NETWORK_SYNC_EVERY_FRAME
-
-// In theory sending 1 of the 2 seeds is enough to check for desyncs
-// so in theory, this next define can be left off.
-//#define NETWORK_SEND_DOUBLE_SEED
-
-// How many clients can we have? Like.. MAX_PLAYERS - 1 is the amount of
-// players that can really play.. so.. a max of 4 spectators.. gives us..
-// MAX_PLAYERS + 3
-#define MAX_CLIENTS (MAX_PLAYERS + 3)
-
-
-// Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1
-#define MAX_CLIENT_INFO (MAX_CLIENTS + 1)
-
-/* Stuff for the master-server */
-#define NETWORK_MASTER_SERVER_PORT 3978
-#define NETWORK_MASTER_SERVER_HOST "master.openttd.org"
-#define NETWORK_MASTER_SERVER_WELCOME_MESSAGE "OpenTTDRegister"
-
-#define NETWORK_DEFAULT_PORT 3979
-
-#define MAX_INTERFACES 9
-
-
-// How many vehicle/station types we put over the network
-#define NETWORK_VEHICLE_TYPES 5
-#define NETWORK_STATION_TYPES 5
-
-enum {
- NETWORK_NAME_LENGTH = 80,
- NETWORK_HOSTNAME_LENGTH = 80,
- NETWORK_REVISION_LENGTH = 15,
- NETWORK_PASSWORD_LENGTH = 20,
- NETWORK_PLAYERS_LENGTH = 200,
- NETWORK_CLIENT_NAME_LENGTH = 25,
- NETWORK_RCONCOMMAND_LENGTH = 500,
-
- NETWORK_GRF_NAME_LENGTH = 80, ///< Maximum length of the name of a GRF
- /* Maximum number of GRFs that can be sent.
- * This value is related to number of handles (files) OpenTTD can open.
- * This is currently 64 and about 10 are currently used when OpenTTD loads
- * without any NewGRFs. Therefore one can only load about 55 NewGRFs, so
- * this is not a limit, but rather a way to easily check whether the limit
- * imposed by the handle count is reached. Secondly it isn't possible to
- * send much more GRF IDs + MD5sums in the PACKET_UDP_SERVER_RESPONSE, due
- * to the limited size of UDP packets. */
- NETWORK_MAX_GRF_COUNT = 55,
-
- NETWORK_NUM_LANGUAGES = 4,
-};
-
-// This is the struct used by both client and server
-// some fields will be empty on the client (like game_password) by default
-// and only filled with data a player enters.
-typedef struct NetworkGameInfo {
- char server_name[NETWORK_NAME_LENGTH]; // Server name
- char hostname[NETWORK_HOSTNAME_LENGTH]; // Hostname of the server (if any)
- char server_revision[NETWORK_REVISION_LENGTH]; // The SVN version number the server is using (e.g.: 'r304')
- // It even shows a SVN version in release-version, so
- // it is easy to compare if a server is of the correct version
- bool version_compatible; // Can we connect to this server or not? (based on server_revision)
- bool compatible; // Can we connect to this server or not? (based on server_revision _and_ grf_match
- byte server_lang; // Language of the server (we should make a nice table for this)
- byte use_password; // Is set to != 0 if it uses a password
- char server_password[NETWORK_PASSWORD_LENGTH]; // On the server: the game password, on the client: != "" if server has password
- byte clients_max; // Max clients allowed on server
- byte clients_on; // Current count of clients on server
- byte companies_max; // Max companies allowed on server
- byte companies_on; // How many started companies do we have (XXX - disabled for server atm, use ActivePlayerCount())
- byte spectators_max; // Max spectators allowed on server
- byte spectators_on; // How many spectators do we have? (XXX - disabled for server atm, use NetworkSpectatorCount())
- Date game_date; // Current date
- Date start_date; // When the game started
- char map_name[NETWORK_NAME_LENGTH]; // Map which is played ["random" for a randomized map]
- uint16 map_width; // Map width
- uint16 map_height; // Map height
- byte map_set; // Graphical set
- bool dedicated; // Is this a dedicated server?
- char rcon_password[NETWORK_PASSWORD_LENGTH]; // RCon password for the server. "" if rcon is disabled
- struct GRFConfig *grfconfig; // List of NewGRF files required
-} NetworkGameInfo;
-
-typedef struct NetworkPlayerInfo {
- char company_name[NETWORK_NAME_LENGTH]; // Company name
- char password[NETWORK_PASSWORD_LENGTH]; // The password for the player
- Year inaugurated_year; // What year the company started in
- int64 company_value; // The company value
- int64 money; // The amount of money the company has
- int64 income; // How much did the company earned last year
- uint16 performance; // What was his performance last month?
- byte use_password; // 0: No password 1: There is a password
- uint16 num_vehicle[NETWORK_VEHICLE_TYPES]; // How many vehicles are there of this type?
- uint16 num_station[NETWORK_STATION_TYPES]; // How many stations are there of this type?
- char players[NETWORK_PLAYERS_LENGTH]; // The players that control this company (Name1, name2, ..)
- uint16 months_empty; // How many months the company is empty
-} NetworkPlayerInfo;
-
-typedef struct NetworkClientInfo {
- uint16 client_index; // Index of the client (same as ClientState->index)
- char client_name[NETWORK_CLIENT_NAME_LENGTH]; // Name of the client
- byte client_lang; // The language of the client
- byte client_playas; // As which player is this client playing (PlayerID)
- uint32 client_ip; // IP-address of the client (so he can be banned)
- Date join_date; // Gamedate the player has joined
- char unique_id[NETWORK_NAME_LENGTH]; // Every play sends an unique id so we can indentify him
-} NetworkClientInfo;
-
-typedef struct NetworkGameList {
- NetworkGameInfo info;
- uint32 ip;
- uint16 port;
- bool online; // False if the server did not respond (default status)
- bool manually; // True if the server was added manually
- struct NetworkGameList *next;
-} NetworkGameList;
-
-typedef enum {
- NETWORK_JOIN_STATUS_CONNECTING,
- NETWORK_JOIN_STATUS_AUTHORIZING,
- NETWORK_JOIN_STATUS_WAITING,
- NETWORK_JOIN_STATUS_DOWNLOADING,
- NETWORK_JOIN_STATUS_PROCESSING,
- NETWORK_JOIN_STATUS_REGISTERING,
-
- NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO,
-} NetworkJoinStatus;
-
-// language ids for server_lang and client_lang
-typedef enum {
- NETLANG_ANY = 0,
- NETLANG_ENGLISH = 1,
- NETLANG_GERMAN = 2,
- NETLANG_FRENCH = 3,
-} NetworkLanguage;
-
-VARDEF NetworkGameList *_network_game_list;
-
-VARDEF NetworkGameInfo _network_game_info;
-VARDEF NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
-VARDEF NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
-
-VARDEF char _network_player_name[NETWORK_CLIENT_NAME_LENGTH];
-VARDEF char _network_default_ip[NETWORK_HOSTNAME_LENGTH];
-
-VARDEF uint16 _network_own_client_index;
-VARDEF char _network_unique_id[NETWORK_NAME_LENGTH]; // Our own unique ID
-
-VARDEF uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
-VARDEF uint32 _frame_counter_max; // To where we may go with our clients
-
-VARDEF uint32 _last_sync_frame; // Used in the server to store the last time a sync packet was sent to clients.
-
-// networking settings
-VARDEF uint32 _broadcast_list[MAX_INTERFACES + 1];
-
-VARDEF uint16 _network_server_port;
-/* We use bind_ip and bind_ip_host, where bind_ip_host is the readable form of
- bind_ip_host, and bind_ip the numeric value, because we want a nice number
- in the openttd.cfg, but we wants to use the uint32 internally.. */
-VARDEF uint32 _network_server_bind_ip;
-VARDEF char _network_server_bind_ip_host[NETWORK_HOSTNAME_LENGTH];
-VARDEF bool _is_network_server; // Does this client wants to be a network-server?
-VARDEF char _network_server_name[NETWORK_NAME_LENGTH];
-VARDEF char _network_server_password[NETWORK_PASSWORD_LENGTH];
-VARDEF char _network_rcon_password[NETWORK_PASSWORD_LENGTH];
-
-VARDEF uint16 _network_max_join_time; ///< Time a client can max take to join
-VARDEF bool _network_pause_on_join; ///< Pause the game when a client tries to join (more chance of succeeding join)
-
-VARDEF uint16 _redirect_console_to_client;
-
-VARDEF uint16 _network_sync_freq;
-VARDEF uint8 _network_frame_freq;
-
-VARDEF uint32 _sync_seed_1, _sync_seed_2;
-VARDEF uint32 _sync_frame;
-VARDEF bool _network_first_time;
-// Vars needed for the join-GUI
-VARDEF NetworkJoinStatus _network_join_status;
-VARDEF uint8 _network_join_waiting;
-VARDEF uint16 _network_join_kbytes;
-VARDEF uint16 _network_join_kbytes_total;
-
-VARDEF char _network_last_host[NETWORK_HOSTNAME_LENGTH];
-VARDEF short _network_last_port;
-VARDEF uint32 _network_last_host_ip;
-VARDEF uint8 _network_reconnect;
-
-VARDEF bool _network_udp_server;
-VARDEF uint16 _network_udp_broadcast;
-
-VARDEF byte _network_lan_internet;
-
-VARDEF bool _network_need_advertise;
-VARDEF uint32 _network_last_advertise_frame;
-VARDEF uint8 _network_advertise_retries;
-
-VARDEF bool _network_autoclean_companies;
-VARDEF uint8 _network_autoclean_unprotected; // Remove a company after X months
-VARDEF uint8 _network_autoclean_protected; // Unprotect a company after X months
-
-VARDEF Year _network_restart_game_year; // If this year is reached, the server automaticly restarts
-VARDEF uint8 _network_min_players; // Minimum number of players for game to unpause
-
-NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info);
-
-byte NetworkSpectatorCount(void);
-
-VARDEF char *_network_host_list[10];
-VARDEF char *_network_ban_list[25];
-
-void ParseConnectionString(const char **player, const char **port, char *connection_string);
-void NetworkUpdateClientInfo(uint16 client_index);
-void NetworkAddServer(const char *b);
-void NetworkRebuildHostList(void);
-bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
-void NetworkPopulateCompanyInfo(void);
-void UpdateNetworkGameWindow(bool unselect);
-void CheckMinPlayers(void);
-
-void NetworkStartUp(void);
-void NetworkUDPClose(void);
-void NetworkShutDown(void);
-void NetworkGameLoop(void);
-void NetworkUDPGameLoop(void);
-bool NetworkServerStart(void);
-bool NetworkClientConnectGame(const char *host, uint16 port);
-void NetworkReboot(void);
-void NetworkDisconnect(void);
-
-VARDEF bool _networking; ///< are we in networking mode?
-VARDEF bool _network_server; ///< network-server is active
-VARDEF bool _network_available; ///< is network mode available?
-
-#else /* ENABLE_NETWORK */
-/* Network function stubs when networking is disabled */
-
-static inline void NetworkStartUp(void) {}
-static inline void NetworkShutDown(void) {}
-
-#define _networking 0
-#define _network_server 0
-#define _network_available 0
-
-#endif /* ENABLE_NETWORK */
-
-/* These variables must always be registered! */
-VARDEF bool _network_dedicated; ///< are we a dedicated server?
-VARDEF bool _network_advertise; ///< is the server advertising to the master server?
-VARDEF PlayerID _network_playas; ///< an id to play as.. (see players.h:Players)
-
-#endif /* NETWORK_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/config.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,49 @@
+/* $Id$ */
+
+#ifndef NETWORK_CORE_CONFIG_H
+#define NETWORK_CORE_CONFIG_H
+
+#ifdef ENABLE_NETWORK
+
+/** DNS hostname of the masterserver */
+#define NETWORK_MASTER_SERVER_HOST "master.openttd.org"
+/** Message sent to the masterserver to 'identify' this client as OpenTTD */
+#define NETWORK_MASTER_SERVER_WELCOME_MESSAGE "OpenTTDRegister"
+
+enum {
+ NETWORK_MASTER_SERVER_PORT = 3978, ///< The default port of the master server (UDP)
+ NETWORK_DEFAULT_PORT = 3979, ///< The default port of the game server (TCP & UDP)
+
+ SEND_MTU = 1460, ///< Number of bytes we can pack in a single packet
+
+ NETWORK_GAME_INFO_VERSION = 4, ///< What version of game-info do we use?
+ NETWORK_COMPANY_INFO_VERSION = 4, ///< What version of company info is this?
+ NETWORK_MASTER_SERVER_VERSION = 1, ///< What version of master-server-protocol do we use?
+
+ NETWORK_NAME_LENGTH = 80, ///< The maximum length of the server name and map name, in bytes including '\0'
+ NETWORK_HOSTNAME_LENGTH = 80, ///< The maximum length of the host name, in bytes including '\0'
+ NETWORK_REVISION_LENGTH = 15, ///< The maximum length of the revision, in bytes including '\0'
+ NETWORK_PASSWORD_LENGTH = 20, ///< The maximum length of the password, in bytes including '\0'
+ NETWORK_PLAYERS_LENGTH = 200, ///< The maximum length for the list of players that controls a company, in bytes including '\0'
+ NETWORK_CLIENT_NAME_LENGTH = 25, ///< The maximum length of a player, in bytes including '\0'
+ NETWORK_RCONCOMMAND_LENGTH = 500, ///< The maximum length of a rconsole command, in bytes including '\0'
+
+ NETWORK_GRF_NAME_LENGTH = 80, ///< Maximum length of the name of a GRF
+ /**
+ * Maximum number of GRFs that can be sent.
+ * This value is related to number of handles (files) OpenTTD can open.
+ * This is currently 64 and about 10 are currently used when OpenTTD loads
+ * without any NewGRFs. Therefore one can only load about 55 NewGRFs, so
+ * this is not a limit, but rather a way to easily check whether the limit
+ * imposed by the handle count is reached. Secondly it isn't possible to
+ * send much more GRF IDs + MD5sums in the PACKET_UDP_SERVER_RESPONSE, due
+ * to the limited size of UDP packets.
+ */
+ NETWORK_MAX_GRF_COUNT = 55,
+
+ NETWORK_NUM_LANGUAGES = 4, ///< Number of known languages (to the network protocol) + 1 for 'any'.
+};
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_CORE_CONFIG_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/game.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,47 @@
+/* $Id$ */
+
+#ifndef NETWORK_CORE_GAME_H
+#define NETWORK_CORE_GAME_H
+
+#ifdef ENABLE_NETWORK
+
+/**
+ * @file game.h Information about a game that is sent between a
+ * game server, game client and masterserver.
+ */
+
+/**
+ * This is the struct used by both client and server
+ * some fields will be empty on the client (like game_password) by default
+ * and only filled with data a player enters.
+ */
+typedef struct NetworkGameInfo {
+ byte game_info_version; ///< Version of the game info
+ char server_name[NETWORK_NAME_LENGTH]; ///< Server name
+ char hostname[NETWORK_HOSTNAME_LENGTH]; ///< Hostname of the server (if any)
+ char server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0)
+ bool version_compatible; ///< Can we connect to this server or not? (based on server_revision)
+ bool compatible; ///< Can we connect to this server or not? (based on server_revision _and_ grf_match
+ byte server_lang; ///< Language of the server (we should make a nice table for this)
+ byte use_password; ///< Is set to != 0 if it uses a password
+ char server_password[NETWORK_PASSWORD_LENGTH]; ///< On the server: the game password, on the client: != "" if server has password
+ byte clients_max; ///< Max clients allowed on server
+ byte clients_on; ///< Current count of clients on server
+ byte companies_max; ///< Max companies allowed on server
+ byte companies_on; ///< How many started companies do we have
+ byte spectators_max; ///< Max spectators allowed on server
+ byte spectators_on; ///< How many spectators do we have?
+ Date game_date; ///< Current date
+ Date start_date; ///< When the game started
+ char map_name[NETWORK_NAME_LENGTH]; ///< Map which is played ["random" for a randomized map]
+ uint16 map_width; ///< Map width
+ uint16 map_height; ///< Map height
+ byte map_set; ///< Graphical set
+ bool dedicated; ///< Is this a dedicated server?
+ char rcon_password[NETWORK_PASSWORD_LENGTH]; ///< RCon password for the server. "" if rcon is disabled
+ struct GRFConfig *grfconfig; ///< List of NewGRF files used
+} NetworkGameInfo;
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_CORE_GAME_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/os_abstraction.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,181 @@
+/* $Id$ */
+
+#ifndef NETWORK_CORE_OS_ABSTRACTION_H
+#define NETWORK_CORE_OS_ABSTRACTION_H
+
+/**
+ * @file os_abstraction.h Network stuff has many things that needs to be
+ * included and/or implemented by default.
+ * All those things are in this file.
+ */
+
+/* Include standard stuff per OS */
+
+#ifdef ENABLE_NETWORK
+
+/* Windows stuff */
+#if defined(WIN32) || defined(WIN64)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+
+#if !(defined(__MINGW32__) || defined(__CYGWIN__))
+ /* Windows has some different names for some types */
+ typedef SSIZE_T ssize_t;
+ typedef int socklen_t;
+#endif
+
+#define GET_LAST_ERROR() WSAGetLastError()
+#define EWOULDBLOCK WSAEWOULDBLOCK
+/* Windows has some different names for some types */
+typedef unsigned long in_addr_t;
+#endif /* WIN32 */
+
+/* UNIX stuff */
+#if defined(UNIX)
+# define SOCKET int
+# define INVALID_SOCKET -1
+# if !defined(__MORPHOS__) && !defined(__AMIGA__)
+# define ioctlsocket ioctl
+# if !defined(BEOS_NET_SERVER)
+# define closesocket close
+# endif
+# define GET_LAST_ERROR() (errno)
+# endif
+/* Need this for FIONREAD on solaris */
+# define BSD_COMP
+
+/* Includes needed for UNIX-like systems */
+# include <unistd.h>
+# include <sys/ioctl.h>
+# if defined(__BEOS__) && defined(BEOS_NET_SERVER)
+# include <be/net/socket.h>
+# include <be/kernel/OS.h> // snooze()
+# include <be/net/netdb.h>
+ typedef unsigned long in_addr_t;
+# define INADDR_NONE INADDR_BROADCAST
+# else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <arpa/inet.h>
+# include <net/if.h>
+/* According to glibc/NEWS, <ifaddrs.h> appeared in glibc-2.3. */
+# if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__INNOTEK_LIBC__) \
+ && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__)
+/* If for any reason ifaddrs.h does not exist on your system, comment out
+ * the following two lines and an alternative way will be used to fetch
+ * the list of IPs from the system. */
+# include <ifaddrs.h>
+# define HAVE_GETIFADDRS
+# endif
+# if defined(SUNOS) || defined(__MORPHOS__) || defined(__BEOS__)
+# define INADDR_NONE 0xffffffff
+# endif
+# if defined(__BEOS__) && !defined(BEOS_NET_SERVER)
+ /* needed on Zeta */
+# include <sys/sockio.h>
+# endif
+# endif /* BEOS_NET_SERVER */
+
+# if !defined(__BEOS__) && defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
+ typedef uint32_t in_addr_t;
+# endif
+
+# include <errno.h>
+# include <sys/time.h>
+# include <netdb.h>
+#endif // UNIX
+
+#ifdef __BEOS__
+ typedef int socklen_t;
+#endif
+
+/* OS/2 stuff */
+#if defined(__OS2__)
+# define SOCKET int
+# define INVALID_SOCKET -1
+# define ioctlsocket ioctl
+# define closesocket close
+# define GET_LAST_ERROR() (sock_errno())
+
+/* Includes needed for OS/2 systems */
+# include <types.h>
+# include <unistd.h>
+# include <sys/ioctl.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <arpa/inet.h>
+# include <net/if.h>
+# include <errno.h>
+# include <sys/time.h>
+# include <netdb.h>
+# include <nerrno.h>
+# define INADDR_NONE 0xffffffff
+
+typedef int socklen_t;
+#if !defined(__INNOTEK_LIBC__)
+typedef unsigned long in_addr_t;
+#endif /* __INNOTEK_LIBC__ */
+#endif /* OS/2 */
+
+/* MorphOS and Amiga stuff */
+#if defined(__MORPHOS__) || defined(__AMIGA__)
+# include <exec/types.h>
+# include <proto/exec.h> // required for Open/CloseLibrary()
+# if defined(__MORPHOS__)
+# include <sys/filio.h> // FIO* defines
+# include <sys/sockio.h> // SIO* defines
+# include <netinet/in.h>
+# else /* __AMIGA__ */
+# include <proto/socket.h>
+# endif
+
+/* Make the names compatible */
+# define closesocket(s) CloseSocket(s)
+# define GET_LAST_ERROR() Errno()
+# define ioctlsocket(s,request,status) IoctlSocket((LONG)s,(ULONG)request,(char*)status)
+# define ioctl ioctlsocket
+
+ typedef unsigned int in_addr_t;
+ typedef long socklen_t;
+ extern struct Library *SocketBase;
+
+# ifdef __AMIGA__
+ /* for usleep() implementation */
+ extern struct Device *TimerBase;
+ extern struct MsgPort *TimerPort;
+ extern struct timerequest *TimerRequest;
+# endif
+#endif // __MORPHOS__ || __AMIGA__
+
+static inline bool SetNonBlocking(int d)
+{
+#ifdef WIN32
+ u_long nonblocking = 1;
+#else
+ int nonblocking = 1;
+#endif
+#if defined(__BEOS__) && defined(BEOS_NET_SERVER)
+ return setsockopt(d, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(nonblocking)) == 0;
+#else
+ return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
+#endif
+}
+
+static inline bool SetNoDelay(int d)
+{
+ /* XXX should this be done at all? */
+#if !defined(BEOS_NET_SERVER) // not implemented on BeOS net_server
+ int b = 1;
+ /* The (const char*) cast is needed for windows */
+ return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
+#else
+ return true;
+#endif
+}
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_CORE_OS_ABSTRACTION_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/packet.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,216 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../../stdafx.h"
+#include "../../macros.h"
+#include "../../string.h"
+
+#include "os_abstraction.h"
+#include "config.h"
+#include "packet.h"
+
+/**
+ * @file packet.h Basic functions to create, fill and read packets.
+ */
+
+
+/* Do not want to include functions.h and all required headers */
+extern void NORETURN CDECL error(const char *str, ...);
+
+
+/**
+ * Create a packet for sending
+ * @param type the of packet
+ * @return the newly created packet
+ */
+Packet *NetworkSend_Init(PacketType type)
+{
+ Packet *packet = malloc(sizeof(Packet));
+ /* An error is inplace here, because it simply means we ran out of memory. */
+ if (packet == NULL) error("Failed to allocate Packet");
+
+ /* Skip the size so we can write that in before sending the packet */
+ packet->size = sizeof(packet->size);
+ packet->buffer[packet->size++] = type;
+ packet->pos = 0;
+
+ return packet;
+}
+
+/**
+ * Writes the packet size from the raw packet from packet->size
+ * @param packet the packet to write the size of
+ */
+void NetworkSend_FillPacketSize(Packet *packet)
+{
+ packet->buffer[0] = GB(packet->size, 0, 8);
+ packet->buffer[1] = GB(packet->size, 8, 8);
+}
+
+/**
+ * The next couple of functions make sure we can send
+ * uint8, uint16, uint32 and uint64 endian-safe
+ * over the network. The least significant bytes are
+ * sent first.
+ *
+ * So 0x01234567 would be sent as 67 45 23 01.
+ */
+
+void NetworkSend_uint8(Packet *packet, uint8 data)
+{
+ assert(packet->size < sizeof(packet->buffer) - sizeof(data));
+ packet->buffer[packet->size++] = data;
+}
+
+void NetworkSend_uint16(Packet *packet, uint16 data)
+{
+ assert(packet->size < sizeof(packet->buffer) - sizeof(data));
+ packet->buffer[packet->size++] = GB(data, 0, 8);
+ packet->buffer[packet->size++] = GB(data, 8, 8);
+}
+
+void NetworkSend_uint32(Packet *packet, uint32 data)
+{
+ assert(packet->size < sizeof(packet->buffer) - sizeof(data));
+ packet->buffer[packet->size++] = GB(data, 0, 8);
+ packet->buffer[packet->size++] = GB(data, 8, 8);
+ packet->buffer[packet->size++] = GB(data, 16, 8);
+ packet->buffer[packet->size++] = GB(data, 24, 8);
+}
+
+void NetworkSend_uint64(Packet *packet, uint64 data)
+{
+ assert(packet->size < sizeof(packet->buffer) - sizeof(data));
+ packet->buffer[packet->size++] = GB(data, 0, 8);
+ packet->buffer[packet->size++] = GB(data, 8, 8);
+ packet->buffer[packet->size++] = GB(data, 16, 8);
+ packet->buffer[packet->size++] = GB(data, 24, 8);
+ packet->buffer[packet->size++] = GB(data, 32, 8);
+ packet->buffer[packet->size++] = GB(data, 40, 8);
+ packet->buffer[packet->size++] = GB(data, 48, 8);
+ packet->buffer[packet->size++] = GB(data, 56, 8);
+}
+
+/**
+ * Sends a string over the network. It sends out
+ * the string + '\0'. No size-byte or something.
+ */
+void NetworkSend_string(Packet *packet, const char* data)
+{
+ assert(data != NULL);
+ assert(packet->size < sizeof(packet->buffer) - strlen(data) - 1);
+ while ((packet->buffer[packet->size++] = *data++) != '\0') {}
+}
+
+
+/**
+ * Receiving commands
+ * Again, the next couple of functions are endian-safe
+ * see the comment before NetworkSend_uint8 for more info.
+ */
+
+
+extern uint CloseConnection(NetworkClientState *cs);
+
+/** Is it safe to read from the packet, i.e. didn't we run over the buffer ? */
+static inline bool CanReadFromPacket(NetworkClientState *cs, Packet *packet, uint bytes_to_read)
+{
+ /* Don't allow reading from a closed socket */
+ if (HasClientQuit(cs)) return false;
+
+ /* Check if variable is within packet-size */
+ if (packet->pos + bytes_to_read > packet->size) {
+ CloseConnection(cs);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Reads the packet size from the raw packet and stores it in the packet->size
+ * @param packet the packet to read the size of
+ */
+void NetworkRecv_ReadPacketSize(Packet *packet)
+{
+ packet->size = (uint16)packet->buffer[0];
+ packet->size += (uint16)packet->buffer[1] << 8;
+}
+
+uint8 NetworkRecv_uint8(NetworkClientState *cs, Packet *packet)
+{
+ uint8 n;
+
+ if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
+
+ n = packet->buffer[packet->pos++];
+ return n;
+}
+
+uint16 NetworkRecv_uint16(NetworkClientState *cs, Packet *packet)
+{
+ uint16 n;
+
+ if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
+
+ n = (uint16)packet->buffer[packet->pos++];
+ n += (uint16)packet->buffer[packet->pos++] << 8;
+ return n;
+}
+
+uint32 NetworkRecv_uint32(NetworkClientState *cs, Packet *packet)
+{
+ uint32 n;
+
+ if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
+
+ n = (uint32)packet->buffer[packet->pos++];
+ n += (uint32)packet->buffer[packet->pos++] << 8;
+ n += (uint32)packet->buffer[packet->pos++] << 16;
+ n += (uint32)packet->buffer[packet->pos++] << 24;
+ return n;
+}
+
+uint64 NetworkRecv_uint64(NetworkClientState *cs, Packet *packet)
+{
+ uint64 n;
+
+ if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
+
+ n = (uint64)packet->buffer[packet->pos++];
+ n += (uint64)packet->buffer[packet->pos++] << 8;
+ n += (uint64)packet->buffer[packet->pos++] << 16;
+ n += (uint64)packet->buffer[packet->pos++] << 24;
+ n += (uint64)packet->buffer[packet->pos++] << 32;
+ n += (uint64)packet->buffer[packet->pos++] << 40;
+ n += (uint64)packet->buffer[packet->pos++] << 48;
+ n += (uint64)packet->buffer[packet->pos++] << 56;
+ return n;
+}
+
+/** Reads a string till it finds a '\0' in the stream */
+void NetworkRecv_string(NetworkClientState *cs, Packet *p, char *buffer, size_t size)
+{
+ PacketSize pos;
+ char *bufp = buffer;
+
+ /* Don't allow reading from a closed socket */
+ if (HasClientQuit(cs)) return;
+
+ pos = p->pos;
+ while (--size > 0 && pos < p->size && (*buffer++ = p->buffer[pos++]) != '\0') {}
+
+ if (size == 0 || pos == p->size) {
+ *buffer = '\0';
+ /* If size was sooner to zero then the string in the stream
+ * skip till the \0, so than packet can be read out correctly for the rest */
+ while (pos < p->size && p->buffer[pos] != '\0') pos++;
+ pos++;
+ }
+ p->pos = pos;
+
+ str_validate(bufp);
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/packet.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,67 @@
+/* $Id$ */
+
+#ifndef NETWORK_CORE_PACKET_H
+#define NETWORK_CORE_PACKET_H
+
+#ifdef ENABLE_NETWORK
+
+/**
+ * @file packet.h Basic functions to create, fill and read packets.
+ */
+
+typedef struct NetworkClientState NetworkClientState;
+
+/**
+ * Queries the network client state struct to determine whether
+ * the client has quit. It indirectly also queries whether the
+ * packet is corrupt as the connection will be closed if it is
+ * reading beyond the boundary of the received packet.
+ * @param cs the state to query
+ * @param true if the connection should be considered dropped
+ */
+bool HasClientQuit(NetworkClientState *cs);
+
+typedef uint16 PacketSize; ///< Size of the whole packet.
+typedef uint8 PacketType; ///< Identifier for the packet
+
+/**
+ * Internal entity of a packet. As everything is sent as a packet,
+ * all network communication will need to call the functions that
+ * populate the packet.
+ * Every packet can be at most SEND_MTU bytes. Overflowing this
+ * limit will give an assertion when sending (i.e. writing) the
+ * packet. Reading past the size of the packet when receiving
+ * will return all 0 values and "" in case of the string.
+ */
+typedef struct Packet {
+ /** The next packet. Used for queueing packets before sending. */
+ struct Packet *next;
+ /** The size of the whole packet for received packets. For packets
+ * that will be sent, the value is filled in just before the
+ * actual transmission. */
+ PacketSize size;
+ /** The current read/write position in the packet */
+ PacketSize pos;
+ /** The buffer of this packet */
+ byte buffer[SEND_MTU];
+} Packet;
+
+
+Packet *NetworkSend_Init(PacketType type);
+void NetworkSend_FillPacketSize(Packet *packet);
+void NetworkSend_uint8 (Packet *packet, uint8 data);
+void NetworkSend_uint16(Packet *packet, uint16 data);
+void NetworkSend_uint32(Packet *packet, uint32 data);
+void NetworkSend_uint64(Packet *packet, uint64 data);
+void NetworkSend_string(Packet *packet, const char* data);
+
+void NetworkRecv_ReadPacketSize(Packet *packet);
+uint8 NetworkRecv_uint8 (NetworkClientState *cs, Packet *packet);
+uint16 NetworkRecv_uint16(NetworkClientState *cs, Packet *packet);
+uint32 NetworkRecv_uint32(NetworkClientState *cs, Packet *packet);
+uint64 NetworkRecv_uint64(NetworkClientState *cs, Packet *packet);
+void NetworkRecv_string(NetworkClientState *cs, Packet *packet, char* buffer, size_t size);
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_CORE_PACKET_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/tcp.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,227 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../../stdafx.h"
+#include "../../debug.h"
+#include "../../openttd.h"
+#include "../../variables.h"
+#include "../../table/strings.h"
+#include "../../functions.h"
+
+#include "os_abstraction.h"
+#include "config.h"
+#include "packet.h"
+#include "../network_data.h"
+#include "tcp.h"
+
+/**
+ * @file tcp.c Basic functions to receive and send TCP packets.
+ */
+
+/**
+ * Functions to help NetworkRecv_Packet/NetworkSend_Packet a bit
+ * A socket can make errors. When that happens this handles what to do.
+ * For clients: close connection and drop back to main-menu
+ * For servers: close connection and that is it
+ * @param cs the client to close the connection of
+ * @return the new status
+ */
+NetworkRecvStatus CloseConnection(NetworkClientState *cs)
+{
+ NetworkCloseClient(cs);
+
+ /* Clients drop back to the main menu */
+ if (!_network_server && _networking) {
+ _switch_mode = SM_MENU;
+ _networking = false;
+ _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
+
+ return NETWORK_RECV_STATUS_CONN_LOST;
+ }
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+/**
+ * Whether the client has quit or not (used in packet.c)
+ * @param cs the client to check
+ * @return true if the client has quit
+ */
+bool HasClientQuit(NetworkClientState *cs)
+{
+ return cs->has_quit;
+}
+
+/**
+ * This function puts the packet in the send-queue and it is send as
+ * soon as possible. This is the next tick, or maybe one tick later
+ * if the OS-network-buffer is full)
+ * @param packet the packet to send
+ * @param cs the client to send to
+ */
+void NetworkSend_Packet(Packet *packet, NetworkClientState *cs)
+{
+ Packet *p;
+ assert(packet != NULL);
+
+ packet->pos = 0;
+ packet->next = NULL;
+
+ NetworkSend_FillPacketSize(packet);
+
+ /* Locate last packet buffered for the client */
+ p = cs->packet_queue;
+ if (p == NULL) {
+ /* No packets yet */
+ cs->packet_queue = packet;
+ } else {
+ /* Skip to the last packet */
+ while (p->next != NULL) p = p->next;
+ p->next = packet;
+ }
+}
+
+/**
+ * Sends all the buffered packets out for this client. It stops when:
+ * 1) all packets are send (queue is empty)
+ * 2) the OS reports back that it can not send any more
+ * data right now (full network-buffer, it happens ;))
+ * 3) sending took too long
+ * @param cs the client to send the packets for
+ */
+bool NetworkSend_Packets(NetworkClientState *cs)
+{
+ ssize_t res;
+ Packet *p;
+
+ /* We can not write to this socket!! */
+ if (!cs->writable) return false;
+ if (cs->socket == INVALID_SOCKET) return false;
+
+ p = cs->packet_queue;
+ while (p != NULL) {
+ res = send(cs->socket, p->buffer + p->pos, p->size - p->pos, 0);
+ if (res == -1) {
+ int err = GET_LAST_ERROR();
+ if (err != EWOULDBLOCK) {
+ /* Something went wrong.. close client! */
+ DEBUG(net, 0, "send failed with error %d", err);
+ CloseConnection(cs);
+ return false;
+ }
+ return true;
+ }
+ if (res == 0) {
+ /* Client/server has left us :( */
+ CloseConnection(cs);
+ return false;
+ }
+
+ p->pos += res;
+
+ /* Is this packet sent? */
+ if (p->pos == p->size) {
+ /* Go to the next packet */
+ cs->packet_queue = p->next;
+ free(p);
+ p = cs->packet_queue;
+ } else {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Receives a packet for the given client
+ * @param cs the client to (try to) receive a packet for
+ * @param status the variable to store the status into
+ * @return the received packet (or NULL when it didn't receive one)
+ */
+Packet *NetworkRecv_Packet(NetworkClientState *cs, NetworkRecvStatus *status)
+{
+ ssize_t res;
+ Packet *p;
+
+ *status = NETWORK_RECV_STATUS_OKAY;
+
+ if (cs->socket == INVALID_SOCKET) return NULL;
+
+ if (cs->packet_recv == NULL) {
+ cs->packet_recv = malloc(sizeof(Packet));
+ if (cs->packet_recv == NULL) error("Failed to allocate packet");
+ /* Set pos to zero! */
+ cs->packet_recv->pos = 0;
+ cs->packet_recv->size = 0; // Can be ommited, just for safety reasons
+ }
+
+ p = cs->packet_recv;
+
+ /* Read packet size */
+ if (p->pos < sizeof(PacketSize)) {
+ while (p->pos < sizeof(PacketSize)) {
+ /* Read the size of the packet */
+ res = recv(cs->socket, p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0);
+ if (res == -1) {
+ int err = GET_LAST_ERROR();
+ if (err != EWOULDBLOCK) {
+ /* Something went wrong... (104 is connection reset by peer) */
+ if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
+ *status = CloseConnection(cs);
+ return NULL;
+ }
+ /* Connection would block, so stop for now */
+ return NULL;
+ }
+ if (res == 0) {
+ /* Client/server has left */
+ *status = CloseConnection(cs);
+ return NULL;
+ }
+ p->pos += res;
+ }
+
+ NetworkRecv_ReadPacketSize(p);
+
+ if (p->size > SEND_MTU) {
+ *status = CloseConnection(cs);
+ return NULL;
+ }
+ }
+
+ /* Read rest of packet */
+ while (p->pos < p->size) {
+ res = recv(cs->socket, p->buffer + p->pos, p->size - p->pos, 0);
+ if (res == -1) {
+ int err = GET_LAST_ERROR();
+ if (err != EWOULDBLOCK) {
+ /* Something went wrong... (104 is connection reset by peer) */
+ if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
+ *status = CloseConnection(cs);
+ return NULL;
+ }
+ /* Connection would block */
+ return NULL;
+ }
+ if (res == 0) {
+ /* Client/server has left */
+ *status = CloseConnection(cs);
+ return NULL;
+ }
+
+ p->pos += res;
+ }
+
+ /* We have a complete packet, return it! */
+ p->pos = 2;
+ p->next = NULL; // Should not be needed, but who knows...
+
+ /* Prepare for receiving a new packet */
+ cs->packet_recv = NULL;
+
+ return p;
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/tcp.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,60 @@
+/* $Id$ */
+
+#ifndef NETWORK_CORE_TCP_H
+#define NETWORK_CORE_TCP_H
+
+#ifdef ENABLE_NETWORK
+
+/**
+ * @file tcp.h Basic functions to receive and send TCP packets.
+ */
+
+/**
+ * Enum with all types of UDP packets.
+ * The order of the first 4 packets MUST not be changed, as
+ * it protects old clients from joining newer servers
+ * (because SERVER_ERROR is the respond to a wrong revision)
+ */
+enum {
+ PACKET_SERVER_FULL,
+ PACKET_SERVER_BANNED,
+ PACKET_CLIENT_JOIN,
+ PACKET_SERVER_ERROR,
+ PACKET_CLIENT_COMPANY_INFO,
+ PACKET_SERVER_COMPANY_INFO,
+ PACKET_SERVER_CLIENT_INFO,
+ PACKET_SERVER_NEED_PASSWORD,
+ PACKET_CLIENT_PASSWORD,
+ PACKET_SERVER_WELCOME,
+ PACKET_CLIENT_GETMAP,
+ PACKET_SERVER_WAIT,
+ PACKET_SERVER_MAP,
+ PACKET_CLIENT_MAP_OK,
+ PACKET_SERVER_JOIN,
+ PACKET_SERVER_FRAME,
+ PACKET_SERVER_SYNC,
+ PACKET_CLIENT_ACK,
+ PACKET_CLIENT_COMMAND,
+ PACKET_SERVER_COMMAND,
+ PACKET_CLIENT_CHAT,
+ PACKET_SERVER_CHAT,
+ PACKET_CLIENT_SET_PASSWORD,
+ PACKET_CLIENT_SET_NAME,
+ PACKET_CLIENT_QUIT,
+ PACKET_CLIENT_ERROR,
+ PACKET_SERVER_QUIT,
+ PACKET_SERVER_ERROR_QUIT,
+ PACKET_SERVER_SHUTDOWN,
+ PACKET_SERVER_NEWGAME,
+ PACKET_SERVER_RCON,
+ PACKET_CLIENT_RCON,
+ PACKET_END ///< Must ALWAYS be on the end of this list!! (period)
+};
+
+void NetworkSend_Packet(Packet *packet, NetworkClientState *cs);
+Packet *NetworkRecv_Packet(NetworkClientState *cs, NetworkRecvStatus *status);
+bool NetworkSend_Packets(NetworkClientState *cs);
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_CORE_TCP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/udp.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,277 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../../stdafx.h"
+#include "../../date.h"
+#include "../../debug.h"
+#include "../../macros.h"
+#include "../../newgrf_config.h"
+
+#include "os_abstraction.h"
+#include "config.h"
+#include "game.h"
+#include "packet.h"
+#include "udp.h"
+
+/**
+ * @file udp.c Basic functions to receive and send UDP packets.
+ */
+
+/**
+ * Send a packet over UDP
+ * @param udp the socket to send over
+ * @param p the packet to send
+ * @param recv the receiver (target) of the packet
+ */
+void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv)
+{
+ int res;
+
+ NetworkSend_FillPacketSize(p);
+
+ /* Send the buffer */
+ res = sendto(udp, p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv));
+
+ /* Check for any errors, but ignore it otherwise */
+ if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR());
+}
+
+/**
+ * Start listening on the given host and port.
+ * @param udp the place where the (references to the) UDP are stored
+ * @param host the host (ip) to listen on
+ * @param port the port to listen on
+ * @param broadcast whether to allow broadcast sending/receiving
+ * @return true if the listening succeeded
+ */
+bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast)
+{
+ struct sockaddr_in sin;
+
+ /* Make sure socket is closed */
+ closesocket(*udp);
+
+ *udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (*udp == INVALID_SOCKET) {
+ DEBUG(net, 0, "[udp] failed to start UDP listener");
+ return false;
+ }
+
+ /* set nonblocking mode for socket */
+ {
+ unsigned long blocking = 1;
+#ifndef BEOS_NET_SERVER
+ ioctlsocket(*udp, FIONBIO, &blocking);
+#else
+ setsockopt(*udp, SOL_SOCKET, SO_NONBLOCK, &blocking, NULL);
+#endif
+ }
+
+ sin.sin_family = AF_INET;
+ /* Listen on all IPs */
+ sin.sin_addr.s_addr = host;
+ sin.sin_port = htons(port);
+
+ if (bind(*udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
+ DEBUG(net, 0, "[udp] bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port);
+ return false;
+ }
+
+ if (broadcast) {
+ /* Enable broadcast */
+ unsigned long val = 1;
+#ifndef BEOS_NET_SERVER // will work around this, some day; maybe.
+ setsockopt(*udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val));
+#endif
+ }
+
+ DEBUG(net, 1, "[udp] listening on port %s:%d", inet_ntoa(*(struct in_addr *)&host), port);
+
+ return true;
+}
+
+/**
+ * Receive a packet at UDP level
+ * @param udp the socket to receive the packet on
+ */
+void NetworkUDPReceive(SOCKET udp)
+{
+ struct sockaddr_in client_addr;
+ socklen_t client_len;
+ int nbytes;
+ Packet p;
+ int packet_len;
+
+ packet_len = sizeof(p.buffer);
+ client_len = sizeof(client_addr);
+
+ /* Try to receive anything */
+ nbytes = recvfrom(udp, p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len);
+
+ /* We got some bytes for the base header of the packet.
+ * Assume we received the whole packet. */
+ if (nbytes > 2) {
+ NetworkRecv_ReadPacketSize(&p);
+
+ /* Put the position on the right place */
+ p.pos = 2;
+ p.next = NULL;
+
+ /* Handle the packet */
+ NetworkHandleUDPPacket(&p, &client_addr);
+ }
+}
+
+
+/**
+ * Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
+ * @param p the packet to write the data to
+ * @param c the configuration to write the GRF ID and MD5 checksum from
+ */
+void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c)
+{
+ uint j;
+ NetworkSend_uint32(p, c->grfid);
+ for (j = 0; j < sizeof(c->md5sum); j++) {
+ NetworkSend_uint8 (p, c->md5sum[j]);
+ }
+}
+
+/**
+ * Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
+ * @param cs the client state (for closing connect on out-of-bounds reading etc)
+ * @param p the packet to read the data from
+ * @param c the configuration to write the GRF ID and MD5 checksum to
+ */
+void NetworkRecv_GRFIdentifier(NetworkClientState *cs, Packet *p, GRFConfig *c)
+{
+ uint j;
+ c->grfid = NetworkRecv_uint32(cs, p);
+ for (j = 0; j < sizeof(c->md5sum); j++) {
+ c->md5sum[j] = NetworkRecv_uint8(cs, p);
+ }
+}
+
+
+/**
+ * Serializes the NetworkGameInfo struct to the packet
+ * @param p the packet to write the data to
+ * @param info the NetworkGameInfo struct to serialize
+ */
+void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
+{
+ NetworkSend_uint8 (p, NETWORK_GAME_INFO_VERSION);
+
+ /*
+ * Please observe the order.
+ * The parts must be read in the same order as they are sent!
+ */
+
+
+ /* NETWORK_GAME_INFO_VERSION = 4 */
+ {
+ /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
+ * the GRFs that are needed, i.e. the ones that the server has
+ * selected in the NewGRF GUI and not the ones that are used due
+ * to the fact that they are in [newgrf-static] in openttd.cfg */
+ const GRFConfig *c;
+ uint count = 0;
+
+ /* Count number of GRFs to send information about */
+ for (c = info->grfconfig; c != NULL; c = c->next) {
+ if (!HASBIT(c->flags, GCF_STATIC)) count++;
+ }
+ NetworkSend_uint8 (p, count); // Send number of GRFs
+
+ /* Send actual GRF Identifications */
+ for (c = info->grfconfig; c != NULL; c = c->next) {
+ if (!HASBIT(c->flags, GCF_STATIC)) NetworkSend_GRFIdentifier(p, c);
+ }
+ }
+
+ /* NETWORK_GAME_INFO_VERSION = 3 */
+ NetworkSend_uint32(p, info->game_date);
+ NetworkSend_uint32(p, info->start_date);
+
+ /* NETWORK_GAME_INFO_VERSION = 2 */
+ NetworkSend_uint8 (p, info->companies_max);
+ NetworkSend_uint8 (p, info->companies_on);
+ NetworkSend_uint8 (p, info->spectators_max);
+
+ /* NETWORK_GAME_INFO_VERSION = 1 */
+ NetworkSend_string(p, info->server_name);
+ NetworkSend_string(p, info->server_revision);
+ NetworkSend_uint8 (p, info->server_lang);
+ NetworkSend_uint8 (p, info->use_password);
+ NetworkSend_uint8 (p, info->clients_max);
+ NetworkSend_uint8 (p, info->clients_on);
+ NetworkSend_uint8 (p, info->spectators_on);
+ NetworkSend_string(p, info->map_name);
+ NetworkSend_uint16(p, info->map_width);
+ NetworkSend_uint16(p, info->map_height);
+ NetworkSend_uint8 (p, info->map_set);
+ NetworkSend_uint8 (p, info->dedicated);
+}
+
+/**
+ * Deserializes the NetworkGameInfo struct from the packet
+ * @param cs the client state (for closing connect on out-of-bounds reading etc)
+ * @param p the packet to read the data from
+ * @param info the NetworkGameInfo to deserialize into
+ */
+void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameInfo *info)
+{
+ info->game_info_version = NetworkRecv_uint8(cs, p);
+
+ /*
+ * Please observe the order.
+ * The parts must be read in the same order as they are sent!
+ */
+
+ switch (info->game_info_version) {
+ case 4: {
+ GRFConfig *c, **dst = &info->grfconfig;
+ uint i;
+ uint num_grfs = NetworkRecv_uint8(cs, p);
+
+ for (i = 0; i < num_grfs; i++) {
+ c = calloc(1, sizeof(*c));
+ NetworkRecv_GRFIdentifier(cs, p, c);
+ HandleIncomingNetworkGameInfoGRFConfig(c);
+
+ /* Append GRFConfig to the list */
+ *dst = c;
+ dst = &c->next;
+ }
+ } /* Fallthrough */
+ case 3:
+ info->game_date = NetworkRecv_uint32(cs, p);
+ info->start_date = NetworkRecv_uint32(cs, p);
+ /* Fallthrough */
+ case 2:
+ info->companies_max = NetworkRecv_uint8 (cs, p);
+ info->companies_on = NetworkRecv_uint8 (cs, p);
+ info->spectators_max = NetworkRecv_uint8 (cs, p);
+ /* Fallthrough */
+ case 1:
+ NetworkRecv_string(cs, p, info->server_name, sizeof(info->server_name));
+ NetworkRecv_string(cs, p, info->server_revision, sizeof(info->server_revision));
+ info->server_lang = NetworkRecv_uint8 (cs, p);
+ info->use_password = NetworkRecv_uint8 (cs, p);
+ info->clients_max = NetworkRecv_uint8 (cs, p);
+ info->clients_on = NetworkRecv_uint8 (cs, p);
+ info->spectators_on = NetworkRecv_uint8 (cs, p);
+ if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
+ info->game_date = NetworkRecv_uint16(cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+ info->start_date = NetworkRecv_uint16(cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+ }
+ NetworkRecv_string(cs, p, info->map_name, sizeof(info->map_name));
+ info->map_width = NetworkRecv_uint16(cs, p);
+ info->map_height = NetworkRecv_uint16(cs, p);
+ info->map_set = NetworkRecv_uint8 (cs, p);
+ info->dedicated = NetworkRecv_uint8 (cs, p);
+ }
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/core/udp.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,62 @@
+/* $Id$ */
+
+#ifndef NETWORK_CORE_UDP_H
+#define NETWORK_CORE_UDP_H
+
+#ifdef ENABLE_NETWORK
+
+/**
+ * @file udp.h Basic functions to receive and send UDP packets.
+ */
+
+///** Sending/receiving of UDP packets **////
+
+void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv);
+bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast);
+void NetworkUDPReceive(SOCKET udp);
+
+/**
+ * Function that is called for every received UDP packet.
+ * @param packet the received packet
+ * @param client_addr the address of the sender of the packet
+ */
+void NetworkHandleUDPPacket(Packet *p, struct sockaddr_in *client_addr);
+
+
+///** Sending/receiving of (large) chuncks of UDP packets **////
+
+
+/** Enum with all types of UDP packets. The order MUST not be changed **/
+enum {
+ PACKET_UDP_CLIENT_FIND_SERVER, ///< Queries a game server for game information
+ PACKET_UDP_SERVER_RESPONSE, ///< Reply of the game server with game information
+ PACKET_UDP_CLIENT_DETAIL_INFO, ///< Queries a game server about details of the game, such as companies
+ PACKET_UDP_SERVER_DETAIL_INFO, ///< Reply of the game server about details of the game, such as companies
+ PACKET_UDP_SERVER_REGISTER, ///< Packet to register itself to the master server
+ PACKET_UDP_MASTER_ACK_REGISTER, ///< Packet indicating registration has succedeed
+ PACKET_UDP_CLIENT_GET_LIST, ///< Request for serverlist from master server
+ PACKET_UDP_MASTER_RESPONSE_LIST, ///< Response from master server with server ip's + port's
+ PACKET_UDP_SERVER_UNREGISTER, ///< Request to be removed from the server-list
+ PACKET_UDP_CLIENT_GET_NEWGRFS, ///< Requests the name for a list of GRFs (GRF_ID and MD5)
+ PACKET_UDP_SERVER_NEWGRFS, ///< Sends the list of NewGRF's requested.
+ PACKET_UDP_END ///< Must ALWAYS be on the end of this list!! (period)
+};
+
+void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c);
+void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info);
+
+void NetworkRecv_GRFIdentifier(NetworkClientState *cs, Packet *p, GRFConfig *c);
+void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameInfo *info);
+
+/**
+ * Function that is called for every GRFConfig that is read when receiving
+ * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
+ * function must set all appropriate fields. This GRF is later appended to
+ * the grfconfig list of the NetworkGameInfo.
+ * @param config the GRF to handle
+ */
+void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config);
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_CORE_UDP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,1451 @@
+/* $Id$ */
+
+#include "../stdafx.h"
+#include "network_data.h"
+
+#if defined(WITH_REV)
+ extern const char _openttd_revision[];
+#elif defined(WITH_REV_HACK)
+ #define WITH_REV
+ const char _openttd_revision[] = WITH_REV_HACK;
+#else
+ const char _openttd_revision[] = NOREV_STRING;
+#endif
+
+
+#ifdef ENABLE_NETWORK
+
+#include "../openttd.h"
+#include "../debug.h"
+#include "../functions.h"
+#include "../string.h"
+#include "../strings.h"
+#include "../map.h"
+#include "../command.h"
+#include "../variables.h"
+#include "../date.h"
+#include "../newgrf_config.h"
+#include "../table/strings.h"
+#include "network_client.h"
+#include "network_server.h"
+#include "network_udp.h"
+#include "network_gamelist.h"
+#include "core/udp.h"
+#include "core/tcp.h"
+#include "network_gui.h"
+#include "../console.h" /* IConsoleCmdExec */
+#include <stdarg.h> /* va_list */
+#include "../md5.h"
+
+#ifdef __MORPHOS__
+// the library base is required here
+struct Library *SocketBase = NULL;
+#endif
+
+// The listen socket for the server
+static SOCKET _listensocket;
+
+// The amount of clients connected
+static byte _network_clients_connected = 0;
+// The index counter for new clients (is never decreased)
+static uint16 _network_client_index = NETWORK_SERVER_INDEX + 1;
+
+/* Some externs / forwards */
+extern void StateGameLoop(void);
+
+// Function that looks up the CI for a given client-index
+NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index)
+{
+ NetworkClientInfo *ci;
+
+ for (ci = _network_client_info; ci != endof(_network_client_info); ci++) {
+ if (ci->client_index == client_index) return ci;
+ }
+
+ return NULL;
+}
+
+/** Return the CI for a given IP
+ * @param ip IP of the client we are looking for. This must be in string-format
+ * @return return a pointer to the corresponding NetworkClientInfo struct or NULL on failure */
+NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip)
+{
+ NetworkClientInfo *ci;
+ uint32 ip_number = inet_addr(ip);
+
+ for (ci = _network_client_info; ci != endof(_network_client_info); ci++) {
+ if (ci->client_ip == ip_number) return ci;
+ }
+
+ return NULL;
+}
+
+// Function that looks up the CS for a given client-index
+NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index)
+{
+ NetworkClientState *cs;
+
+ for (cs = _clients; cs != &_clients[MAX_CLIENT_INFO]; cs++) {
+ if (cs->index == client_index) return cs;
+ }
+
+ return NULL;
+}
+
+// NetworkGetClientName is a server-safe function to get the name of the client
+// if the user did not send it yet, Client #<no> is used.
+void NetworkGetClientName(char *client_name, size_t size, const NetworkClientState *cs)
+{
+ const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
+
+ if (ci->client_name[0] == '\0') {
+ snprintf(client_name, size, "Client #%4d", cs->index);
+ } else {
+ ttd_strlcpy(client_name, ci->client_name, size);
+ }
+}
+
+byte NetworkSpectatorCount(void)
+{
+ const NetworkClientState *cs;
+ byte count = 0;
+
+ FOR_ALL_CLIENTS(cs) {
+ if (DEREF_CLIENT_INFO(cs)->client_playas == PLAYER_SPECTATOR) count++;
+ }
+
+ return count;
+}
+
+// This puts a text-message to the console, or in the future, the chat-box,
+// (to keep it all a bit more general)
+// If 'self_send' is true, this is the client who is sending the message
+void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...)
+{
+ char buf[1024];
+ va_list va;
+ const int duration = 10; // Game days the messages stay visible
+ char message[1024];
+ char temp[1024];
+
+ va_start(va, str);
+ vsnprintf(buf, lengthof(buf), str, va);
+ va_end(va);
+
+ switch (action) {
+ case NETWORK_ACTION_SERVER_MESSAGE:
+ color = 1;
+ snprintf(message, sizeof(message), "*** %s", buf);
+ break;
+ case NETWORK_ACTION_JOIN:
+ color = 1;
+ GetString(temp, STR_NETWORK_CLIENT_JOINED, lastof(temp));
+ snprintf(message, sizeof(message), "*** %s %s", name, temp);
+ break;
+ case NETWORK_ACTION_LEAVE:
+ color = 1;
+ GetString(temp, STR_NETWORK_ERR_LEFT, lastof(temp));
+ snprintf(message, sizeof(message), "*** %s %s (%s)", name, temp, buf);
+ break;
+ case NETWORK_ACTION_GIVE_MONEY:
+ if (self_send) {
+ SetDParamStr(0, name);
+ SetDParam(1, atoi(buf));
+ GetString(temp, STR_NETWORK_GAVE_MONEY_AWAY, lastof(temp));
+ snprintf(message, sizeof(message), "*** %s", temp);
+ } else {
+ SetDParam(0, atoi(buf));
+ GetString(temp, STR_NETWORK_GIVE_MONEY, lastof(temp));
+ snprintf(message, sizeof(message), "*** %s %s", name, temp);
+ }
+ break;
+ case NETWORK_ACTION_NAME_CHANGE:
+ GetString(temp, STR_NETWORK_NAME_CHANGE, lastof(temp));
+ snprintf(message, sizeof(message), "*** %s %s %s", name, temp, buf);
+ break;
+ case NETWORK_ACTION_CHAT_COMPANY:
+ SetDParamStr(0, name);
+ SetDParamStr(1, buf);
+ GetString(temp, self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY, lastof(temp));
+ ttd_strlcpy(message, temp, sizeof(message));
+ break;
+ case NETWORK_ACTION_CHAT_CLIENT:
+ SetDParamStr(0, name);
+ SetDParamStr(1, buf);
+ GetString(temp, self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT, lastof(temp));
+ ttd_strlcpy(message, temp, sizeof(message));
+ break;
+ default:
+ SetDParamStr(0, name);
+ SetDParamStr(1, buf);
+ GetString(temp, STR_NETWORK_CHAT_ALL, lastof(temp));
+ ttd_strlcpy(message, temp, sizeof(message));
+ break;
+ }
+
+ IConsolePrintF(color, "%s", message);
+ AddTextMessage(color, duration, "%s", message);
+}
+
+// Calculate the frame-lag of a client
+uint NetworkCalculateLag(const NetworkClientState *cs)
+{
+ int lag = cs->last_frame_server - cs->last_frame;
+ // This client has missed his ACK packet after 1 DAY_TICKS..
+ // so we increase his lag for every frame that passes!
+ // The packet can be out by a max of _net_frame_freq
+ if (cs->last_frame_server + DAY_TICKS + _network_frame_freq < _frame_counter)
+ lag += _frame_counter - (cs->last_frame_server + DAY_TICKS + _network_frame_freq);
+
+ return lag;
+}
+
+
+// There was a non-recoverable error, drop back to the main menu with a nice
+// error
+static void NetworkError(StringID error_string)
+{
+ _switch_mode = SM_MENU;
+ _switch_mode_errorstr = error_string;
+}
+
+static void ClientStartError(const char *error)
+{
+ DEBUG(net, 0, "[client] could not start network: %s",error);
+ NetworkError(STR_NETWORK_ERR_CLIENT_START);
+}
+
+static void ServerStartError(const char *error)
+{
+ DEBUG(net, 0, "[server] could not start network: %s",error);
+ NetworkError(STR_NETWORK_ERR_SERVER_START);
+}
+
+static void NetworkClientError(NetworkRecvStatus res, NetworkClientState* cs)
+{
+ // First, send a CLIENT_ERROR to the server, so he knows we are
+ // disconnection (and why!)
+ NetworkErrorCode errorno;
+
+ // We just want to close the connection..
+ if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
+ cs->has_quit = true;
+ NetworkCloseClient(cs);
+ _networking = false;
+
+ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+ return;
+ }
+
+ switch (res) {
+ case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
+ case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
+ default: errorno = NETWORK_ERROR_GENERAL; break;
+ }
+ // This means we fucked up and the server closed the connection
+ if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
+ res != NETWORK_RECV_STATUS_SERVER_BANNED) {
+ SEND_COMMAND(PACKET_CLIENT_ERROR)(errorno);
+
+ // Dequeue all commands before closing the socket
+ NetworkSend_Packets(DEREF_CLIENT(0));
+ }
+
+ _switch_mode = SM_MENU;
+ NetworkCloseClient(cs);
+ _networking = false;
+}
+
+/** Retrieve a string representation of an internal error number
+ * @param buf buffer where the error message will be stored
+ * @param err NetworkErrorCode
+ * @return returns a pointer to the error message (buf) */
+char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last)
+{
+ /* List of possible network errors, used by
+ * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
+ static const StringID network_error_strings[] = {
+ STR_NETWORK_ERR_CLIENT_GENERAL,
+ STR_NETWORK_ERR_CLIENT_DESYNC,
+ STR_NETWORK_ERR_CLIENT_SAVEGAME,
+ STR_NETWORK_ERR_CLIENT_CONNECTION_LOST,
+ STR_NETWORK_ERR_CLIENT_PROTOCOL_ERROR,
+ STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED,
+ STR_NETWORK_ERR_CLIENT_NOT_EXPECTED,
+ STR_NETWORK_ERR_CLIENT_WRONG_REVISION,
+ STR_NETWORK_ERR_CLIENT_NAME_IN_USE,
+ STR_NETWORK_ERR_CLIENT_WRONG_PASSWORD,
+ STR_NETWORK_ERR_CLIENT_PLAYER_MISMATCH,
+ STR_NETWORK_ERR_CLIENT_KICKED,
+ STR_NETWORK_ERR_CLIENT_CHEATER,
+ STR_NETWORK_ERR_CLIENT_SERVER_FULL
+ };
+
+ if (err >= lengthof(network_error_strings)) err = 0;
+
+ return GetString(buf, network_error_strings[err], last);
+}
+
+/* Count the number of active clients connected */
+static uint NetworkCountPlayers(void)
+{
+ const NetworkClientState *cs;
+ uint count = 0;
+
+ FOR_ALL_CLIENTS(cs) {
+ const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
+ if (IsValidPlayer(ci->client_playas)) count++;
+ }
+
+ return count;
+}
+
+static bool _min_players_paused = false;
+
+/* Check if the minimum number of players has been reached and pause or unpause the game as appropriate */
+void CheckMinPlayers(void)
+{
+ if (!_network_dedicated) return;
+
+ if (NetworkCountPlayers() < _network_min_players) {
+ if (_min_players_paused) return;
+
+ _min_players_paused = true;
+ DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
+ NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (not enough players)", NETWORK_SERVER_INDEX);
+ } else {
+ if (!_min_players_paused) return;
+
+ _min_players_paused = false;
+ DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
+ NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", NETWORK_SERVER_INDEX);
+ }
+}
+
+// Find all IP-aliases for this host
+static void NetworkFindIPs(void)
+{
+ int i;
+
+#if defined(BEOS_NET_SERVER) /* doesn't have neither getifaddrs or net/if.h */
+ /* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */
+ int _netstat(int fd, char **output, int verbose);
+
+ int seek_past_header(char **pos, const char *header) {
+ char *new_pos = strstr(*pos, header);
+ if (new_pos == 0) {
+ return B_ERROR;
+ }
+ *pos += strlen(header) + new_pos - *pos + 1;
+ return B_OK;
+ }
+
+ int output_length;
+ char *output_pointer = NULL;
+ char **output;
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
+ i = 0;
+
+ // If something fails, make sure the list is empty
+ _broadcast_list[0] = 0;
+
+ if (sock < 0) {
+ DEBUG(net, 0, "[core] error creating socket");
+ return;
+ }
+
+ output_length = _netstat(sock, &output_pointer, 1);
+ if (output_length < 0) {
+ DEBUG(net, 0, "[core] error running _netstat");
+ return;
+ }
+
+ output = &output_pointer;
+ if (seek_past_header(output, "IP Interfaces:") == B_OK) {
+ for (;;) {
+ uint32 n, fields, read;
+ uint8 i1, i2, i3, i4, j1, j2, j3, j4;
+ struct in_addr inaddr;
+ uint32 ip;
+ uint32 netmask;
+
+ fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n",
+ &n, &i1,&i2,&i3,&i4, &j1,&j2,&j3,&j4, &read);
+ read += 1;
+ if (fields != 9) {
+ break;
+ }
+
+ ip = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4;
+ netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4;
+
+ if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) {
+ inaddr.s_addr = htonl(ip | ~netmask);
+ _broadcast_list[i] = inaddr.s_addr;
+ i++;
+ }
+ if (read < 0) {
+ break;
+ }
+ *output += read;
+ }
+ /* XXX - Using either one of these crashes openttd heavily? - wber */
+ /*free(output_pointer);*/
+ /*free(output);*/
+ closesocket(sock);
+ }
+#elif defined(HAVE_GETIFADDRS)
+ struct ifaddrs *ifap, *ifa;
+
+ // If something fails, make sure the list is empty
+ _broadcast_list[0] = 0;
+
+ if (getifaddrs(&ifap) != 0)
+ return;
+
+ i = 0;
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ if (!(ifa->ifa_flags & IFF_BROADCAST)) continue;
+ if (ifa->ifa_broadaddr == NULL) continue;
+ if (ifa->ifa_broadaddr->sa_family != AF_INET) continue;
+ _broadcast_list[i] = ((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr;
+ i++;
+ }
+ freeifaddrs(ifap);
+
+#else /* not HAVE_GETIFADDRS */
+ SOCKET sock;
+#ifdef WIN32
+ DWORD len = 0;
+ INTERFACE_INFO ifo[MAX_INTERFACES];
+ uint j;
+#else
+ char buf[4 * 1024]; // Arbitrary buffer size
+ struct ifconf ifconf;
+ const char* buf_end;
+ const char* p;
+#endif
+
+ // If something fails, make sure the list is empty
+ _broadcast_list[0] = 0;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == INVALID_SOCKET) return;
+
+#ifdef WIN32
+ memset(&ifo[0], 0, sizeof(ifo));
+ if ((WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, &ifo[0], sizeof(ifo), &len, NULL, NULL)) != 0) {
+ closesocket(sock);
+ return;
+ }
+
+ i = 0;
+ for (j = 0; j < len / sizeof(*ifo); j++) {
+ if (ifo[j].iiFlags & IFF_LOOPBACK) continue;
+ if (!(ifo[j].iiFlags & IFF_BROADCAST)) continue;
+ /* iiBroadcast is unusable, because it always seems to be set to
+ * 255.255.255.255.
+ */
+ _broadcast_list[i++] =
+ ifo[j].iiAddress.AddressIn.sin_addr.s_addr |
+ ~ifo[j].iiNetmask.AddressIn.sin_addr.s_addr;
+ }
+#else
+ ifconf.ifc_len = sizeof(buf);
+ ifconf.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1) {
+ closesocket(sock);
+ return;
+ }
+
+ i = 0;
+ buf_end = buf + ifconf.ifc_len;
+ for (p = buf; p < buf_end;) {
+ const struct ifreq* req = (const struct ifreq*)p;
+
+ if (req->ifr_addr.sa_family == AF_INET) {
+ struct ifreq r;
+
+ strncpy(r.ifr_name, req->ifr_name, lengthof(r.ifr_name));
+ if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 &&
+ r.ifr_flags & IFF_BROADCAST &&
+ ioctl(sock, SIOCGIFBRDADDR, &r) != -1) {
+ _broadcast_list[i++] =
+ ((struct sockaddr_in*)&r.ifr_broadaddr)->sin_addr.s_addr;
+ }
+ }
+
+ p += sizeof(struct ifreq);
+#ifdef AF_LINK
+ p += req->ifr_addr.sa_len - sizeof(struct sockaddr);
+#endif
+ }
+#endif
+
+ closesocket(sock);
+#endif /* not HAVE_GETIFADDRS */
+
+ _broadcast_list[i] = 0;
+
+ DEBUG(net, 3, "Detected broadcast addresses:");
+ // Now display to the debug all the detected ips
+ for (i = 0; _broadcast_list[i] != 0; i++) {
+ DEBUG(net, 3, "%d) %s", i, inet_ntoa(*(struct in_addr *)&_broadcast_list[i]));//inet_ntoa(inaddr));
+ }
+}
+
+// Resolve a hostname to a inet_addr
+unsigned long NetworkResolveHost(const char *hostname)
+{
+ in_addr_t ip;
+
+ // First try: is it an ip address?
+ ip = inet_addr(hostname);
+
+ // If not try to resolve the name
+ if (ip == INADDR_NONE) {
+ struct hostent *he = gethostbyname(hostname);
+ if (he == NULL) {
+ DEBUG(net, 0, "Cannot resolve '%s'", hostname);
+ } else {
+ struct in_addr addr = *(struct in_addr *)he->h_addr_list[0];
+ DEBUG(net, 1, "Resolved '%s' to %s", hostname, inet_ntoa(addr));
+ ip = addr.s_addr;
+ }
+ }
+ return ip;
+}
+
+// Converts a string to ip/port/player
+// Format: IP#player:port
+//
+// connection_string will be re-terminated to seperate out the hostname, and player and port will
+// be set to the player and port strings given by the user, inside the memory area originally
+// occupied by connection_string.
+void ParseConnectionString(const char **player, const char **port, char *connection_string)
+{
+ char *p;
+ for (p = connection_string; *p != '\0'; p++) {
+ if (*p == '#') {
+ *p = '\0';
+ *player = ++p;
+ while (IsValidChar(*p, CS_NUMERAL)) p++;
+ if (*p == '\0') break;
+ } else if (*p == ':') {
+ *port = p + 1;
+ *p = '\0';
+ }
+ }
+}
+
+// Creates a new client from a socket
+// Used both by the server and the client
+static NetworkClientState *NetworkAllocClient(SOCKET s)
+{
+ NetworkClientState *cs;
+ byte client_no = 0;
+
+ if (_network_server) {
+ // Can we handle a new client?
+ if (_network_clients_connected >= MAX_CLIENTS) return NULL;
+ if (_network_game_info.clients_on >= _network_game_info.clients_max) return NULL;
+
+ // Register the login
+ client_no = _network_clients_connected++;
+ }
+
+ cs = DEREF_CLIENT(client_no);
+ memset(cs, 0, sizeof(*cs));
+ cs->socket = s;
+ cs->last_frame = 0;
+ cs->has_quit = false;
+
+ cs->last_frame = _frame_counter;
+ cs->last_frame_server = _frame_counter;
+
+ if (_network_server) {
+ NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
+ memset(ci, 0, sizeof(*ci));
+
+ cs->index = _network_client_index++;
+ ci->client_index = cs->index;
+ ci->client_playas = PLAYER_INACTIVE_CLIENT;
+ ci->join_date = _date;
+
+ InvalidateWindow(WC_CLIENT_LIST, 0);
+ }
+
+ return cs;
+}
+
+// Close a connection
+void NetworkCloseClient(NetworkClientState *cs)
+{
+ NetworkClientInfo *ci;
+ // Socket is already dead
+ if (cs->socket == INVALID_SOCKET) {
+ cs->has_quit = true;
+ return;
+ }
+
+ DEBUG(net, 1, "Closed client connection %d", cs->index);
+
+ if (!cs->has_quit && _network_server && cs->status > STATUS_INACTIVE) {
+ // We did not receive a leave message from this client...
+ NetworkErrorCode errorno = NETWORK_ERROR_CONNECTION_LOST;
+ char str[100];
+ char client_name[NETWORK_CLIENT_NAME_LENGTH];
+ NetworkClientState *new_cs;
+
+ NetworkGetClientName(client_name, sizeof(client_name), cs);
+
+ GetNetworkErrorMsg(str, errorno, lastof(str));
+
+ NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+
+ // Inform other clients of this... strange leaving ;)
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status > STATUS_AUTH && cs != new_cs) {
+ SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
+ }
+ }
+ }
+
+ /* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
+ if (cs->status == STATUS_PRE_ACTIVE && _network_pause_on_join) {
+ DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
+ NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
+ }
+
+ closesocket(cs->socket);
+ cs->writable = false;
+ cs->has_quit = true;
+
+ // Free all pending and partially received packets
+ while (cs->packet_queue != NULL) {
+ Packet *p = cs->packet_queue->next;
+ free(cs->packet_queue);
+ cs->packet_queue = p;
+ }
+ free(cs->packet_recv);
+ cs->packet_recv = NULL;
+
+ while (cs->command_queue != NULL) {
+ CommandPacket *p = cs->command_queue->next;
+ free(cs->command_queue);
+ cs->command_queue = p;
+ }
+
+ // Close the gap in the client-list
+ ci = DEREF_CLIENT_INFO(cs);
+
+ if (_network_server) {
+ // We just lost one client :(
+ if (cs->status > STATUS_INACTIVE) _network_game_info.clients_on--;
+ _network_clients_connected--;
+
+ while ((cs + 1) != DEREF_CLIENT(MAX_CLIENTS) && (cs + 1)->socket != INVALID_SOCKET) {
+ *cs = *(cs + 1);
+ *ci = *(ci + 1);
+ cs++;
+ ci++;
+ }
+
+ InvalidateWindow(WC_CLIENT_LIST, 0);
+ }
+
+ // Reset the status of the last socket
+ cs->socket = INVALID_SOCKET;
+ cs->status = STATUS_INACTIVE;
+ cs->index = NETWORK_EMPTY_INDEX;
+ ci->client_index = NETWORK_EMPTY_INDEX;
+
+ CheckMinPlayers();
+}
+
+// A client wants to connect to a server
+static bool NetworkConnect(const char *hostname, int port)
+{
+ SOCKET s;
+ struct sockaddr_in sin;
+
+ DEBUG(net, 1, "Connecting to %s %d", hostname, port);
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) {
+ ClientStartError("socket() failed");
+ return false;
+ }
+
+ if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
+
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = NetworkResolveHost(hostname);
+ sin.sin_port = htons(port);
+ _network_last_host_ip = sin.sin_addr.s_addr;
+
+ /* We failed to connect for which reason what so ever */
+ if (connect(s, (struct sockaddr*) &sin, sizeof(sin)) != 0) return false;
+
+ if (!SetNonBlocking(s)) DEBUG(net, 0, "Setting non-blocking mode failed"); // XXX should this be an error?
+
+ // in client mode, only the first client field is used. it's pointing to the server.
+ NetworkAllocClient(s);
+
+ _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
+ ShowJoinStatusWindow();
+
+ return true;
+}
+
+// For the server, to accept new clients
+static void NetworkAcceptClients(void)
+{
+ struct sockaddr_in sin;
+ NetworkClientState *cs;
+ uint i;
+ bool banned;
+
+ // Should never ever happen.. is it possible??
+ assert(_listensocket != INVALID_SOCKET);
+
+ for (;;) {
+ socklen_t sin_len = sizeof(sin);
+ SOCKET s = accept(_listensocket, (struct sockaddr*)&sin, &sin_len);
+ if (s == INVALID_SOCKET) return;
+
+ SetNonBlocking(s); // XXX error handling?
+
+ DEBUG(net, 1, "Client connected from %s on frame %d", inet_ntoa(sin.sin_addr), _frame_counter);
+
+ SetNoDelay(s); // XXX error handling?
+
+ /* Check if the client is banned */
+ banned = false;
+ for (i = 0; i < lengthof(_network_ban_list); i++) {
+ if (_network_ban_list[i] == NULL) continue;
+
+ if (sin.sin_addr.s_addr == inet_addr(_network_ban_list[i])) {
+ Packet *p = NetworkSend_Init(PACKET_SERVER_BANNED);
+
+ DEBUG(net, 1, "Banned ip tried to join (%s), refused", _network_ban_list[i]);
+
+ p->buffer[0] = p->size & 0xFF;
+ p->buffer[1] = p->size >> 8;
+
+ send(s, p->buffer, p->size, 0);
+ closesocket(s);
+
+ free(p);
+
+ banned = true;
+ break;
+ }
+ }
+ /* If this client is banned, continue with next client */
+ if (banned) continue;
+
+ cs = NetworkAllocClient(s);
+ if (cs == NULL) {
+ // no more clients allowed?
+ // Send to the client that we are full!
+ Packet *p = NetworkSend_Init(PACKET_SERVER_FULL);
+
+ p->buffer[0] = p->size & 0xFF;
+ p->buffer[1] = p->size >> 8;
+
+ send(s, p->buffer, p->size, 0);
+ closesocket(s);
+
+ free(p);
+
+ continue;
+ }
+
+ // a new client has connected. We set him at inactive for now
+ // maybe he is only requesting server-info. Till he has sent a PACKET_CLIENT_MAP_OK
+ // the client stays inactive
+ cs->status = STATUS_INACTIVE;
+
+ DEREF_CLIENT_INFO(cs)->client_ip = sin.sin_addr.s_addr; // Save the IP of the client
+ }
+}
+
+// Set up the listen socket for the server
+static bool NetworkListen(void)
+{
+ SOCKET ls;
+ struct sockaddr_in sin;
+
+ DEBUG(net, 1, "Listening on %s:%d", _network_server_bind_ip_host, _network_server_port);
+
+ ls = socket(AF_INET, SOCK_STREAM, 0);
+ if (ls == INVALID_SOCKET) {
+ ServerStartError("socket() on listen socket failed");
+ return false;
+ }
+
+ { // reuse the socket
+ int reuse = 1;
+ // The (const char*) cast is needed for windows!!
+ if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) == -1) {
+ ServerStartError("setsockopt() on listen socket failed");
+ return false;
+ }
+ }
+
+ if (!SetNonBlocking(ls)) DEBUG(net, 0, "Setting non-blocking mode failed"); // XXX should this be an error?
+
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = _network_server_bind_ip;
+ sin.sin_port = htons(_network_server_port);
+
+ if (bind(ls, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
+ ServerStartError("bind() failed");
+ return false;
+ }
+
+ if (listen(ls, 1) != 0) {
+ ServerStartError("listen() failed");
+ return false;
+ }
+
+ _listensocket = ls;
+
+ return true;
+}
+
+// Close all current connections
+static void NetworkClose(void)
+{
+ NetworkClientState *cs;
+
+ FOR_ALL_CLIENTS(cs) {
+ if (!_network_server) {
+ SEND_COMMAND(PACKET_CLIENT_QUIT)("leaving");
+ NetworkSend_Packets(cs);
+ }
+ NetworkCloseClient(cs);
+ }
+
+ if (_network_server) {
+ // We are a server, also close the listensocket
+ closesocket(_listensocket);
+ _listensocket = INVALID_SOCKET;
+ DEBUG(net, 1, "Closed listener");
+ NetworkUDPClose();
+ }
+}
+
+// Inits the network (cleans sockets and stuff)
+static void NetworkInitialize(void)
+{
+ NetworkClientState *cs;
+
+ _local_command_queue = NULL;
+
+ // Clean all client-sockets
+ memset(_clients, 0, sizeof(_clients));
+ for (cs = _clients; cs != &_clients[MAX_CLIENTS]; cs++) {
+ cs->socket = INVALID_SOCKET;
+ cs->status = STATUS_INACTIVE;
+ cs->command_queue = NULL;
+ }
+
+ // Clean the client_info memory
+ memset(&_network_client_info, 0, sizeof(_network_client_info));
+ memset(&_network_player_info, 0, sizeof(_network_player_info));
+
+ _sync_frame = 0;
+ _network_first_time = true;
+
+ _network_reconnect = 0;
+
+ NetworkUDPInitialize();
+}
+
+// Query a server to fetch his game-info
+// If game_info is true, only the gameinfo is fetched,
+// else only the client_info is fetched
+NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info)
+{
+ if (!_network_available) return NULL;
+
+ NetworkDisconnect();
+
+ if (game_info) return NetworkUDPQueryServer(host, port);
+
+ NetworkInitialize();
+
+ _network_server = false;
+
+ // Try to connect
+ _networking = NetworkConnect(host, port);
+
+ // We are connected
+ if (_networking) {
+ SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)();
+ } else { // No networking, close everything down again
+ NetworkDisconnect();
+ }
+
+ return NULL;
+}
+
+/* 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)
+{
+ if (*b != '\0') {
+ NetworkGameList *item;
+ const char *port = NULL;
+ const char *player = NULL;
+ char host[NETWORK_HOSTNAME_LENGTH];
+ uint16 rport;
+
+ ttd_strlcpy(host, b, lengthof(host));
+
+ ttd_strlcpy(_network_default_ip, b, lengthof(_network_default_ip));
+ rport = NETWORK_DEFAULT_PORT;
+
+ ParseConnectionString(&player, &port, host);
+ if (port != NULL) rport = atoi(port);
+
+ item = NetworkQueryServer(host, rport, true);
+ item->manually = true;
+ }
+}
+
+/* Generates the list of manually added hosts from NetworkGameList and
+ * dumps them into the array _network_host_list. This array is needed
+ * by the function that generates the config file. */
+void NetworkRebuildHostList(void)
+{
+ uint i = 0;
+ const NetworkGameList *item = _network_game_list;
+ while (item != NULL && i != lengthof(_network_host_list)) {
+ if (item->manually) {
+ free(_network_host_list[i]);
+ _network_host_list[i++] = str_fmt("%s:%i", item->info.hostname, item->port);
+ }
+ item = item->next;
+ }
+
+ for (; i < lengthof(_network_host_list); i++) {
+ free(_network_host_list[i]);
+ _network_host_list[i] = NULL;
+ }
+}
+
+// Used by clients, to connect to a server
+bool NetworkClientConnectGame(const char *host, uint16 port)
+{
+ if (!_network_available) return false;
+
+ if (port == 0) return false;
+
+ ttd_strlcpy(_network_last_host, host, sizeof(_network_last_host));
+ _network_last_port = port;
+
+ NetworkDisconnect();
+ NetworkUDPClose();
+ NetworkInitialize();
+
+ // Try to connect
+ _networking = NetworkConnect(host, port);
+
+ // We are connected
+ if (_networking) {
+ IConsoleCmdExec("exec scripts/on_client.scr 0");
+ NetworkClient_Connected();
+ } else {
+ // Connecting failed
+ NetworkError(STR_NETWORK_ERR_NOCONNECTION);
+ }
+
+ return _networking;
+}
+
+static void NetworkInitGameInfo(void)
+{
+ NetworkClientInfo *ci;
+
+ ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
+ ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
+ ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_rcon_password));
+ if (_network_game_info.server_name[0] == '\0')
+ snprintf(_network_game_info.server_name, sizeof(_network_game_info.server_name), "Unnamed Server");
+
+ ttd_strlcpy(_network_game_info.server_revision, _openttd_revision, sizeof(_network_game_info.server_revision));
+
+ // The server is a client too ;)
+ if (_network_dedicated) {
+ _network_game_info.clients_on = 0;
+ _network_game_info.companies_on = 0;
+ _network_game_info.dedicated = true;
+ } else {
+ _network_game_info.clients_on = 1;
+ _network_game_info.companies_on = 1;
+ _network_game_info.dedicated = false;
+ }
+
+ _network_game_info.spectators_on = 0;
+
+ _network_game_info.game_date = _date;
+ _network_game_info.start_date = ConvertYMDToDate(_patches.starting_year, 0, 1);
+ _network_game_info.map_width = MapSizeX();
+ _network_game_info.map_height = MapSizeY();
+ _network_game_info.map_set = _opt.landscape;
+
+ _network_game_info.use_password = (_network_server_password[0] != '\0');
+
+ // We use _network_client_info[MAX_CLIENT_INFO - 1] to store the server-data in it
+ // The index is NETWORK_SERVER_INDEX ( = 1)
+ ci = &_network_client_info[MAX_CLIENT_INFO - 1];
+ memset(ci, 0, sizeof(*ci));
+
+ ci->client_index = NETWORK_SERVER_INDEX;
+ ci->client_playas = _network_dedicated ? PLAYER_SPECTATOR : _local_player;
+
+ ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
+ ttd_strlcpy(ci->unique_id, _network_unique_id, sizeof(ci->unique_id));
+}
+
+bool NetworkServerStart(void)
+{
+ if (!_network_available) return false;
+
+ /* Call the pre-scripts */
+ IConsoleCmdExec("exec scripts/pre_server.scr 0");
+ if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
+
+ NetworkInitialize();
+ if (!NetworkListen()) return false;
+
+ // Try to start UDP-server
+ _network_udp_server = true;
+ _network_udp_server = NetworkUDPListen(&_udp_server_socket, _network_server_bind_ip, _network_server_port, false);
+
+ _network_server = true;
+ _networking = true;
+ _frame_counter = 0;
+ _frame_counter_server = 0;
+ _frame_counter_max = 0;
+ _last_sync_frame = 0;
+ _network_own_client_index = NETWORK_SERVER_INDEX;
+
+ /* Non-dedicated server will always be player #1 */
+ if (!_network_dedicated) _network_playas = 0;
+
+ _network_clients_connected = 0;
+
+ NetworkInitGameInfo();
+
+ // execute server initialization script
+ IConsoleCmdExec("exec scripts/on_server.scr 0");
+ // if the server is dedicated ... add some other script
+ if (_network_dedicated) IConsoleCmdExec("exec scripts/on_dedicated.scr 0");
+
+ _min_players_paused = false;
+ CheckMinPlayers();
+
+ /* Try to register us to the master server */
+ _network_last_advertise_frame = 0;
+ _network_need_advertise = true;
+ NetworkUDPAdvertise();
+ return true;
+}
+
+// The server is rebooting...
+// The only difference with NetworkDisconnect, is the packets that is sent
+void NetworkReboot(void)
+{
+ if (_network_server) {
+ NetworkClientState *cs;
+ FOR_ALL_CLIENTS(cs) {
+ SEND_COMMAND(PACKET_SERVER_NEWGAME)(cs);
+ NetworkSend_Packets(cs);
+ }
+ }
+
+ NetworkClose();
+
+ // Free all queued commands
+ while (_local_command_queue != NULL) {
+ CommandPacket *p = _local_command_queue;
+ _local_command_queue = _local_command_queue->next;
+ free(p);
+ }
+
+ _networking = false;
+ _network_server = false;
+}
+
+// We want to disconnect from the host/clients
+void NetworkDisconnect(void)
+{
+ if (_network_server) {
+ NetworkClientState *cs;
+ FOR_ALL_CLIENTS(cs) {
+ SEND_COMMAND(PACKET_SERVER_SHUTDOWN)(cs);
+ NetworkSend_Packets(cs);
+ }
+ }
+
+ if (_network_advertise) NetworkUDPRemoveAdvertise();
+
+ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+
+ NetworkClose();
+
+ // Free all queued commands
+ while (_local_command_queue != NULL) {
+ CommandPacket *p = _local_command_queue;
+ _local_command_queue = _local_command_queue->next;
+ free(p);
+ }
+
+ _networking = false;
+ _network_server = false;
+}
+
+// Receives something from the network
+static bool NetworkReceive(void)
+{
+ NetworkClientState *cs;
+ int n;
+ fd_set read_fd, write_fd;
+ struct timeval tv;
+
+ FD_ZERO(&read_fd);
+ FD_ZERO(&write_fd);
+
+ FOR_ALL_CLIENTS(cs) {
+ FD_SET(cs->socket, &read_fd);
+ FD_SET(cs->socket, &write_fd);
+ }
+
+ // take care of listener port
+ if (_network_server) FD_SET(_listensocket, &read_fd);
+
+ tv.tv_sec = tv.tv_usec = 0; // don't block at all.
+#if !defined(__MORPHOS__) && !defined(__AMIGA__)
+ n = select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
+#else
+ n = WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
+#endif
+ if (n == -1 && !_network_server) NetworkError(STR_NETWORK_ERR_LOSTCONNECTION);
+
+ // accept clients..
+ if (_network_server && FD_ISSET(_listensocket, &read_fd)) NetworkAcceptClients();
+
+ // read stuff from clients
+ FOR_ALL_CLIENTS(cs) {
+ cs->writable = !!FD_ISSET(cs->socket, &write_fd);
+ if (FD_ISSET(cs->socket, &read_fd)) {
+ if (_network_server) {
+ NetworkServer_ReadPackets(cs);
+ } else {
+ NetworkRecvStatus res;
+
+ // The client already was quiting!
+ if (cs->has_quit) return false;
+
+ res = NetworkClient_ReadPackets(cs);
+ if (res != NETWORK_RECV_STATUS_OKAY) {
+ // The client made an error of which we can not recover
+ // close the client and drop back to main menu
+ NetworkClientError(res, cs);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// This sends all buffered commands (if possible)
+static void NetworkSend(void)
+{
+ NetworkClientState *cs;
+ FOR_ALL_CLIENTS(cs) {
+ if (cs->writable) {
+ NetworkSend_Packets(cs);
+
+ if (cs->status == STATUS_MAP) {
+ // This client is in the middle of a map-send, call the function for that
+ SEND_COMMAND(PACKET_SERVER_MAP)(cs);
+ }
+ }
+ }
+}
+
+// Handle the local-command-queue
+static void NetworkHandleLocalQueue(void)
+{
+ CommandPacket *cp, **cp_prev;
+
+ cp_prev = &_local_command_queue;
+
+ while ( (cp = *cp_prev) != NULL) {
+
+ // The queue is always in order, which means
+ // that the first element will be executed first.
+ if (_frame_counter < cp->frame) break;
+
+ if (_frame_counter > cp->frame) {
+ // If we reach here, it means for whatever reason, we've already executed
+ // past the command we need to execute.
+ DEBUG(net, 0, "Trying to execute a packet in the past!");
+ assert(0);
+ }
+
+ // We can execute this command
+ NetworkExecuteCommand(cp);
+
+ *cp_prev = cp->next;
+ free(cp);
+ }
+
+ // Just a safety check, to be removed in the future.
+ // Make sure that no older command appears towards the end of the queue
+ // In that case we missed executing it. This will never happen.
+ for (cp = _local_command_queue; cp; cp = cp->next) {
+ assert(_frame_counter < cp->frame);
+ }
+
+}
+
+static bool NetworkDoClientLoop(void)
+{
+ _frame_counter++;
+
+ NetworkHandleLocalQueue();
+
+ StateGameLoop();
+
+ // Check if we are in sync!
+ if (_sync_frame != 0) {
+ if (_sync_frame == _frame_counter) {
+#ifdef NETWORK_SEND_DOUBLE_SEED
+ if (_sync_seed_1 != _random_seeds[0][0] || _sync_seed_2 != _random_seeds[0][1]) {
+#else
+ if (_sync_seed_1 != _random_seeds[0][0]) {
+#endif
+ NetworkError(STR_NETWORK_ERR_DESYNC);
+ DEBUG(net, 0, "Sync error detected!");
+ NetworkClientError(NETWORK_RECV_STATUS_DESYNC, DEREF_CLIENT(0));
+ return false;
+ }
+
+ // If this is the first time we have a sync-frame, we
+ // need to let the server know that we are ready and at the same
+ // frame as he is.. so we can start playing!
+ if (_network_first_time) {
+ _network_first_time = false;
+ SEND_COMMAND(PACKET_CLIENT_ACK)();
+ }
+
+ _sync_frame = 0;
+ } else if (_sync_frame < _frame_counter) {
+ DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
+ _sync_frame = 0;
+ }
+ }
+
+ return true;
+}
+
+// We have to do some UDP checking
+void NetworkUDPGameLoop(void)
+{
+ if (_network_udp_server) {
+ NetworkUDPReceive(_udp_server_socket);
+ if (_udp_master_socket != INVALID_SOCKET) {
+ NetworkUDPReceive(_udp_master_socket);
+ }
+ } else if (_udp_client_socket != INVALID_SOCKET) {
+ NetworkUDPReceive(_udp_client_socket);
+ if (_network_udp_broadcast > 0) _network_udp_broadcast--;
+ }
+}
+
+// The main loop called from ttd.c
+// Here we also have to do StateGameLoop if needed!
+void NetworkGameLoop(void)
+{
+ if (!_networking) return;
+
+ if (!NetworkReceive()) return;
+
+ if (_network_server) {
+ bool send_frame = false;
+
+ // We first increase the _frame_counter
+ _frame_counter++;
+ // Update max-frame-counter
+ if (_frame_counter > _frame_counter_max) {
+ _frame_counter_max = _frame_counter + _network_frame_freq;
+ send_frame = true;
+ }
+
+ NetworkHandleLocalQueue();
+
+ // Then we make the frame
+ StateGameLoop();
+
+ _sync_seed_1 = _random_seeds[0][0];
+#ifdef NETWORK_SEND_DOUBLE_SEED
+ _sync_seed_2 = _random_seeds[0][1];
+#endif
+
+ NetworkServer_Tick(send_frame);
+ } else {
+ // Client
+
+ // Make sure we are at the frame were the server is (quick-frames)
+ if (_frame_counter_server > _frame_counter) {
+ while (_frame_counter_server > _frame_counter) {
+ if (!NetworkDoClientLoop()) break;
+ }
+ } else {
+ // Else, keep on going till _frame_counter_max
+ if (_frame_counter_max > _frame_counter) NetworkDoClientLoop();
+ }
+ }
+
+ NetworkSend();
+}
+
+static void NetworkGenerateUniqueId(void)
+{
+ md5_state_t state;
+ md5_byte_t digest[16];
+ char hex_output[16*2 + 1];
+ char coding_string[NETWORK_NAME_LENGTH];
+ int di;
+
+ snprintf(coding_string, sizeof(coding_string), "%d%s", (uint)Random(), "OpenTTD Unique ID");
+
+ /* Generate the MD5 hash */
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t*)coding_string, strlen(coding_string));
+ md5_finish(&state, digest);
+
+ for (di = 0; di < 16; ++di)
+ sprintf(hex_output + di * 2, "%02x", digest[di]);
+
+ /* _network_unique_id is our id */
+ snprintf(_network_unique_id, sizeof(_network_unique_id), "%s", hex_output);
+}
+
+// This tries to launch the network for a given OS
+void NetworkStartUp(void)
+{
+ DEBUG(net, 3, "[core] starting network...");
+
+#if defined(__MORPHOS__) || defined(__AMIGA__)
+ /*
+ * IMPORTANT NOTE: SocketBase needs to be initialized before we use _any_
+ * network related function, else: crash.
+ */
+ DEBUG(net, 3, "[core] loading bsd socket library");
+ SocketBase = OpenLibrary("bsdsocket.library", 4);
+ if (SocketBase == NULL) {
+ DEBUG(net, 0, "[core] can't open bsdsocket.library version 4, network unavailable");
+ _network_available = false;
+ return;
+ }
+
+#if defined(__AMIGA__)
+ // for usleep() implementation (only required for legacy AmigaOS builds)
+ TimerPort = CreateMsgPort();
+ if (TimerPort != NULL) {
+ TimerRequest = (struct timerequest*)CreateIORequest(TimerPort, sizeof(struct timerequest);
+ if (TimerRequest != NULL) {
+ if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest*)TimerRequest, 0) == 0) {
+ TimerBase = TimerRequest->tr_node.io_Device;
+ if (TimerBase == NULL) {
+ // free ressources...
+ DEBUG(net, 0, "[core] can't initialize timer, network unavailable");
+ _network_available = false;
+ return;
+ }
+ }
+ }
+ }
+#endif // __AMIGA__
+#endif // __MORPHOS__ / __AMIGA__
+
+ // Network is available
+ _network_available = true;
+ _network_dedicated = false;
+ _network_last_advertise_frame = 0;
+ _network_need_advertise = true;
+ _network_advertise_retries = 0;
+
+ /* Load the ip from the openttd.cfg */
+ _network_server_bind_ip = inet_addr(_network_server_bind_ip_host);
+ /* And put the data back in it in case it was an invalid ip */
+ snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
+
+ /* Generate an unique id when there is none yet */
+ if (_network_unique_id[0] == '\0') NetworkGenerateUniqueId();
+
+ {
+ byte cl_max = _network_game_info.clients_max;
+ byte cp_max = _network_game_info.companies_max;
+ byte sp_max = _network_game_info.spectators_max;
+
+ memset(&_network_game_info, 0, sizeof(_network_game_info));
+ _network_game_info.clients_max = cl_max;
+ _network_game_info.companies_max = cp_max;
+ _network_game_info.spectators_max = sp_max;
+ }
+
+ // Let's load the network in windows
+ #if defined(WIN32)
+ {
+ WSADATA wsa;
+ DEBUG(net, 3, "[core] loading windows socket library");
+ if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {
+ DEBUG(net, 0, "[core] WSAStartup failed, network unavailable");
+ _network_available = false;
+ return;
+ }
+ }
+ #endif // WIN32
+
+ NetworkInitialize();
+ DEBUG(net, 3, "[core] network online, multiplayer available");
+ NetworkFindIPs();
+}
+
+// This shuts the network down
+void NetworkShutDown(void)
+{
+ NetworkDisconnect();
+ NetworkUDPClose();
+
+ DEBUG(net, 3, "[core] shutting down network");
+
+ _network_available = false;
+
+#if defined(__MORPHOS__) || defined(__AMIGA__)
+ // free allocated ressources
+#if defined(__AMIGA__)
+ if (TimerBase != NULL) CloseDevice((struct IORequest*)TimerRequest); // XXX This smells wrong
+ if (TimerRequest != NULL) DeleteIORequest(TimerRequest);
+ if (TimerPort != NULL) DeleteMsgPort(TimerPort);
+#endif
+
+ if (SocketBase != NULL) CloseLibrary(SocketBase);
+#endif
+
+#if defined(WIN32)
+ WSACleanup();
+#endif
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,212 @@
+/* $Id$ */
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+#define NOREV_STRING "norev000"
+
+#ifdef ENABLE_NETWORK
+
+#include "../player.h"
+#include "core/config.h"
+#include "core/game.h"
+
+// If this line is enable, every frame will have a sync test
+// this is not needed in normal games. Normal is like 1 sync in 100
+// frames. You can enable this if you have a lot of desyncs on a certain
+// game.
+// Remember: both client and server have to be compiled with this
+// option enabled to make it to work. If one of the two has it disabled
+// nothing will happen.
+//#define ENABLE_NETWORK_SYNC_EVERY_FRAME
+
+// In theory sending 1 of the 2 seeds is enough to check for desyncs
+// so in theory, this next define can be left off.
+//#define NETWORK_SEND_DOUBLE_SEED
+
+// How many clients can we have? Like.. MAX_PLAYERS - 1 is the amount of
+// players that can really play.. so.. a max of 4 spectators.. gives us..
+// MAX_PLAYERS + 3
+#define MAX_CLIENTS (MAX_PLAYERS + 3)
+
+
+// Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1
+#define MAX_CLIENT_INFO (MAX_CLIENTS + 1)
+
+#define MAX_INTERFACES 9
+
+
+// How many vehicle/station types we put over the network
+#define NETWORK_VEHICLE_TYPES 5
+#define NETWORK_STATION_TYPES 5
+
+typedef struct NetworkPlayerInfo {
+ char company_name[NETWORK_NAME_LENGTH]; // Company name
+ char password[NETWORK_PASSWORD_LENGTH]; // The password for the player
+ Year inaugurated_year; // What year the company started in
+ int64 company_value; // The company value
+ int64 money; // The amount of money the company has
+ int64 income; // How much did the company earned last year
+ uint16 performance; // What was his performance last month?
+ byte use_password; // 0: No password 1: There is a password
+ uint16 num_vehicle[NETWORK_VEHICLE_TYPES]; // How many vehicles are there of this type?
+ uint16 num_station[NETWORK_STATION_TYPES]; // How many stations are there of this type?
+ char players[NETWORK_PLAYERS_LENGTH]; // The players that control this company (Name1, name2, ..)
+ uint16 months_empty; // How many months the company is empty
+} NetworkPlayerInfo;
+
+typedef struct NetworkClientInfo {
+ uint16 client_index; // Index of the client (same as ClientState->index)
+ char client_name[NETWORK_CLIENT_NAME_LENGTH]; // Name of the client
+ byte client_lang; // The language of the client
+ byte client_playas; // As which player is this client playing (PlayerID)
+ uint32 client_ip; // IP-address of the client (so he can be banned)
+ Date join_date; // Gamedate the player has joined
+ char unique_id[NETWORK_NAME_LENGTH]; // Every play sends an unique id so we can indentify him
+} NetworkClientInfo;
+
+typedef struct NetworkGameList {
+ NetworkGameInfo info;
+ uint32 ip;
+ uint16 port;
+ bool online; // False if the server did not respond (default status)
+ bool manually; // True if the server was added manually
+ struct NetworkGameList *next;
+} NetworkGameList;
+
+typedef enum {
+ NETWORK_JOIN_STATUS_CONNECTING,
+ NETWORK_JOIN_STATUS_AUTHORIZING,
+ NETWORK_JOIN_STATUS_WAITING,
+ NETWORK_JOIN_STATUS_DOWNLOADING,
+ NETWORK_JOIN_STATUS_PROCESSING,
+ NETWORK_JOIN_STATUS_REGISTERING,
+
+ NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO,
+} NetworkJoinStatus;
+
+// language ids for server_lang and client_lang
+typedef enum {
+ NETLANG_ANY = 0,
+ NETLANG_ENGLISH = 1,
+ NETLANG_GERMAN = 2,
+ NETLANG_FRENCH = 3,
+} NetworkLanguage;
+
+VARDEF NetworkGameList *_network_game_list;
+
+VARDEF NetworkGameInfo _network_game_info;
+VARDEF NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
+VARDEF NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
+
+VARDEF char _network_player_name[NETWORK_CLIENT_NAME_LENGTH];
+VARDEF char _network_default_ip[NETWORK_HOSTNAME_LENGTH];
+
+VARDEF uint16 _network_own_client_index;
+VARDEF char _network_unique_id[NETWORK_NAME_LENGTH]; // Our own unique ID
+
+VARDEF uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
+VARDEF uint32 _frame_counter_max; // To where we may go with our clients
+
+VARDEF uint32 _last_sync_frame; // Used in the server to store the last time a sync packet was sent to clients.
+
+// networking settings
+VARDEF uint32 _broadcast_list[MAX_INTERFACES + 1];
+
+VARDEF uint16 _network_server_port;
+/* We use bind_ip and bind_ip_host, where bind_ip_host is the readable form of
+ bind_ip_host, and bind_ip the numeric value, because we want a nice number
+ in the openttd.cfg, but we wants to use the uint32 internally.. */
+VARDEF uint32 _network_server_bind_ip;
+VARDEF char _network_server_bind_ip_host[NETWORK_HOSTNAME_LENGTH];
+VARDEF bool _is_network_server; // Does this client wants to be a network-server?
+VARDEF char _network_server_name[NETWORK_NAME_LENGTH];
+VARDEF char _network_server_password[NETWORK_PASSWORD_LENGTH];
+VARDEF char _network_rcon_password[NETWORK_PASSWORD_LENGTH];
+
+VARDEF uint16 _network_max_join_time; ///< Time a client can max take to join
+VARDEF bool _network_pause_on_join; ///< Pause the game when a client tries to join (more chance of succeeding join)
+
+VARDEF uint16 _redirect_console_to_client;
+
+VARDEF uint16 _network_sync_freq;
+VARDEF uint8 _network_frame_freq;
+
+VARDEF uint32 _sync_seed_1, _sync_seed_2;
+VARDEF uint32 _sync_frame;
+VARDEF bool _network_first_time;
+// Vars needed for the join-GUI
+VARDEF NetworkJoinStatus _network_join_status;
+VARDEF uint8 _network_join_waiting;
+VARDEF uint16 _network_join_kbytes;
+VARDEF uint16 _network_join_kbytes_total;
+
+VARDEF char _network_last_host[NETWORK_HOSTNAME_LENGTH];
+VARDEF short _network_last_port;
+VARDEF uint32 _network_last_host_ip;
+VARDEF uint8 _network_reconnect;
+
+VARDEF bool _network_udp_server;
+VARDEF uint16 _network_udp_broadcast;
+
+VARDEF byte _network_lan_internet;
+
+VARDEF bool _network_need_advertise;
+VARDEF uint32 _network_last_advertise_frame;
+VARDEF uint8 _network_advertise_retries;
+
+VARDEF bool _network_autoclean_companies;
+VARDEF uint8 _network_autoclean_unprotected; // Remove a company after X months
+VARDEF uint8 _network_autoclean_protected; // Unprotect a company after X months
+
+VARDEF Year _network_restart_game_year; // If this year is reached, the server automaticly restarts
+VARDEF uint8 _network_min_players; // Minimum number of players for game to unpause
+
+NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info);
+
+byte NetworkSpectatorCount(void);
+
+VARDEF char *_network_host_list[10];
+VARDEF char *_network_ban_list[25];
+
+void ParseConnectionString(const char **player, const char **port, char *connection_string);
+void NetworkUpdateClientInfo(uint16 client_index);
+void NetworkAddServer(const char *b);
+void NetworkRebuildHostList(void);
+bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
+void NetworkPopulateCompanyInfo(void);
+void UpdateNetworkGameWindow(bool unselect);
+void CheckMinPlayers(void);
+
+void NetworkStartUp(void);
+void NetworkUDPClose(void);
+void NetworkShutDown(void);
+void NetworkGameLoop(void);
+void NetworkUDPGameLoop(void);
+bool NetworkServerStart(void);
+bool NetworkClientConnectGame(const char *host, uint16 port);
+void NetworkReboot(void);
+void NetworkDisconnect(void);
+
+VARDEF bool _networking; ///< are we in networking mode?
+VARDEF bool _network_server; ///< network-server is active
+VARDEF bool _network_available; ///< is network mode available?
+
+#else /* ENABLE_NETWORK */
+/* Network function stubs when networking is disabled */
+
+static inline void NetworkStartUp(void) {}
+static inline void NetworkShutDown(void) {}
+
+#define _networking 0
+#define _network_server 0
+#define _network_available 0
+
+#endif /* ENABLE_NETWORK */
+
+/* These variables must always be registered! */
+VARDEF bool _network_dedicated; ///< are we a dedicated server?
+VARDEF bool _network_advertise; ///< is the server advertising to the master server?
+VARDEF PlayerID _network_playas; ///< an id to play as.. (see players.h:Players)
+
+#endif /* NETWORK_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_client.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,819 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../stdafx.h"
+#include "../debug.h"
+#include "../string.h"
+#include "../strings.h"
+#include "network_data.h"
+#include "core/tcp.h"
+#include "../date.h"
+#include "../table/strings.h"
+#include "../functions.h"
+#include "network_client.h"
+#include "network_gamelist.h"
+#include "network_gui.h"
+#include "../saveload.h"
+#include "../command.h"
+#include "../window.h"
+#include "../console.h"
+#include "../variables.h"
+#include "../ai/ai.h"
+
+
+// This file handles all the client-commands
+
+
+// So we don't make too much typos ;)
+#define MY_CLIENT DEREF_CLIENT(0)
+
+static uint32 last_ack_frame;
+
+// **********
+// Sending functions
+// DEF_CLIENT_SEND_COMMAND has no parameters
+// **********
+
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)
+{
+ //
+ // Packet: CLIENT_COMPANY_INFO
+ // Function: Request company-info (in detail)
+ // Data:
+ // <none>
+ //
+ Packet *p;
+ _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
+ InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
+
+ p = NetworkSend_Init(PACKET_CLIENT_COMPANY_INFO);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_JOIN)
+{
+ //
+ // Packet: CLIENT_JOIN
+ // Function: Try to join the server
+ // Data:
+ // String: OpenTTD Revision (norev000 if no revision)
+ // String: Player Name (max NETWORK_NAME_LENGTH)
+ // uint8: Play as Player id (1..MAX_PLAYERS)
+ // uint8: Language ID
+ // String: Unique id to find the player back in server-listing
+ //
+
+ extern const char _openttd_revision[];
+ Packet *p;
+ _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
+ InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
+
+ p = NetworkSend_Init(PACKET_CLIENT_JOIN);
+ NetworkSend_string(p, _openttd_revision);
+ NetworkSend_string(p, _network_player_name); // Player name
+ NetworkSend_uint8(p, _network_playas); // PlayAs
+ NetworkSend_uint8(p, NETLANG_ANY); // Language
+ NetworkSend_string(p, _network_unique_id);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password)
+{
+ //
+ // Packet: CLIENT_PASSWORD
+ // Function: Send a password to the server to authorize
+ // Data:
+ // uint8: NetworkPasswordType
+ // String: Password
+ //
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_PASSWORD);
+ NetworkSend_uint8(p, type);
+ NetworkSend_string(p, password);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GETMAP)
+{
+ //
+ // Packet: CLIENT_GETMAP
+ // Function: Request the map from the server
+ // Data:
+ // <none>
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_GETMAP);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_MAP_OK)
+{
+ //
+ // Packet: CLIENT_MAP_OK
+ // Function: Tell the server that we are done receiving/loading the map
+ // Data:
+ // <none>
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_MAP_OK);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK)
+{
+ //
+ // Packet: CLIENT_ACK
+ // Function: Tell the server we are done with this frame
+ // Data:
+ // uint32: current FrameCounter of the client
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_ACK);
+
+ NetworkSend_uint32(p, _frame_counter);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+// Send a command packet to the server
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(CommandPacket *cp)
+{
+ //
+ // Packet: CLIENT_COMMAND
+ // Function: Send a DoCommand to the Server
+ // Data:
+ // uint8: PlayerID (0..MAX_PLAYERS-1)
+ // uint32: CommandID (see command.h)
+ // uint32: P1 (free variables used in DoCommand)
+ // uint32: P2
+ // uint32: Tile
+ // string: text
+ // uint8: CallBackID (see callback_table.c)
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_COMMAND);
+
+ NetworkSend_uint8(p, cp->player);
+ NetworkSend_uint32(p, cp->cmd);
+ NetworkSend_uint32(p, cp->p1);
+ NetworkSend_uint32(p, cp->p2);
+ NetworkSend_uint32(p, (uint32)cp->tile);
+ NetworkSend_string(p, cp->text);
+ NetworkSend_uint8(p, cp->callback);
+
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+// Send a chat-packet over the network
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType type, int dest, const char *msg)
+{
+ //
+ // Packet: CLIENT_CHAT
+ // Function: Send a chat-packet to the serve
+ // Data:
+ // uint8: ActionID (see network_data.h, NetworkAction)
+ // uint8: Destination Type (see network_data.h, DestType);
+ // uint8: Destination Player (1..MAX_PLAYERS)
+ // String: Message (max MAX_TEXT_MSG_LEN)
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_CHAT);
+
+ NetworkSend_uint8(p, action);
+ NetworkSend_uint8(p, type);
+ NetworkSend_uint8(p, dest);
+ NetworkSend_string(p, msg);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+// Send an error-packet over the network
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno)
+{
+ //
+ // Packet: CLIENT_ERROR
+ // Function: The client made an error and is quiting the game
+ // Data:
+ // uint8: ErrorID (see network_data.h, NetworkErrorCode)
+ //
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_ERROR);
+
+ NetworkSend_uint8(p, errorno);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password)
+{
+ //
+ // Packet: PACKET_CLIENT_SET_PASSWORD
+ // Function: Set the password for the clients current company
+ // Data:
+ // String: Password
+ //
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_PASSWORD);
+
+ NetworkSend_string(p, password);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name)
+{
+ //
+ // Packet: PACKET_CLIENT_SET_NAME
+ // Function: Gives the player a new name
+ // Data:
+ // String: Name
+ //
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_NAME);
+
+ NetworkSend_string(p, name);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+// Send an quit-packet over the network
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg)
+{
+ //
+ // Packet: CLIENT_QUIT
+ // Function: The client is quiting the game
+ // Data:
+ // String: leave-message
+ //
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_QUIT);
+
+ NetworkSend_string(p, leavemsg);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command)
+{
+ Packet *p = NetworkSend_Init(PACKET_CLIENT_RCON);
+ NetworkSend_string(p, pass);
+ NetworkSend_string(p, command);
+ NetworkSend_Packet(p, MY_CLIENT);
+}
+
+
+// **********
+// Receiving functions
+// DEF_CLIENT_RECEIVE_COMMAND has parameter: Packet *p
+// **********
+
+extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FULL)
+{
+ // We try to join a server which is full
+ _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
+ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+
+ return NETWORK_RECV_STATUS_SERVER_FULL;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_BANNED)
+{
+ // We try to join a server where we are banned
+ _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_BANNED;
+ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+
+ return NETWORK_RECV_STATUS_SERVER_BANNED;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO)
+{
+ byte company_info_version;
+ int i;
+
+ company_info_version = NetworkRecv_uint8(MY_CLIENT, p);
+
+ if (!MY_CLIENT->has_quit && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
+ byte total;
+ byte current;
+
+ total = NetworkRecv_uint8(MY_CLIENT, p);
+
+ // There is no data at all..
+ if (total == 0) return NETWORK_RECV_STATUS_CLOSE_QUERY;
+
+ current = NetworkRecv_uint8(MY_CLIENT, p);
+ if (!IsValidPlayer(current)) return NETWORK_RECV_STATUS_CLOSE_QUERY;
+
+ NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].company_name, sizeof(_network_player_info[current].company_name));
+ _network_player_info[current].inaugurated_year = NetworkRecv_uint32(MY_CLIENT, p);
+ _network_player_info[current].company_value = NetworkRecv_uint64(MY_CLIENT, p);
+ _network_player_info[current].money = NetworkRecv_uint64(MY_CLIENT, p);
+ _network_player_info[current].income = NetworkRecv_uint64(MY_CLIENT, p);
+ _network_player_info[current].performance = NetworkRecv_uint16(MY_CLIENT, p);
+ _network_player_info[current].use_password = NetworkRecv_uint8(MY_CLIENT, p);
+ for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
+ _network_player_info[current].num_vehicle[i] = NetworkRecv_uint16(MY_CLIENT, p);
+ for (i = 0; i < NETWORK_STATION_TYPES; i++)
+ _network_player_info[current].num_station[i] = NetworkRecv_uint16(MY_CLIENT, p);
+
+ NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].players, sizeof(_network_player_info[current].players));
+
+ InvalidateWindow(WC_NETWORK_WINDOW, 0);
+
+ return NETWORK_RECV_STATUS_OKAY;
+ }
+
+ return NETWORK_RECV_STATUS_CLOSE_QUERY;
+}
+
+// This packet contains info about the client (playas and name)
+// as client we save this in NetworkClientInfo, linked via 'index'
+// which is always an unique number on a server.
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
+{
+ NetworkClientInfo *ci;
+ uint16 index = NetworkRecv_uint16(MY_CLIENT, p);
+ PlayerID playas = NetworkRecv_uint8(MY_CLIENT, p);
+ char name[NETWORK_NAME_LENGTH];
+ char unique_id[NETWORK_NAME_LENGTH];
+
+ NetworkRecv_string(MY_CLIENT, p, name, sizeof(name));
+ NetworkRecv_string(MY_CLIENT, p, unique_id, sizeof(unique_id));
+
+ if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
+
+ /* Do we receive a change of data? Most likely we changed playas */
+ if (index == _network_own_client_index) _network_playas = playas;
+
+ ci = NetworkFindClientInfoFromIndex(index);
+ if (ci != NULL) {
+ if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
+ // Client name changed, display the change
+ NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", name);
+ } else if (playas != ci->client_playas) {
+ // The player changed from client-player..
+ // Do not display that for now
+ }
+
+ ci->client_playas = playas;
+ ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
+
+ InvalidateWindow(WC_CLIENT_LIST, 0);
+
+ return NETWORK_RECV_STATUS_OKAY;
+ }
+
+ // We don't have this index yet, find an empty index, and put the data there
+ ci = NetworkFindClientInfoFromIndex(NETWORK_EMPTY_INDEX);
+ if (ci != NULL) {
+ ci->client_index = index;
+ ci->client_playas = playas;
+
+ ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
+ ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
+
+ InvalidateWindow(WC_CLIENT_LIST, 0);
+
+ return NETWORK_RECV_STATUS_OKAY;
+ }
+
+ // Here the program should never ever come.....
+ return NETWORK_RECV_STATUS_MALFORMED_PACKET;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
+{
+ NetworkErrorCode error = NetworkRecv_uint8(MY_CLIENT, p);
+
+ switch (error) {
+ /* We made an error in the protocol, and our connection is closed.... */
+ case NETWORK_ERROR_NOT_AUTHORIZED:
+ case NETWORK_ERROR_NOT_EXPECTED:
+ case NETWORK_ERROR_PLAYER_MISMATCH:
+ _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR;
+ break;
+ case NETWORK_ERROR_FULL:
+ _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
+ break;
+ case NETWORK_ERROR_WRONG_REVISION:
+ _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_REVISION;
+ break;
+ case NETWORK_ERROR_WRONG_PASSWORD:
+ _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_PASSWORD;
+ break;
+ case NETWORK_ERROR_KICKED:
+ _switch_mode_errorstr = STR_NETWORK_ERR_KICKED;
+ break;
+ case NETWORK_ERROR_CHEATER:
+ _switch_mode_errorstr = STR_NETWORK_ERR_CHEATER;
+ break;
+ default:
+ _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
+ }
+
+ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+
+ return NETWORK_RECV_STATUS_SERVER_ERROR;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
+{
+ NetworkPasswordType type = NetworkRecv_uint8(MY_CLIENT, p);
+
+ switch (type) {
+ case NETWORK_GAME_PASSWORD:
+ case NETWORK_COMPANY_PASSWORD:
+ ShowNetworkNeedPassword(type);
+ return NETWORK_RECV_STATUS_OKAY;
+
+ default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
+ }
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
+{
+ _network_own_client_index = NetworkRecv_uint16(MY_CLIENT, p);
+
+ // Start receiving the map
+ SEND_COMMAND(PACKET_CLIENT_GETMAP)();
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
+{
+ _network_join_status = NETWORK_JOIN_STATUS_WAITING;
+ _network_join_waiting = NetworkRecv_uint8(MY_CLIENT, p);
+ InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
+
+ // We are put on hold for receiving the map.. we need GUI for this ;)
+ DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." );
+ DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting);
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
+{
+ static char filename[256];
+ static FILE *file_pointer;
+
+ byte maptype;
+
+ maptype = NetworkRecv_uint8(MY_CLIENT, p);
+
+ if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
+
+ // First packet, init some stuff
+ if (maptype == MAP_PACKET_START) {
+ // The name for the temp-map
+ snprintf(filename, lengthof(filename), "%s%snetwork_client.tmp", _paths.autosave_dir, PATHSEP);
+
+ file_pointer = fopen(filename, "wb");
+ if (file_pointer == NULL) {
+ _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
+ return NETWORK_RECV_STATUS_SAVEGAME;
+ }
+
+ _frame_counter = _frame_counter_server = _frame_counter_max = NetworkRecv_uint32(MY_CLIENT, p);
+
+ _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
+ _network_join_kbytes = 0;
+ _network_join_kbytes_total = NetworkRecv_uint32(MY_CLIENT, p) / 1024;
+ InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
+
+ // The first packet does not contain any more data
+ return NETWORK_RECV_STATUS_OKAY;
+ }
+
+ if (maptype == MAP_PACKET_NORMAL) {
+ // We are still receiving data, put it to the file
+ fwrite(p->buffer + p->pos, 1, p->size - p->pos, file_pointer);
+
+ _network_join_kbytes = ftell(file_pointer) / 1024;
+ InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
+ }
+
+ // Check if this was the last packet
+ if (maptype == MAP_PACKET_END) {
+ fclose(file_pointer);
+
+ _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
+ InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
+
+ /* The map is done downloading, load it */
+ if (!SafeSaveOrLoad(filename, SL_LOAD, GM_NORMAL)) {
+ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+ _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
+ return NETWORK_RECV_STATUS_SAVEGAME;
+ }
+ /* If the savegame has successfully loaded, ALL windows have been removed,
+ * only toolbar/statusbar and gamefield are visible */
+
+ _opt_ptr = &_opt; // during a network game you are always in-game
+
+ // Say we received the map and loaded it correctly!
+ SEND_COMMAND(PACKET_CLIENT_MAP_OK)();
+
+ /* New company/spectator (invalid player) or company we want to join is not active
+ * Switch local player to spectator and await the server's judgement */
+ if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayer(_network_playas) ||
+ !GetPlayer(_network_playas)->is_active) {
+
+ SetLocalPlayer(PLAYER_SPECTATOR);
+
+ if (_network_playas != PLAYER_SPECTATOR) {
+ /* We have arrived and ready to start playing; send a command to make a new player;
+ * the server will give us a client-id and let us in */
+ _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
+ ShowJoinStatusWindow();
+ NetworkSend_Command(0, 0, 0, CMD_PLAYER_CTRL, NULL);
+ }
+ } else {
+ // take control over an existing company
+ SetLocalPlayer(_network_playas);
+ }
+ }
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FRAME)
+{
+ _frame_counter_server = NetworkRecv_uint32(MY_CLIENT, p);
+ _frame_counter_max = NetworkRecv_uint32(MY_CLIENT, p);
+#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
+ // Test if the server supports this option
+ // and if we are at the frame the server is
+ if (p->pos < p->size) {
+ _sync_frame = _frame_counter_server;
+ _sync_seed_1 = NetworkRecv_uint32(MY_CLIENT, p);
+#ifdef NETWORK_SEND_DOUBLE_SEED
+ _sync_seed_2 = NetworkRecv_uint32(MY_CLIENT, p);
+#endif
+ }
+#endif
+ DEBUG(net, 5, "Received FRAME %d", _frame_counter_server);
+
+ // Let the server know that we received this frame correctly
+ // We do this only once per day, to save some bandwidth ;)
+ if (!_network_first_time && last_ack_frame < _frame_counter) {
+ last_ack_frame = _frame_counter + DAY_TICKS;
+ DEBUG(net, 4, "Sent ACK at %d", _frame_counter);
+ SEND_COMMAND(PACKET_CLIENT_ACK)();
+ }
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SYNC)
+{
+ _sync_frame = NetworkRecv_uint32(MY_CLIENT, p);
+ _sync_seed_1 = NetworkRecv_uint32(MY_CLIENT, p);
+#ifdef NETWORK_SEND_DOUBLE_SEED
+ _sync_seed_2 = NetworkRecv_uint32(MY_CLIENT, p);
+#endif
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
+{
+ CommandPacket *cp = malloc(sizeof(CommandPacket));
+ cp->player = NetworkRecv_uint8(MY_CLIENT, p);
+ cp->cmd = NetworkRecv_uint32(MY_CLIENT, p);
+ cp->p1 = NetworkRecv_uint32(MY_CLIENT, p);
+ cp->p2 = NetworkRecv_uint32(MY_CLIENT, p);
+ cp->tile = NetworkRecv_uint32(MY_CLIENT, p);
+ NetworkRecv_string(MY_CLIENT, p, cp->text, sizeof(cp->text));
+ cp->callback = NetworkRecv_uint8(MY_CLIENT, p);
+ cp->frame = NetworkRecv_uint32(MY_CLIENT, p);
+ cp->next = NULL;
+
+ // The server did send us this command..
+ // queue it in our own queue, so we can handle it in the upcoming frame!
+
+ if (_local_command_queue == NULL) {
+ _local_command_queue = cp;
+ } else {
+ // Find last packet
+ CommandPacket *c = _local_command_queue;
+ while (c->next != NULL) c = c->next;
+ c->next = cp;
+ }
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
+{
+ char name[NETWORK_NAME_LENGTH], msg[MAX_TEXT_MSG_LEN];
+ const NetworkClientInfo *ci = NULL, *ci_to;
+
+ NetworkAction action = NetworkRecv_uint8(MY_CLIENT, p);
+ uint16 index = NetworkRecv_uint16(MY_CLIENT, p);
+ bool self_send = NetworkRecv_uint8(MY_CLIENT, p);
+ NetworkRecv_string(MY_CLIENT, p, msg, MAX_TEXT_MSG_LEN);
+
+ ci_to = NetworkFindClientInfoFromIndex(index);
+ if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY;
+
+ /* Did we initiate the action locally? */
+ if (self_send) {
+ switch (action) {
+ case NETWORK_ACTION_CHAT_CLIENT:
+ /* For speaking to client we need the client-name */
+ snprintf(name, sizeof(name), "%s", ci_to->client_name);
+ ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
+ break;
+
+ /* For speaking to company or giving money, we need the player-name */
+ case NETWORK_ACTION_GIVE_MONEY:
+ if (!IsValidPlayer(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY;
+ /* fallthrough */
+ case NETWORK_ACTION_CHAT_COMPANY: {
+ StringID str = IsValidPlayer(ci_to->client_playas) ? GetPlayer(ci_to->client_playas)->name_1 : STR_NETWORK_SPECTATORS;
+
+ GetString(name, str, lastof(name));
+ ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
+ } break;
+
+ default: NOT_REACHED(); break;
+ }
+ } else {
+ /* Display message from somebody else */
+ snprintf(name, sizeof(name), "%s", ci_to->client_name);
+ ci = ci_to;
+ }
+
+ if (ci != NULL)
+ NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg);
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
+{
+ char str[100];
+ uint16 index;
+ NetworkClientInfo *ci;
+
+ index = NetworkRecv_uint16(MY_CLIENT, p);
+ GetNetworkErrorMsg(str, NetworkRecv_uint8(MY_CLIENT, p), lastof(str));
+
+ ci = NetworkFindClientInfoFromIndex(index);
+ if (ci != NULL) {
+ NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
+
+ // The client is gone, give the NetworkClientInfo free
+ ci->client_index = NETWORK_EMPTY_INDEX;
+ }
+
+ InvalidateWindow(WC_CLIENT_LIST, 0);
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
+{
+ char str[100];
+ uint16 index;
+ NetworkClientInfo *ci;
+
+ index = NetworkRecv_uint16(MY_CLIENT, p);
+ NetworkRecv_string(MY_CLIENT, p, str, lengthof(str));
+
+ ci = NetworkFindClientInfoFromIndex(index);
+ if (ci != NULL) {
+ NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
+
+ // The client is gone, give the NetworkClientInfo free
+ ci->client_index = NETWORK_EMPTY_INDEX;
+ } else {
+ DEBUG(net, 0, "Unknown client (%d) is leaving the game", index);
+ }
+
+ InvalidateWindow(WC_CLIENT_LIST, 0);
+
+ // If we come here it means we could not locate the client.. strange :s
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
+{
+ uint16 index;
+ NetworkClientInfo *ci;
+
+ index = NetworkRecv_uint16(MY_CLIENT, p);
+
+ ci = NetworkFindClientInfoFromIndex(index);
+ if (ci != NULL)
+ NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, ci->client_name, "");
+
+ InvalidateWindow(WC_CLIENT_LIST, 0);
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN)
+{
+ _switch_mode_errorstr = STR_NETWORK_SERVER_SHUTDOWN;
+
+ return NETWORK_RECV_STATUS_SERVER_ERROR;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME)
+{
+ // To trottle the reconnects a bit, every clients waits
+ // his _local_player value before reconnecting
+ // PLAYER_SPECTATOR is currently 255, so to avoid long wait periods
+ // set the max to 10.
+ _network_reconnect = min(_local_player + 1, 10);
+ _switch_mode_errorstr = STR_NETWORK_SERVER_REBOOT;
+
+ return NETWORK_RECV_STATUS_SERVER_ERROR;
+}
+
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
+{
+ char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
+ uint16 color_code;
+
+ color_code = NetworkRecv_uint16(MY_CLIENT, p);
+ NetworkRecv_string(MY_CLIENT, p, rcon_out, sizeof(rcon_out));
+
+ IConsolePrint(color_code, rcon_out);
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+
+
+// The layout for the receive-functions by the client
+typedef NetworkRecvStatus NetworkClientPacket(Packet *p);
+
+// This array matches PacketType. At an incoming
+// packet it is matches against this array
+// and that way the right function to handle that
+// packet is found.
+static NetworkClientPacket* const _network_client_packet[] = {
+ RECEIVE_COMMAND(PACKET_SERVER_FULL),
+ RECEIVE_COMMAND(PACKET_SERVER_BANNED),
+ NULL, /*PACKET_CLIENT_JOIN,*/
+ RECEIVE_COMMAND(PACKET_SERVER_ERROR),
+ NULL, /*PACKET_CLIENT_COMPANY_INFO,*/
+ RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO),
+ RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO),
+ RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD),
+ NULL, /*PACKET_CLIENT_PASSWORD,*/
+ RECEIVE_COMMAND(PACKET_SERVER_WELCOME),
+ NULL, /*PACKET_CLIENT_GETMAP,*/
+ RECEIVE_COMMAND(PACKET_SERVER_WAIT),
+ RECEIVE_COMMAND(PACKET_SERVER_MAP),
+ NULL, /*PACKET_CLIENT_MAP_OK,*/
+ RECEIVE_COMMAND(PACKET_SERVER_JOIN),
+ RECEIVE_COMMAND(PACKET_SERVER_FRAME),
+ RECEIVE_COMMAND(PACKET_SERVER_SYNC),
+ NULL, /*PACKET_CLIENT_ACK,*/
+ NULL, /*PACKET_CLIENT_COMMAND,*/
+ RECEIVE_COMMAND(PACKET_SERVER_COMMAND),
+ NULL, /*PACKET_CLIENT_CHAT,*/
+ RECEIVE_COMMAND(PACKET_SERVER_CHAT),
+ NULL, /*PACKET_CLIENT_SET_PASSWORD,*/
+ NULL, /*PACKET_CLIENT_SET_NAME,*/
+ NULL, /*PACKET_CLIENT_QUIT,*/
+ NULL, /*PACKET_CLIENT_ERROR,*/
+ RECEIVE_COMMAND(PACKET_SERVER_QUIT),
+ RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT),
+ RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN),
+ RECEIVE_COMMAND(PACKET_SERVER_NEWGAME),
+ RECEIVE_COMMAND(PACKET_SERVER_RCON),
+ NULL, /*PACKET_CLIENT_RCON,*/
+};
+
+// If this fails, check the array above with network_data.h
+assert_compile(lengthof(_network_client_packet) == PACKET_END);
+
+// Is called after a client is connected to the server
+void NetworkClient_Connected(void)
+{
+ // Set the frame-counter to 0 so nothing happens till we are ready
+ _frame_counter = 0;
+ _frame_counter_server = 0;
+ last_ack_frame = 0;
+ // Request the game-info
+ SEND_COMMAND(PACKET_CLIENT_JOIN)();
+}
+
+// Reads the packets from the socket-stream, if available
+NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs)
+{
+ Packet *p;
+ NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY;
+
+ while (res == NETWORK_RECV_STATUS_OKAY && (p = NetworkRecv_Packet(cs, &res)) != NULL) {
+ byte type = NetworkRecv_uint8(MY_CLIENT, p);
+ if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->has_quit) {
+ res = _network_client_packet[type](p);
+ } else {
+ res = NETWORK_RECV_STATUS_MALFORMED_PACKET;
+ DEBUG(net, 0, "[client] received invalid packet type %d", type);
+ }
+
+ free(p);
+ }
+
+ return res;
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_client.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,25 @@
+/* $Id$ */
+
+#ifndef NETWORK_CLIENT_H
+#define NETWORK_CLIENT_H
+
+#ifdef ENABLE_NETWORK
+
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GAME_INFO);
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(CommandPacket *cp);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType desttype, int dest, const char *msg);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name);
+DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK);
+DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command);
+
+NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs);
+void NetworkClient_Connected(void);
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_CLIENT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_data.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,106 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../stdafx.h"
+#include "../debug.h"
+#include "network_data.h"
+#include "../string.h"
+#include "network_client.h"
+#include "../command.h"
+#include "../callback_table.h"
+
+// Add a command to the local command queue
+void NetworkAddCommandQueue(NetworkClientState *cs, CommandPacket *cp)
+{
+ CommandPacket* new_cp = malloc(sizeof(*new_cp));
+
+ *new_cp = *cp;
+
+ if (cs->command_queue == NULL) {
+ cs->command_queue = new_cp;
+ } else {
+ CommandPacket *c = cs->command_queue;
+ while (c->next != NULL) c = c->next;
+ c->next = new_cp;
+ }
+}
+
+// Prepare a DoCommand to be send over the network
+void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback)
+{
+ CommandPacket *c = malloc(sizeof(CommandPacket));
+ byte temp_callback;
+
+ c->player = _local_player;
+ c->next = NULL;
+ c->tile = tile;
+ c->p1 = p1;
+ c->p2 = p2;
+ c->cmd = cmd;
+ c->callback = 0;
+
+ temp_callback = 0;
+
+ while (temp_callback < _callback_table_count && _callback_table[temp_callback] != callback)
+ temp_callback++;
+ if (temp_callback == _callback_table_count) {
+ DEBUG(net, 0, "Unknown callback. (Pointer: %p) No callback sent", callback);
+ temp_callback = 0; /* _callback_table[0] == NULL */
+ }
+
+ if (_network_server) {
+ // We are the server, so set the command to be executed next possible frame
+ c->frame = _frame_counter_max + 1;
+ } else {
+ c->frame = 0; // The client can't tell which frame, so just make it 0
+ }
+
+ ttd_strlcpy(c->text, (_cmd_text != NULL) ? _cmd_text : "", lengthof(c->text));
+
+ if (_network_server) {
+ // If we are the server, we queue the command in our 'special' queue.
+ // In theory, we could execute the command right away, but then the
+ // client on the server can do everything 1 tick faster than others.
+ // So to keep the game fair, we delay the command with 1 tick
+ // which gives about the same speed as most clients.
+ NetworkClientState *cs;
+
+ // And we queue it for delivery to the clients
+ FOR_ALL_CLIENTS(cs) {
+ if (cs->status > STATUS_AUTH) NetworkAddCommandQueue(cs, c);
+ }
+
+ // Only the server gets the callback, because clients should not get them
+ c->callback = temp_callback;
+ if (_local_command_queue == NULL) {
+ _local_command_queue = c;
+ } else {
+ // Find last packet
+ CommandPacket *cp = _local_command_queue;
+ while (cp->next != NULL) cp = cp->next;
+ cp->next = c;
+ }
+
+ return;
+ }
+
+ // Clients send their command to the server and forget all about the packet
+ c->callback = temp_callback;
+ SEND_COMMAND(PACKET_CLIENT_COMMAND)(c);
+}
+
+// Execute a DoCommand we received from the network
+void NetworkExecuteCommand(CommandPacket *cp)
+{
+ _current_player = cp->player;
+ _cmd_text = cp->text;
+ /* cp->callback is unsigned. so we don't need to do lower bounds checking. */
+ if (cp->callback > _callback_table_count) {
+ DEBUG(net, 0, "Received out-of-bounds callback (%d)", cp->callback);
+ cp->callback = 0;
+ }
+ DoCommandP(cp->tile, cp->p1, cp->p2, _callback_table[cp->callback], cp->cmd | CMD_NETWORK_COMMAND);
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_data.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,167 @@
+/* $Id$ */
+
+#ifndef NETWORK_DATA_H
+#define NETWORK_DATA_H
+
+// Is the network enabled?
+#ifdef ENABLE_NETWORK
+
+#include "../openttd.h"
+#include "network.h"
+#include "core/os_abstraction.h"
+#include "core/config.h"
+#include "core/packet.h"
+
+#define MAX_TEXT_MSG_LEN 1024 /* long long long long sentences :-) */
+
+// The client-info-server-index is always 1
+#define NETWORK_SERVER_INDEX 1
+#define NETWORK_EMPTY_INDEX 0
+
+typedef struct CommandPacket {
+ struct CommandPacket *next;
+ PlayerID player; /// player that is executing the command
+ uint32 cmd; /// command being executed
+ uint32 p1; /// parameter p1
+ uint32 p2; /// parameter p2
+ TileIndex tile; /// tile command being executed on
+ char text[80];
+ uint32 frame; /// the frame in which this packet is executed
+ byte callback; /// any callback function executed upon successful completion of the command
+} CommandPacket;
+
+typedef enum {
+ STATUS_INACTIVE,
+ STATUS_AUTH, // This means that the client is authorized
+ STATUS_MAP_WAIT, // This means that the client is put on hold because someone else is getting the map
+ STATUS_MAP,
+ STATUS_DONE_MAP,
+ STATUS_PRE_ACTIVE,
+ STATUS_ACTIVE,
+} ClientStatus;
+
+typedef enum {
+ MAP_PACKET_START,
+ MAP_PACKET_NORMAL,
+ MAP_PACKET_END,
+} MapPacket;
+
+typedef enum {
+ NETWORK_RECV_STATUS_OKAY,
+ NETWORK_RECV_STATUS_DESYNC,
+ NETWORK_RECV_STATUS_SAVEGAME,
+ NETWORK_RECV_STATUS_CONN_LOST,
+ NETWORK_RECV_STATUS_MALFORMED_PACKET,
+ NETWORK_RECV_STATUS_SERVER_ERROR, // The server told us we made an error
+ NETWORK_RECV_STATUS_SERVER_FULL,
+ NETWORK_RECV_STATUS_SERVER_BANNED,
+ NETWORK_RECV_STATUS_CLOSE_QUERY, // Done quering the server
+} NetworkRecvStatus;
+
+typedef enum {
+ NETWORK_ERROR_GENERAL, // Try to use thisone like never
+
+ // Signals from clients
+ NETWORK_ERROR_DESYNC,
+ NETWORK_ERROR_SAVEGAME_FAILED,
+ NETWORK_ERROR_CONNECTION_LOST,
+ NETWORK_ERROR_ILLEGAL_PACKET,
+
+ // Signals from servers
+ NETWORK_ERROR_NOT_AUTHORIZED,
+ NETWORK_ERROR_NOT_EXPECTED,
+ NETWORK_ERROR_WRONG_REVISION,
+ NETWORK_ERROR_NAME_IN_USE,
+ NETWORK_ERROR_WRONG_PASSWORD,
+ NETWORK_ERROR_PLAYER_MISMATCH, // Happens in CLIENT_COMMAND
+ NETWORK_ERROR_KICKED,
+ NETWORK_ERROR_CHEATER,
+ NETWORK_ERROR_FULL,
+} NetworkErrorCode;
+
+// Actions that can be used for NetworkTextMessage
+typedef enum {
+ NETWORK_ACTION_JOIN,
+ NETWORK_ACTION_LEAVE,
+ NETWORK_ACTION_SERVER_MESSAGE,
+ NETWORK_ACTION_CHAT,
+ NETWORK_ACTION_CHAT_COMPANY,
+ NETWORK_ACTION_CHAT_CLIENT,
+ NETWORK_ACTION_GIVE_MONEY,
+ NETWORK_ACTION_NAME_CHANGE,
+} NetworkAction;
+
+typedef enum {
+ NETWORK_GAME_PASSWORD,
+ NETWORK_COMPANY_PASSWORD,
+} NetworkPasswordType;
+
+// To keep the clients all together
+struct NetworkClientState { // Typedeffed in network_core/packet.h
+ SOCKET socket;
+ uint16 index;
+ uint32 last_frame;
+ uint32 last_frame_server;
+ byte lag_test; // This byte is used for lag-testing the client
+
+ ClientStatus status;
+ bool writable; // is client ready to write to?
+ bool has_quit;
+
+ Packet *packet_queue; // Packets that are awaiting delivery
+ Packet *packet_recv; // Partially received packet
+
+ CommandPacket *command_queue; // The command-queue awaiting delivery
+};
+
+typedef enum {
+ DESTTYPE_BROADCAST, ///< Send message/notice to all players (All)
+ DESTTYPE_TEAM, ///< Send message/notice to everyone playing the same company (Team)
+ DESTTYPE_CLIENT, ///< Send message/notice to only a certain player (Private)
+} DestType;
+
+CommandPacket *_local_command_queue;
+
+SOCKET _udp_client_socket; // udp client socket
+SOCKET _udp_server_socket; // udp server socket
+SOCKET _udp_master_socket; // udp master socket
+
+// Here we keep track of the clients
+// (and the client uses [0] for his own communication)
+NetworkClientState _clients[MAX_CLIENTS];
+#define DEREF_CLIENT(i) (&_clients[i])
+// This returns the NetworkClientInfo from a NetworkClientState
+#define DEREF_CLIENT_INFO(cs) (&_network_client_info[cs - _clients])
+
+// Macros to make life a bit more easier
+#define DEF_CLIENT_RECEIVE_COMMAND(type) NetworkRecvStatus NetworkPacketReceive_ ## type ## _command(Packet *p)
+#define DEF_CLIENT_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(void)
+#define DEF_CLIENT_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
+#define DEF_SERVER_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(NetworkClientState *cs, Packet *p)
+#define DEF_SERVER_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(NetworkClientState *cs)
+#define DEF_SERVER_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
+
+#define SEND_COMMAND(type) NetworkPacketSend_ ## type ## _command
+#define RECEIVE_COMMAND(type) NetworkPacketReceive_ ## type ## _command
+
+#define FOR_ALL_CLIENTS(cs) for (cs = _clients; cs != endof(_clients) && cs->socket != INVALID_SOCKET; cs++)
+#define FOR_ALL_ACTIVE_CLIENT_INFOS(ci) for (ci = _network_client_info; ci != endof(_network_client_info); ci++) if (ci->client_index != NETWORK_EMPTY_INDEX)
+
+void NetworkExecuteCommand(CommandPacket *cp);
+void NetworkAddCommandQueue(NetworkClientState *cs, CommandPacket *cp);
+
+// from network.c
+void NetworkCloseClient(NetworkClientState *cs);
+void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...);
+void NetworkGetClientName(char *clientname, size_t size, const NetworkClientState *cs);
+uint NetworkCalculateLag(const NetworkClientState *cs);
+byte NetworkGetCurrentLanguageIndex(void);
+NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
+NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
+NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index);
+unsigned long NetworkResolveHost(const char *hostname);
+char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_DATA_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_gamelist.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,74 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../stdafx.h"
+#include "../debug.h"
+#include "network_data.h"
+#include "../newgrf_config.h"
+
+// This file handles the GameList
+// Also, it handles the request to a server for data about the server
+
+/** Add a new item to the linked gamelist. If the IP and Port match
+ * return the existing item instead of adding it again
+ * @param ip the IP-address (inet_addr) of the to-be added item
+ * @param port the port the server is running on
+ * @return a point to the newly added or already existing item */
+NetworkGameList *NetworkGameListAddItem(uint32 ip, uint16 port)
+{
+ NetworkGameList *item, *prev_item;
+
+ prev_item = NULL;
+ for (item = _network_game_list; item != NULL; item = item->next) {
+ if (item->ip == ip && item->port == port) return item;
+ prev_item = item;
+ }
+
+ item = malloc(sizeof(*item));
+ memset(item, 0, sizeof(*item));
+ item->next = NULL;
+ item->ip = ip;
+ item->port = port;
+
+ if (prev_item == NULL) {
+ _network_game_list = item;
+ } else {
+ prev_item->next = item;
+ }
+ DEBUG(net, 4, "[gamelist] added server to list");
+
+ UpdateNetworkGameWindow(false);
+
+ return item;
+}
+
+/** Remove an item from the gamelist linked list
+ * @param remove pointer to the item to be removed */
+void NetworkGameListRemoveItem(NetworkGameList *remove)
+{
+ NetworkGameList *item, *prev_item;
+
+ prev_item = NULL;
+ for (item = _network_game_list; item != NULL; item = item->next) {
+ if (remove == item) {
+ if (prev_item == NULL) {
+ _network_game_list = remove->next;
+ } else {
+ prev_item->next = remove->next;
+ }
+
+ /* Remove GRFConfig information */
+ ClearGRFConfigList(&remove->info.grfconfig);
+ free(remove);
+ remove = NULL;
+
+ DEBUG(net, 4, "[gamelist] removed server from list");
+ UpdateNetworkGameWindow(false);
+ return;
+ }
+ prev_item = item;
+ }
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_gamelist.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,11 @@
+/* $Id$ */
+
+#ifndef NETWORK_GAMELIST_H
+#define NETWORK_GAMELIST_H
+
+void NetworkGameListClear(void);
+NetworkGameList *NetworkGameListAddItem(uint32 ip, uint16 port);
+void NetworkGameListRemoveItem(NetworkGameList *remove);
+void NetworkGameListAddQueriedItem(const NetworkGameInfo *info, bool server_online);
+
+#endif /* NETWORK_GAMELIST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,1706 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+#include "../stdafx.h"
+#include "../openttd.h"
+#include "../string.h"
+#include "../strings.h"
+#include "../table/sprites.h"
+#include "network.h"
+#include "../date.h"
+
+#include "../fios.h"
+#include "../table/strings.h"
+#include "../functions.h"
+#include "network_data.h"
+#include "network_client.h"
+#include "network_gui.h"
+#include "network_gamelist.h"
+#include "../window.h"
+#include "../gui.h"
+#include "../gfx.h"
+#include "../command.h"
+#include "../variables.h"
+#include "network_server.h"
+#include "network_udp.h"
+#include "../settings.h"
+#include "../string.h"
+#include "../town.h"
+#include "../newgrf.h"
+
+#define BGC 5
+#define BTC 15
+
+typedef struct network_d {
+ PlayerID company; // select company in network lobby
+ byte field; // select text-field in start-server and game-listing
+ NetworkGameList *server; // selected server in lobby and game-listing
+ FiosItem *map; // selected map in start-server
+} network_d;
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_d));
+
+typedef struct network_ql_d {
+ network_d n; // see above; general stuff
+ querystr_d q; // text-input in start-server and game-listing
+ NetworkGameList **sort_list; // list of games (sorted)
+ list_d l; // accompanying list-administration
+} network_ql_d;
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_ql_d));
+
+/* Global to remember sorting after window has been closed */
+static Listing _ng_sorting;
+
+static char _edit_str_buf[150];
+static bool _chat_tab_completion_active;
+
+static void ShowNetworkStartServerWindow(void);
+static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
+extern void SwitchMode(int new_mode);
+
+static const StringID _connection_types_dropdown[] = {
+ STR_NETWORK_LAN_INTERNET,
+ STR_NETWORK_INTERNET_ADVERTISE,
+ INVALID_STRING_ID
+};
+
+static const StringID _lan_internet_types_dropdown[] = {
+ STR_NETWORK_LAN,
+ STR_NETWORK_INTERNET,
+ INVALID_STRING_ID
+};
+
+static const StringID _players_dropdown[] = {
+ STR_NETWORK_0_PLAYERS,
+ STR_NETWORK_1_PLAYERS,
+ STR_NETWORK_2_PLAYERS,
+ STR_NETWORK_3_PLAYERS,
+ STR_NETWORK_4_PLAYERS,
+ STR_NETWORK_5_PLAYERS,
+ STR_NETWORK_6_PLAYERS,
+ STR_NETWORK_7_PLAYERS,
+ STR_NETWORK_8_PLAYERS,
+ STR_NETWORK_9_PLAYERS,
+ STR_NETWORK_10_PLAYERS,
+ INVALID_STRING_ID
+};
+
+static const StringID _language_dropdown[] = {
+ STR_NETWORK_LANG_ANY,
+ STR_NETWORK_LANG_ENGLISH,
+ STR_NETWORK_LANG_GERMAN,
+ STR_NETWORK_LANG_FRENCH,
+ INVALID_STRING_ID
+};
+
+enum {
+ NET_PRC__OFFSET_TOP_WIDGET = 54,
+ NET_PRC__OFFSET_TOP_WIDGET_COMPANY = 52,
+ NET_PRC__SIZE_OF_ROW = 14,
+};
+
+/** Update the network new window because a new server is
+ * found on the network.
+ * @param unselect unselect the currently selected item */
+void UpdateNetworkGameWindow(bool unselect)
+{
+ SendWindowMessage(WC_NETWORK_WINDOW, 0, unselect, 0, 0);
+}
+
+static bool _internal_sort_order; // Used for Qsort order-flipping
+typedef int CDECL NGameNameSortFunction(const void*, const void*);
+
+/** Qsort function to sort by name. */
+static int CDECL NGameNameSorter(const void *a, const void *b)
+{
+ const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
+ const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
+ int r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
+
+ return _internal_sort_order ? -r : r;
+}
+
+/** Qsort function to sort by the amount of clients online on a
+ * server. If the two servers have the same amount, the one with the
+ * higher maximum is preferred. */
+static int CDECL NGameClientSorter(const void *a, const void *b)
+{
+ const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
+ const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
+ /* Reverse as per default we are interested in most-clients first */
+ int r = cmp1->info.clients_on - cmp2->info.clients_on;
+
+ if (r == 0) r = cmp1->info.clients_max - cmp2->info.clients_max;
+ if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
+
+ return _internal_sort_order ? -r : r;
+}
+
+/** Qsort function to sort by joinability. If both servers are the
+ * same, prefer the non-passworded server first. */
+static int CDECL NGameAllowedSorter(const void *a, const void *b)
+{
+ const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
+ const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
+ /* Reverse default as we are interested in compatible clients first */
+ int r = cmp2->info.compatible - cmp1->info.compatible;
+
+ if (r == 0) r = cmp1->info.use_password - cmp2->info.use_password;
+ if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
+
+ return _internal_sort_order ? -r : r;
+}
+
+/** (Re)build the network game list as its amount has changed because
+ * an item has been added or deleted for example
+ * @param ngl list_d struct that contains all necessary information for sorting */
+static void BuildNetworkGameList(network_ql_d *nqld)
+{
+ NetworkGameList *ngl_temp;
+ uint n = 0;
+
+ if (!(nqld->l.flags & VL_REBUILD)) return;
+
+ /* Count the number of games in the list */
+ for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
+ if (n == 0) return;
+
+ /* Create temporary array of games to use for listing */
+ free(nqld->sort_list);
+ nqld->sort_list = malloc(n * sizeof(nqld->sort_list[0]));
+ if (nqld->sort_list == NULL) error("Could not allocate memory for the network-game-sorting-list");
+ nqld->l.list_length = n;
+
+ for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
+ nqld->sort_list[n++] = ngl_temp;
+ }
+
+ /* Force resort */
+ nqld->l.flags &= ~VL_REBUILD;
+ nqld->l.flags |= VL_RESORT;
+}
+
+static void SortNetworkGameList(network_ql_d *nqld)
+{
+ static NGameNameSortFunction * const ngame_sorter[] = {
+ &NGameNameSorter,
+ &NGameClientSorter,
+ &NGameAllowedSorter
+ };
+
+ NetworkGameList *item;
+ uint i;
+
+ if (!(nqld->l.flags & VL_RESORT)) return;
+ if (nqld->l.list_length == 0) return;
+
+ _internal_sort_order = !!(nqld->l.flags & VL_DESC);
+ qsort(nqld->sort_list, nqld->l.list_length, sizeof(nqld->sort_list[0]), ngame_sorter[nqld->l.sort_type]);
+
+ /* After sorting ngl->sort_list contains the sorted items. Put these back
+ * into the original list. Basically nothing has changed, we are only
+ * shuffling the ->next pointers */
+ _network_game_list = nqld->sort_list[0];
+ for (item = _network_game_list, i = 1; i != nqld->l.list_length; i++) {
+ item->next = nqld->sort_list[i];
+ item = item->next;
+ }
+ item->next = NULL;
+
+ nqld->l.flags &= ~VL_RESORT;
+}
+
+/* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
+static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
+{
+ network_d *nd = &WP(w, network_ql_d).n;
+ list_d *ld = &WP(w, network_ql_d).l;
+
+ switch (e->event) {
+ case WE_CREATE: /* Focus input box */
+ nd->field = 3;
+ nd->server = NULL;
+
+ WP(w, network_ql_d).sort_list = NULL;
+ ld->flags = VL_REBUILD | (_ng_sorting.order << (VL_DESC - 1));
+ ld->sort_type = _ng_sorting.criteria;
+ break;
+
+ case WE_PAINT: {
+ const NetworkGameList *sel = nd->server;
+ const char *arrow = (ld->flags & VL_DESC) ? DOWNARROW : UPARROW;
+
+ if (ld->flags & VL_REBUILD) {
+ BuildNetworkGameList(&WP(w, network_ql_d));
+ SetVScrollCount(w, ld->list_length);
+ }
+ if (ld->flags & VL_RESORT) SortNetworkGameList(&WP(w, network_ql_d));
+
+ SetWindowWidgetDisabledState(w, 17, sel == NULL);
+ /* Join Button disabling conditions */
+ SetWindowWidgetDisabledState(w, 16, sel == NULL || // no Selected Server
+ !sel->online || // Server offline
+ sel->info.clients_on >= sel->info.clients_max || // Server full
+ !sel->info.compatible); // Revision mismatch
+
+ SetWindowWidgetHiddenState(w, 18, sel == NULL ||
+ !sel->online ||
+ sel->info.grfconfig == NULL);
+
+ SetDParam(0, 0x00);
+ SetDParam(7, _lan_internet_types_dropdown[_network_lan_internet]);
+ DrawWindowWidgets(w);
+
+ DrawEditBox(w, &WP(w, network_ql_d).q, 3);
+
+ DrawString(9, 23, STR_NETWORK_CONNECTION, 2);
+ DrawString(210, 23, STR_NETWORK_PLAYER_NAME, 2);
+
+ /* Sort based on widgets: name, clients, compatibility */
+ switch (ld->sort_type) {
+ case 6 - 6: DoDrawString(arrow, w->widget[6].right - 10, 42, 0x10); break;
+ case 7 - 6: DoDrawString(arrow, w->widget[7].right - 10, 42, 0x10); break;
+ case 8 - 6: DoDrawString(arrow, w->widget[8].right - 10, 42, 0x10); break;
+ }
+
+ { // draw list of games
+ uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
+ int32 n = 0;
+ int32 pos = w->vscroll.pos;
+ uint max_name_width = w->widget[6].right - w->widget[6].left - 5;
+ const NetworkGameList *cur_item = _network_game_list;
+
+ while (pos > 0 && cur_item != NULL) {
+ pos--;
+ cur_item = cur_item->next;
+ }
+
+ while (cur_item != NULL) {
+ // show highlighted item with a different colour
+ if (cur_item == sel) GfxFillRect(w->widget[6].left + 1, y - 2, w->widget[8].right - 1, y + 9, 10);
+
+ SetDParamStr(0, cur_item->info.server_name);
+ DrawStringTruncated(w->widget[6].left + 5, y, STR_02BD, 16, max_name_width);
+
+ SetDParam(0, cur_item->info.clients_on);
+ SetDParam(1, cur_item->info.clients_max);
+ SetDParam(2, cur_item->info.companies_on);
+ SetDParam(3, cur_item->info.companies_max);
+ DrawStringCentered(210, y, STR_NETWORK_GENERAL_ONLINE, 2);
+
+ // only draw icons if the server is online
+ if (cur_item->online) {
+ // draw a lock if the server is password protected.
+ if (cur_item->info.use_password) DrawSprite(SPR_LOCK, w->widget[8].left + 5, y - 1);
+
+ // draw red or green icon, depending on compatibility with server.
+ DrawSprite(SPR_BLOT | (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), w->widget[8].left + 15, y);
+
+ // draw flag according to server language
+ DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, w->widget[8].left + 25, y);
+ }
+
+ cur_item = cur_item->next;
+ y += NET_PRC__SIZE_OF_ROW;
+ if (++n == w->vscroll.cap) break; // max number of games in the window
+ }
+ }
+
+ /* Draw the right menu */
+ GfxFillRect(311, 43, 539, 92, 157);
+ if (sel == NULL) {
+ DrawStringCentered(425, 58, STR_NETWORK_GAME_INFO, 0);
+ } else if (!sel->online) {
+ SetDParamStr(0, sel->info.server_name);
+ DrawStringCentered(425, 68, STR_ORANGE, 0); // game name
+
+ DrawStringCentered(425, 132, STR_NETWORK_SERVER_OFFLINE, 0); // server offline
+ } else { // show game info
+ uint16 y = 100;
+ const uint16 x = w->widget[15].left + 5;
+
+ DrawStringCentered(425, 48, STR_NETWORK_GAME_INFO, 0);
+
+
+ SetDParamStr(0, sel->info.server_name);
+ DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 62, STR_ORANGE, 16); // game name
+
+ SetDParamStr(0, sel->info.map_name);
+ DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 74, STR_02BD, 16); // map name
+
+ SetDParam(0, sel->info.clients_on);
+ SetDParam(1, sel->info.clients_max);
+ SetDParam(2, sel->info.companies_on);
+ SetDParam(3, sel->info.companies_max);
+ DrawString(x, y, STR_NETWORK_CLIENTS, 2);
+ y += 10;
+
+ SetDParam(0, _language_dropdown[sel->info.server_lang]);
+ DrawString(x, y, STR_NETWORK_LANGUAGE, 2); // server language
+ y += 10;
+
+ SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
+ DrawString(x, y, STR_NETWORK_TILESET, 2); // tileset
+ y += 10;
+
+ SetDParam(0, sel->info.map_width);
+ SetDParam(1, sel->info.map_height);
+ DrawString(x, y, STR_NETWORK_MAP_SIZE, 2); // map size
+ y += 10;
+
+ SetDParamStr(0, sel->info.server_revision);
+ DrawString(x, y, STR_NETWORK_SERVER_VERSION, 2); // server version
+ y += 10;
+
+ SetDParamStr(0, sel->info.hostname);
+ SetDParam(1, sel->port);
+ DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, 2); // server address
+ y += 10;
+
+ SetDParam(0, sel->info.start_date);
+ DrawString(x, y, STR_NETWORK_START_DATE, 2); // start date
+ y += 10;
+
+ SetDParam(0, sel->info.game_date);
+ DrawString(x, y, STR_NETWORK_CURRENT_DATE, 2); // current date
+ y += 10;
+
+ y += 2;
+
+ if (!sel->info.compatible) {
+ DrawStringCentered(425, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, 0); // server mismatch
+ } else if (sel->info.clients_on == sel->info.clients_max) {
+ // Show: server full, when clients_on == clients_max
+ DrawStringCentered(425, y, STR_NETWORK_SERVER_FULL, 0); // server full
+ } else if (sel->info.use_password) {
+ DrawStringCentered(425, y, STR_NETWORK_PASSWORD, 0); // password warning
+ }
+
+ y += 10;
+ }
+ } break;
+
+ case WE_CLICK:
+ nd->field = e->we.click.widget;
+ switch (e->we.click.widget) {
+ case 0: case 14: /* Close 'X' | Cancel button */
+ DeleteWindowById(WC_NETWORK_WINDOW, 0);
+ break;
+ case 4: case 5:
+ ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0, 0); // do it for widget 5
+ break;
+ case 6: /* Sort by name */
+ case 7: /* Sort by connected clients */
+ case 8: /* Connectivity (green dot) */
+ if (ld->sort_type == e->we.click.widget - 6) ld->flags ^= VL_DESC;
+ ld->flags |= VL_RESORT;
+ ld->sort_type = e->we.click.widget - 6;
+
+ _ng_sorting.order = !!(ld->flags & VL_DESC);
+ _ng_sorting.criteria = ld->sort_type;
+ SetWindowDirty(w);
+ break;
+ case 9: { /* Matrix to show networkgames */
+ NetworkGameList *cur_item;
+ uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
+
+ if (id_v >= w->vscroll.cap) return; // click out of bounds
+ id_v += w->vscroll.pos;
+
+ cur_item = _network_game_list;
+ for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
+
+ nd->server = cur_item;
+ SetWindowDirty(w);
+ } break;
+ case 11: /* Find server automatically */
+ switch (_network_lan_internet) {
+ case 0: NetworkUDPSearchGame(); break;
+ case 1: NetworkUDPQueryMasterServer(); break;
+ }
+ break;
+ case 12: { // Add a server
+ ShowQueryString(
+ BindCString(_network_default_ip),
+ STR_NETWORK_ENTER_IP,
+ 31 | 0x1000, // maximum number of characters OR
+ 250, // characters up to this width pixels, whichever is satisfied first
+ w, CS_ALPHANUMERAL);
+ } break;
+ case 13: /* Start server */
+ ShowNetworkStartServerWindow();
+ break;
+ case 16: /* Join Game */
+ if (nd->server != NULL) {
+ snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&nd->server->ip));
+ _network_last_port = nd->server->port;
+ ShowNetworkLobbyWindow(nd->server);
+ }
+ break;
+ case 17: // Refresh
+ if (nd->server != NULL)
+ NetworkQueryServer(nd->server->info.hostname, nd->server->port, true);
+ break;
+ case 18: // NewGRF Settings
+ if (nd->server != NULL) ShowNewGRFSettings(false, false, false, &nd->server->info.grfconfig);
+ break;
+
+ } break;
+
+ case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
+ switch (e->we.dropdown.button) {
+ case 5:
+ _network_lan_internet = e->we.dropdown.index;
+ break;
+ }
+
+ SetWindowDirty(w);
+ break;
+
+ case WE_MOUSELOOP:
+ if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
+ break;
+
+ case WE_MESSAGE:
+ if (e->we.message.msg != 0) nd->server = NULL;
+ ld->flags |= VL_REBUILD;
+ SetWindowDirty(w);
+ break;
+
+ case WE_KEYPRESS:
+ if (nd->field != 3) {
+ if (nd->server != NULL) {
+ if (e->we.keypress.keycode == WKC_DELETE) { /* Press 'delete' to remove servers */
+ NetworkGameListRemoveItem(nd->server);
+ NetworkRebuildHostList();
+ nd->server = NULL;
+ }
+ }
+ break;
+ }
+
+ if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
+
+ // The name is only allowed when it starts with a letter!
+ if (_edit_str_buf[0] != '\0' && _edit_str_buf[0] != ' ') {
+ ttd_strlcpy(_network_player_name, _edit_str_buf, lengthof(_network_player_name));
+ } else {
+ ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
+ }
+
+ break;
+
+ case WE_ON_EDIT_TEXT:
+ NetworkAddServer(e->we.edittext.str);
+ NetworkRebuildHostList();
+ break;
+
+ case WE_DESTROY: /* Nicely clean up the sort-list */
+ free(WP(w, network_ql_d).sort_list);
+ break;
+ }
+}
+
+static const Widget _network_game_window_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 549, 0, 13, STR_NETWORK_MULTIPLAYER, STR_NULL},
+{ WWT_PANEL, RESIZE_NONE, BGC, 0, 549, 14, 263, 0x0, STR_NULL},
+
+/* LEFT SIDE */
+{ WWT_PANEL, RESIZE_NONE, BGC, 310, 461, 22, 33, 0x0, STR_NETWORK_ENTER_NAME_TIP},
+
+{ WWT_INSET, RESIZE_NONE, BGC, 90, 181, 22, 33, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TIP},
+{ WWT_TEXTBTN, RESIZE_NONE, BGC, 170, 180, 23, 32, STR_0225, STR_NETWORK_CONNECTION_TIP},
+
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 170, 42, 53, STR_NETWORK_GAME_NAME, STR_NETWORK_GAME_NAME_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 171, 250, 42, 53, STR_NETWORK_CLIENTS_CAPTION, STR_NETWORK_CLIENTS_CAPTION_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 251, 290, 42, 53, STR_EMPTY, STR_NETWORK_INFO_ICONS_TIP},
+
+{ WWT_MATRIX, RESIZE_NONE, BGC, 10, 290, 54, 236, (13 << 8) + 1, STR_NETWORK_CLICK_GAME_TO_SELECT},
+{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 291, 302, 42, 236, STR_NULL, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 30, 130, 246, 257, STR_NETWORK_FIND_SERVER, STR_NETWORK_FIND_SERVER_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 180, 280, 246, 257, STR_NETWORK_ADD_SERVER, STR_NETWORK_ADD_SERVER_TIP},
+
+/* RIGHT SIDE */
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 315, 415, 246, 257, STR_NETWORK_START_SERVER, STR_NETWORK_START_SERVER_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 246, 257, STR_012E_CANCEL, STR_NULL},
+
+{ WWT_PANEL, RESIZE_NONE, BGC, 310, 540, 42, 236, 0x0, STR_NULL},
+
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 315, 415, 215, 226, STR_NETWORK_JOIN_GAME, STR_NULL},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 215, 226, STR_NETWORK_REFRESH, STR_NETWORK_REFRESH_TIP},
+
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 197, 208, STR_NEWGRF_SETTINGS_BUTTON, STR_NULL},
+
+{ WIDGETS_END},
+};
+
+static const WindowDesc _network_game_window_desc = {
+ WDP_CENTER, WDP_CENTER, 550, 264,
+ WC_NETWORK_WINDOW,0,
+ WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+ _network_game_window_widgets,
+ NetworkGameWindowWndProc,
+};
+
+void ShowNetworkGameWindow(void)
+{
+ static bool first = true;
+ Window *w;
+ DeleteWindowById(WC_NETWORK_WINDOW, 0);
+
+ /* Only show once */
+ if (first) {
+ char* const *srv;
+
+ first = false;
+ // add all servers from the config file to our list
+ for (srv = &_network_host_list[0]; srv != endof(_network_host_list) && *srv != NULL; srv++) {
+ NetworkAddServer(*srv);
+ }
+
+ _ng_sorting.criteria = 2; // sort default by collectivity (green-dots on top)
+ _ng_sorting.order = 0; // sort ascending by default
+ }
+
+ w = AllocateWindowDesc(&_network_game_window_desc);
+ if (w != NULL) {
+ querystr_d *querystr = &WP(w, network_ql_d).q;
+
+ ttd_strlcpy(_edit_str_buf, _network_player_name, lengthof(_edit_str_buf));
+ w->vscroll.cap = 13;
+
+ querystr->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&querystr->text, _edit_str_buf, lengthof(_edit_str_buf), 120);
+
+ UpdateNetworkGameWindow(true);
+ }
+}
+
+enum {
+ NSSWND_START = 64,
+ NSSWND_ROWSIZE = 12
+};
+
+/* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
+static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
+{
+ network_d *nd = &WP(w, network_ql_d).n;
+
+ switch (e->event) {
+ case WE_CREATE: /* focus input box */
+ nd->field = 3;
+ _network_game_info.use_password = (_network_server_password[0] != '\0');
+ break;
+
+ case WE_PAINT: {
+ int y = NSSWND_START, pos;
+ const FiosItem *item;
+
+ SetDParam( 7, _connection_types_dropdown[_network_advertise]);
+ SetDParam( 9, _players_dropdown[_network_game_info.clients_max]);
+ SetDParam(11, _players_dropdown[_network_game_info.companies_max]);
+ SetDParam(13, _players_dropdown[_network_game_info.spectators_max]);
+ SetDParam(15, _language_dropdown[_network_game_info.server_lang]);
+ DrawWindowWidgets(w);
+
+ GfxFillRect(11, 63, 258, 215, 0xD7);
+ DrawEditBox(w, &WP(w, network_ql_d).q, 3);
+
+ DrawString(10, 22, STR_NETWORK_NEW_GAME_NAME, 2);
+
+ DrawString(10, 43, STR_NETWORK_SELECT_MAP, 2);
+
+ DrawString(280, 63, STR_NETWORK_CONNECTION, 2);
+ DrawString(280, 95, STR_NETWORK_NUMBER_OF_CLIENTS, 2);
+ DrawString(280, 127, STR_NETWORK_NUMBER_OF_COMPANIES, 2);
+ DrawString(280, 159, STR_NETWORK_NUMBER_OF_SPECTATORS, 2);
+ DrawString(280, 191, STR_NETWORK_LANGUAGE_SPOKEN, 2);
+
+ if (_network_game_info.use_password) DoDrawString("*", 408, 23, 3);
+
+ // draw list of maps
+ pos = w->vscroll.pos;
+ while (pos < _fios_num + 1) {
+ item = _fios_list + pos - 1;
+ if (item == nd->map || (pos == 0 && nd->map == NULL))
+ GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
+
+ if (pos == 0) {
+ DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, 9);
+ } else {
+ DoDrawString(item->title, 14, y, _fios_colors[item->type] );
+ }
+ pos++;
+ y += NSSWND_ROWSIZE;
+
+ if (y >= w->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
+ }
+ } break;
+
+ case WE_CLICK:
+ nd->field = e->we.click.widget;
+ switch (e->we.click.widget) {
+ case 0: /* Close 'X' */
+ case 19: /* Cancel button */
+ ShowNetworkGameWindow();
+ break;
+
+ case 4: /* Set password button */
+ ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
+ break;
+
+ case 5: { /* Select map */
+ int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
+
+ y += w->vscroll.pos;
+ if (y >= w->vscroll.count) return;
+
+ nd->map = (y == 0) ? NULL : _fios_list + y - 1;
+ SetWindowDirty(w);
+ } break;
+ case 7: case 8: /* Connection type */
+ ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
+ break;
+ case 9: case 10: /* Number of Players (hide 0 and 1 players) */
+ ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max, 10, 0, 3);
+ break;
+ case 11: case 12: /* Number of Companies (hide 0, 9 and 10 companies; max is 8) */
+ ShowDropDownMenu(w, _players_dropdown, _network_game_info.companies_max, 12, 0, 1537);
+ break;
+ case 13: case 14: /* Number of Spectators */
+ ShowDropDownMenu(w, _players_dropdown, _network_game_info.spectators_max, 14, 0, 0);
+ break;
+ case 15: case 16: /* Language */
+ ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 16, 0, 0);
+ break;
+ case 17: /* Start game */
+ _is_network_server = true;
+
+ if (nd->map == NULL) { // start random new game
+ ShowGenerateLandscape();
+ } else { // load a scenario
+ char *name = FiosBrowseTo(nd->map);
+ if (name != NULL) {
+ SetFiosType(nd->map->type);
+ ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+ ttd_strlcpy(_file_to_saveload.title, nd->map->title, sizeof(_file_to_saveload.title));
+
+ DeleteWindow(w);
+ SwitchMode(SM_START_SCENARIO);
+ }
+ }
+ break;
+ case 18: /* Load game */
+ _is_network_server = true;
+ /* XXX - WC_NETWORK_WINDOW should stay, but if it stays, it gets
+ * copied all the elements of 'load game' and upon closing that, it segfaults */
+ DeleteWindowById(WC_NETWORK_WINDOW, 0);
+ ShowSaveLoadDialog(SLD_LOAD_GAME);
+ break;
+ }
+ break;
+
+ case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
+ switch (e->we.dropdown.button) {
+ case 8: _network_advertise = (e->we.dropdown.index != 0); break;
+ case 10: _network_game_info.clients_max = e->we.dropdown.index; break;
+ case 12: _network_game_info.companies_max = e->we.dropdown.index; break;
+ case 14: _network_game_info.spectators_max = e->we.dropdown.index; break;
+ case 16: _network_game_info.server_lang = e->we.dropdown.index; break;
+ }
+
+ SetWindowDirty(w);
+ break;
+
+ case WE_MOUSELOOP:
+ if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
+ break;
+
+ case WE_KEYPRESS:
+ if (nd->field == 3) {
+ if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
+
+ ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
+ UpdateTextBufferSize(&WP(w, network_ql_d).q.text);
+ }
+ break;
+
+ case WE_ON_EDIT_TEXT: {
+ ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
+ _network_game_info.use_password = (_network_server_password[0] != '\0');
+ SetWindowDirty(w);
+ } break;
+ }
+}
+
+static const Widget _network_start_server_window_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
+{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 419, 0, 13, STR_NETWORK_START_GAME_WINDOW, STR_NULL},
+{ WWT_PANEL, RESIZE_NONE, BGC, 0, 419, 14, 243, 0x0, STR_NULL},
+
+{ WWT_PANEL, RESIZE_NONE, BGC, 100, 272, 22, 33, 0x0, STR_NETWORK_NEW_GAME_NAME_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 285, 405, 22, 33, STR_NETWORK_SET_PASSWORD, STR_NETWORK_PASSWORD_TIP},
+
+{ WWT_INSET, RESIZE_NONE, BGC, 10, 271, 62, 216, 0x0, STR_NETWORK_SELECT_MAP_TIP},
+{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 259, 270, 63, 215, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+/* Combo boxes to control Connection Type / Max Clients / Max Companies / Max Observers / Language */
+{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 77, 88, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TIP},
+{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 78, 87, STR_0225, STR_NETWORK_CONNECTION_TIP},
+{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 109, 120, STR_NETWORK_COMBO2, STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
+{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 110, 119, STR_0225, STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
+{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 141, 152, STR_NETWORK_COMBO3, STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
+{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 142, 151, STR_0225, STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
+{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 173, 184, STR_NETWORK_COMBO4, STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
+{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 174, 183, STR_0225, STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
+{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 205, 216, STR_NETWORK_COMBO5, STR_NETWORK_LANGUAGE_TIP},
+{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 206, 215, STR_0225, STR_NETWORK_LANGUAGE_TIP},
+
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 40, 140, 224, 235, STR_NETWORK_START_GAME, STR_NETWORK_START_GAME_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 150, 250, 224, 235, STR_NETWORK_LOAD_GAME, STR_NETWORK_LOAD_GAME_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 260, 360, 224, 235, STR_012E_CANCEL, STR_NULL},
+{ WIDGETS_END},
+};
+
+static const WindowDesc _network_start_server_window_desc = {
+ WDP_CENTER, WDP_CENTER, 420, 244,
+ WC_NETWORK_WINDOW,0,
+ WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+ _network_start_server_window_widgets,
+ NetworkStartServerWindowWndProc,
+};
+
+static void ShowNetworkStartServerWindow(void)
+{
+ Window *w;
+ DeleteWindowById(WC_NETWORK_WINDOW, 0);
+
+ w = AllocateWindowDesc(&_network_start_server_window_desc);
+ ttd_strlcpy(_edit_str_buf, _network_server_name, lengthof(_edit_str_buf));
+
+ _saveload_mode = SLD_NEW_GAME;
+ BuildFileList();
+ w->vscroll.cap = 12;
+ w->vscroll.count = _fios_num+1;
+
+ WP(w, network_ql_d).q.afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&WP(w, network_ql_d).q.text, _edit_str_buf, lengthof(_edit_str_buf), 160);
+}
+
+static byte NetworkLobbyFindCompanyIndex(byte pos)
+{
+ byte i;
+
+ /* Scroll through all _network_player_info and get the 'pos' item
+ that is not empty */
+ for (i = 0; i < MAX_PLAYERS; i++) {
+ if (_network_player_info[i].company_name[0] != '\0') {
+ if (pos-- == 0) return i;
+ }
+ }
+
+ return 0;
+}
+
+/* uses network_d WP macro */
+static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e)
+{
+ network_d *nd = &WP(w, network_d);
+
+ switch (e->event) {
+ case WE_CREATE:
+ nd->company = (byte)-1;
+ break;
+
+ case WE_PAINT: {
+ const NetworkGameInfo *gi = &nd->server->info;
+ int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
+
+ SetWindowWidgetDisabledState(w, 7, nd->company == (byte)-1);
+ SetWindowWidgetDisabledState(w, 8, gi->companies_on >= gi->companies_max);
+ /* You can not join a server as spectator when it has no companies active..
+ * it causes some nasty crashes */
+ SetWindowWidgetDisabledState(w, 9, gi->spectators_on >= gi->spectators_max ||
+ gi->companies_on == 0);
+
+ DrawWindowWidgets(w);
+
+ SetDParamStr(0, gi->server_name);
+ DrawString(10, 22, STR_NETWORK_PREPARE_TO_JOIN, 2);
+
+ /* Draw company list */
+ pos = w->vscroll.pos;
+ while (pos < gi->companies_on) {
+ byte company = NetworkLobbyFindCompanyIndex(pos);
+ bool income = false;
+ if (nd->company == company)
+ GfxFillRect(11, y - 1, 154, y + 10, 10); // show highlighted item with a different colour
+
+ DoDrawStringTruncated(_network_player_info[company].company_name, 13, y, 16, 135 - 13);
+ if (_network_player_info[company].use_password != 0) DrawSprite(SPR_LOCK, 135, y);
+
+ /* If the company's income was positive puts a green dot else a red dot */
+ if (_network_player_info[company].income >= 0) income = true;
+ DrawSprite(SPR_BLOT | (income ? PALETTE_TO_GREEN : PALETTE_TO_RED), 145, y);
+
+ pos++;
+ y += NET_PRC__SIZE_OF_ROW;
+ if (pos >= w->vscroll.cap) break;
+ }
+
+ /* Draw info about selected company when it is selected in the left window */
+ GfxFillRect(174, 39, 403, 75, 157);
+ DrawStringCentered(290, 50, STR_NETWORK_COMPANY_INFO, 0);
+ if (nd->company != (byte)-1) {
+ const uint x = 183;
+ const uint trunc_width = w->widget[6].right - x;
+ y = 80;
+
+ SetDParam(0, nd->server->info.clients_on);
+ SetDParam(1, nd->server->info.clients_max);
+ SetDParam(2, nd->server->info.companies_on);
+ SetDParam(3, nd->server->info.companies_max);
+ DrawString(x, y, STR_NETWORK_CLIENTS, 2);
+ y += 10;
+
+ SetDParamStr(0, _network_player_info[nd->company].company_name);
+ DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, 2, trunc_width);
+ y += 10;
+
+ SetDParam(0, _network_player_info[nd->company].inaugurated_year);
+ DrawString(x, y, STR_NETWORK_INAUGURATION_YEAR, 2); // inauguration year
+ y += 10;
+
+ SetDParam64(0, _network_player_info[nd->company].company_value);
+ DrawString(x, y, STR_NETWORK_VALUE, 2); // company value
+ y += 10;
+
+ SetDParam64(0, _network_player_info[nd->company].money);
+ DrawString(x, y, STR_NETWORK_CURRENT_BALANCE, 2); // current balance
+ y += 10;
+
+ SetDParam64(0, _network_player_info[nd->company].income);
+ DrawString(x, y, STR_NETWORK_LAST_YEARS_INCOME, 2); // last year's income
+ y += 10;
+
+ SetDParam(0, _network_player_info[nd->company].performance);
+ DrawString(x, y, STR_NETWORK_PERFORMANCE, 2); // performance
+ y += 10;
+
+ SetDParam(0, _network_player_info[nd->company].num_vehicle[0]);
+ SetDParam(1, _network_player_info[nd->company].num_vehicle[1]);
+ SetDParam(2, _network_player_info[nd->company].num_vehicle[2]);
+ SetDParam(3, _network_player_info[nd->company].num_vehicle[3]);
+ SetDParam(4, _network_player_info[nd->company].num_vehicle[4]);
+ DrawString(x, y, STR_NETWORK_VEHICLES, 2); // vehicles
+ y += 10;
+
+ SetDParam(0, _network_player_info[nd->company].num_station[0]);
+ SetDParam(1, _network_player_info[nd->company].num_station[1]);
+ SetDParam(2, _network_player_info[nd->company].num_station[2]);
+ SetDParam(3, _network_player_info[nd->company].num_station[3]);
+ SetDParam(4, _network_player_info[nd->company].num_station[4]);
+ DrawString(x, y, STR_NETWORK_STATIONS, 2); // stations
+ y += 10;
+
+ SetDParamStr(0, _network_player_info[nd->company].players);
+ DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, 2, trunc_width); // players
+ }
+ } break;
+
+ case WE_CLICK:
+ switch (e->we.click.widget) {
+ case 0: case 11: /* Close 'X' | Cancel button */
+ ShowNetworkGameWindow();
+ break;
+ case 4: { /* Company list */
+ uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET_COMPANY) / NET_PRC__SIZE_OF_ROW;
+
+ if (id_v >= w->vscroll.cap) return;
+
+ id_v += w->vscroll.pos;
+ nd->company = (id_v >= nd->server->info.companies_on) ? (byte)-1 : NetworkLobbyFindCompanyIndex(id_v);
+ SetWindowDirty(w);
+ } break;
+ case 7: /* Join company */
+ if (nd->company != (byte)-1) {
+ _network_playas = nd->company;
+ NetworkClientConnectGame(_network_last_host, _network_last_port);
+ }
+ break;
+ case 8: /* New company */
+ _network_playas = PLAYER_NEW_COMPANY;
+ NetworkClientConnectGame(_network_last_host, _network_last_port);
+ break;
+ case 9: /* Spectate game */
+ _network_playas = PLAYER_SPECTATOR;
+ NetworkClientConnectGame(_network_last_host, _network_last_port);
+ break;
+ case 10: /* Refresh */
+ NetworkQueryServer(_network_last_host, _network_last_port, false); // company info
+ NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
+ break;
+ } break;
+
+ case WE_MESSAGE:
+ SetWindowDirty(w);
+ break;
+ }
+}
+
+static const Widget _network_lobby_window_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
+{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 419, 0, 13, STR_NETWORK_GAME_LOBBY, STR_NULL},
+{ WWT_PANEL, RESIZE_NONE, BGC, 0, 419, 14, 234, 0x0, STR_NULL},
+
+// company list
+{ WWT_PANEL, RESIZE_NONE, BTC, 10, 155, 38, 49, 0x0, STR_NULL},
+{ WWT_MATRIX, RESIZE_NONE, BGC, 10, 155, 50, 190, (10 << 8) + 1, STR_NETWORK_COMPANY_LIST_TIP},
+{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 156, 167, 38, 190, STR_NULL, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+
+// company/player info
+{ WWT_PANEL, RESIZE_NONE, BGC, 173, 404, 38, 190, 0x0, STR_NULL},
+
+// buttons
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 151, 200, 211, STR_NETWORK_JOIN_COMPANY, STR_NETWORK_JOIN_COMPANY_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 151, 215, 226, STR_NETWORK_NEW_COMPANY, STR_NETWORK_NEW_COMPANY_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 158, 268, 200, 211, STR_NETWORK_SPECTATE_GAME, STR_NETWORK_SPECTATE_GAME_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 158, 268, 215, 226, STR_NETWORK_REFRESH, STR_NETWORK_REFRESH_TIP},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 278, 388, 200, 211, STR_012E_CANCEL, STR_NULL},
+
+{ WIDGETS_END},
+};
+
+static const WindowDesc _network_lobby_window_desc = {
+ WDP_CENTER, WDP_CENTER, 420, 235,
+ WC_NETWORK_WINDOW,0,
+ WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+ _network_lobby_window_widgets,
+ NetworkLobbyWindowWndProc,
+};
+
+/* Show the networklobbywindow with the selected server
+ * @param ngl Selected game pointer which is passed to the new window */
+static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
+{
+ Window *w;
+ DeleteWindowById(WC_NETWORK_WINDOW, 0);
+
+ NetworkQueryServer(_network_last_host, _network_last_port, false); // company info
+ NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
+
+ w = AllocateWindowDesc(&_network_lobby_window_desc);
+ if (w != NULL) {
+ WP(w, network_ql_d).n.server = ngl;
+ strcpy(_edit_str_buf, "");
+ w->vscroll.cap = 10;
+ }
+}
+
+// The window below gives information about the connected clients
+// and also makes able to give money to them, kick them (if server)
+// and stuff like that.
+
+extern void DrawPlayerIcon(PlayerID pid, int x, int y);
+
+// Every action must be of this form
+typedef void ClientList_Action_Proc(byte client_no);
+
+// Max 10 actions per client
+#define MAX_CLIENTLIST_ACTION 10
+
+// Some standard bullshit.. defines variables ;)
+static void ClientListWndProc(Window *w, WindowEvent *e);
+static void ClientListPopupWndProc(Window *w, WindowEvent *e);
+static byte _selected_clientlist_item = 255;
+static byte _selected_clientlist_y = 0;
+static char _clientlist_action[MAX_CLIENTLIST_ACTION][50];
+static ClientList_Action_Proc *_clientlist_proc[MAX_CLIENTLIST_ACTION];
+
+enum {
+ CLNWND_OFFSET = 16,
+ CLNWND_ROWSIZE = 10
+};
+
+static const Widget _client_list_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, RESIZE_NONE, 14, 11, 249, 0, 13, STR_NETWORK_CLIENT_LIST, STR_018C_WINDOW_TITLE_DRAG_THIS},
+
+{ WWT_PANEL, RESIZE_NONE, 14, 0, 249, 14, 14 + CLNWND_ROWSIZE + 1, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
+
+static const Widget _client_list_popup_widgets[] = {
+{ WWT_PANEL, RESIZE_NONE, 14, 0, 99, 0, 0, 0, STR_NULL},
+{ WIDGETS_END},
+};
+
+static WindowDesc _client_list_desc = {
+ WDP_AUTO, WDP_AUTO, 250, 1,
+ WC_CLIENT_LIST,0,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
+ _client_list_widgets,
+ ClientListWndProc
+};
+
+// Finds the Xth client-info that is active
+static const NetworkClientInfo *NetworkFindClientInfo(byte client_no)
+{
+ const NetworkClientInfo *ci;
+
+ FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
+ if (client_no == 0) return ci;
+ client_no--;
+ }
+
+ return NULL;
+}
+
+// Here we start to define the options out of the menu
+static void ClientList_Kick(byte client_no)
+{
+ if (client_no < MAX_PLAYERS)
+ SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
+}
+
+static void ClientList_Ban(byte client_no)
+{
+ uint i;
+ uint32 ip = NetworkFindClientInfo(client_no)->client_ip;
+
+ for (i = 0; i < lengthof(_network_ban_list); i++) {
+ if (_network_ban_list[i] == NULL) {
+ _network_ban_list[i] = strdup(inet_ntoa(*(struct in_addr *)&ip));
+ break;
+ }
+ }
+
+ if (client_no < MAX_PLAYERS)
+ SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
+}
+
+static void ClientList_GiveMoney(byte client_no)
+{
+ if (NetworkFindClientInfo(client_no) != NULL)
+ ShowNetworkGiveMoneyWindow(NetworkFindClientInfo(client_no)->client_playas);
+}
+
+static void ClientList_SpeakToClient(byte client_no)
+{
+ if (NetworkFindClientInfo(client_no) != NULL)
+ ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, NetworkFindClientInfo(client_no)->client_index);
+}
+
+static void ClientList_SpeakToCompany(byte client_no)
+{
+ if (NetworkFindClientInfo(client_no) != NULL)
+ ShowNetworkChatQueryWindow(DESTTYPE_TEAM, NetworkFindClientInfo(client_no)->client_playas);
+}
+
+static void ClientList_SpeakToAll(byte client_no)
+{
+ ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
+}
+
+static void ClientList_None(byte client_no)
+{
+ // No action ;)
+}
+
+
+
+// Help, a action is clicked! What do we do?
+static void HandleClientListPopupClick(byte index, byte clientno) {
+ // A click on the Popup of the ClientList.. handle the command
+ if (index < MAX_CLIENTLIST_ACTION && _clientlist_proc[index] != NULL) {
+ _clientlist_proc[index](clientno);
+ }
+}
+
+// Finds the amount of clients and set the height correct
+static bool CheckClientListHeight(Window *w)
+{
+ int num = 0;
+ const NetworkClientInfo *ci;
+
+ // Should be replaced with a loop through all clients
+ FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
+ num++;
+ }
+
+ num *= CLNWND_ROWSIZE;
+
+ // If height is changed
+ if (w->height != CLNWND_OFFSET + num + 1) {
+ // XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
+ SetWindowDirty(w);
+ w->widget[2].bottom = w->widget[2].top + num + 2;
+ w->height = CLNWND_OFFSET + num + 1;
+ SetWindowDirty(w);
+ return false;
+ }
+ return true;
+}
+
+// Finds the amount of actions in the popup and set the height correct
+static uint ClientListPopupHeigth(void) {
+ int i, num = 0;
+
+ // Find the amount of actions
+ for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
+ if (_clientlist_action[i][0] == '\0') continue;
+ if (_clientlist_proc[i] == NULL) continue;
+ num++;
+ }
+
+ num *= CLNWND_ROWSIZE;
+
+ return num + 1;
+}
+
+// Show the popup (action list)
+static Window *PopupClientList(Window *w, int client_no, int x, int y)
+{
+ int i, h;
+ const NetworkClientInfo *ci;
+ DeleteWindowById(WC_TOOLBAR_MENU, 0);
+
+ // Clean the current actions
+ for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
+ _clientlist_action[i][0] = '\0';
+ _clientlist_proc[i] = NULL;
+ }
+
+ // Fill the actions this client has
+ // Watch is, max 50 chars long!
+
+ ci = NetworkFindClientInfo(client_no);
+ if (ci == NULL) return NULL;
+
+ i = 0;
+ if (_network_own_client_index != ci->client_index) {
+ GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(_clientlist_action[i]));
+ _clientlist_proc[i++] = &ClientList_SpeakToClient;
+ }
+
+ if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) {
+ GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(_clientlist_action[i]));
+ _clientlist_proc[i++] = &ClientList_SpeakToCompany;
+ }
+ GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(_clientlist_action[i]));
+ _clientlist_proc[i++] = &ClientList_SpeakToAll;
+
+ if (_network_own_client_index != ci->client_index) {
+ /* We are no spectator and the player we want to give money to is no spectator */
+ if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas)) {
+ GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i]));
+ _clientlist_proc[i++] = &ClientList_GiveMoney;
+ }
+ }
+
+ // A server can kick clients (but not himself)
+ if (_network_server && _network_own_client_index != ci->client_index) {
+ GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(_clientlist_action[i]));
+ _clientlist_proc[i++] = &ClientList_Kick;
+
+ sprintf(_clientlist_action[i],"Ban"); // XXX GetString?
+ _clientlist_proc[i++] = &ClientList_Ban;
+ }
+
+ if (i == 0) {
+ GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(_clientlist_action[i]));
+ _clientlist_proc[i++] = &ClientList_None;
+ }
+
+ /* Calculate the height */
+ h = ClientListPopupHeigth();
+
+ // Allocate the popup
+ w = AllocateWindow(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets);
+ w->widget[0].bottom = w->widget[0].top + h;
+ w->widget[0].right = w->widget[0].left + 150;
+
+ w->flags4 &= ~WF_WHITE_BORDER_MASK;
+ WP(w,menu_d).item_count = 0;
+ // Save our client
+ WP(w,menu_d).main_button = client_no;
+ WP(w,menu_d).sel_index = 0;
+ // We are a popup
+ _popup_menu_active = true;
+
+ return w;
+}
+
+/** Main handle for the client popup list
+ * uses menu_d WP macro */
+static void ClientListPopupWndProc(Window *w, WindowEvent *e)
+{
+ switch (e->event) {
+ case WE_PAINT: {
+ int i, y, sel;
+ byte colour;
+ DrawWindowWidgets(w);
+
+ // Draw the actions
+ sel = WP(w,menu_d).sel_index;
+ y = 1;
+ for (i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) {
+ if (_clientlist_action[i][0] == '\0') continue;
+ if (_clientlist_proc[i] == NULL) continue;
+
+ if (sel-- == 0) { // Selected item, highlight it
+ GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0);
+ colour = 0xC;
+ } else {
+ colour = 0x10;
+ }
+
+ DoDrawString(_clientlist_action[i], 4, y, colour);
+ }
+ } break;
+
+ case WE_POPUPMENU_SELECT: {
+ // We selected an action
+ int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
+
+ if (index >= 0 && e->we.popupmenu.pt.y >= w->top)
+ HandleClientListPopupClick(index, WP(w,menu_d).main_button);
+
+ DeleteWindowById(WC_TOOLBAR_MENU, 0);
+ } break;
+
+ case WE_POPUPMENU_OVER: {
+ // Our mouse hoovers over an action? Select it!
+ int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
+
+ if (index == -1 || index == WP(w,menu_d).sel_index) return;
+
+ WP(w,menu_d).sel_index = index;
+ SetWindowDirty(w);
+ } break;
+
+ }
+}
+
+// Main handle for clientlist
+static void ClientListWndProc(Window *w, WindowEvent *e)
+{
+ switch (e->event) {
+ case WE_PAINT: {
+ NetworkClientInfo *ci;
+ int y, i = 0;
+ byte colour;
+
+ // Check if we need to reset the height
+ if (!CheckClientListHeight(w)) break;
+
+ DrawWindowWidgets(w);
+
+ y = CLNWND_OFFSET;
+
+ FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
+ if (_selected_clientlist_item == i++) { // Selected item, highlight it
+ GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
+ colour = 0xC;
+ } else {
+ colour = 0x10;
+ }
+
+ if (ci->client_index == NETWORK_SERVER_INDEX) {
+ DrawString(4, y, STR_NETWORK_SERVER, colour);
+ } else {
+ DrawString(4, y, STR_NETWORK_CLIENT, colour);
+ }
+
+ // Filter out spectators
+ if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1);
+
+ DoDrawString(ci->client_name, 81, y, colour);
+
+ y += CLNWND_ROWSIZE;
+ }
+ } break;
+
+ case WE_CLICK:
+ // Show the popup with option
+ if (_selected_clientlist_item != 255) {
+ PopupClientList(w, _selected_clientlist_item, e->we.click.pt.x + w->left, e->we.click.pt.y + w->top);
+ }
+
+ break;
+
+ case WE_MOUSEOVER:
+ // -1 means we left the current window
+ if (e->we.mouseover.pt.y == -1) {
+ _selected_clientlist_y = 0;
+ _selected_clientlist_item = 255;
+ SetWindowDirty(w);
+ break;
+ }
+ // It did not change.. no update!
+ if (e->we.mouseover.pt.y == _selected_clientlist_y) break;
+
+ // Find the new selected item (if any)
+ _selected_clientlist_y = e->we.mouseover.pt.y;
+ if (e->we.mouseover.pt.y > CLNWND_OFFSET) {
+ _selected_clientlist_item = (e->we.mouseover.pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE;
+ } else {
+ _selected_clientlist_item = 255;
+ }
+
+ // Repaint
+ SetWindowDirty(w);
+ break;
+
+ case WE_DESTROY: case WE_CREATE:
+ // When created or destroyed, data is reset
+ _selected_clientlist_item = 255;
+ _selected_clientlist_y = 0;
+ break;
+ }
+}
+
+void ShowClientList(void)
+{
+ AllocateWindowDescFront(&_client_list_desc, 0);
+}
+
+
+static NetworkPasswordType pw_type;
+
+
+void ShowNetworkNeedPassword(NetworkPasswordType npt)
+{
+ StringID caption;
+
+ pw_type = npt;
+ switch (npt) {
+ default: NOT_REACHED();
+ case NETWORK_GAME_PASSWORD: caption = STR_NETWORK_NEED_GAME_PASSWORD_CAPTION; break;
+ case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break;
+ }
+ ShowQueryString(STR_EMPTY, caption, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL);
+}
+
+
+static void NetworkJoinStatusWindowWndProc(Window *w, WindowEvent *e)
+{
+ switch (e->event) {
+ case WE_PAINT: {
+ uint8 progress; // used for progress bar
+ DrawWindowWidgets(w);
+
+ DrawStringCentered(125, 35, STR_NETWORK_CONNECTING_1 + _network_join_status, 14);
+ switch (_network_join_status) {
+ case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
+ case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
+ progress = 10; // first two stages 10%
+ break;
+ case NETWORK_JOIN_STATUS_WAITING:
+ SetDParam(0, _network_join_waiting);
+ DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_WAITING, 14);
+ progress = 15; // third stage is 15%
+ break;
+ case NETWORK_JOIN_STATUS_DOWNLOADING:
+ SetDParam(0, _network_join_kbytes);
+ SetDParam(1, _network_join_kbytes_total);
+ DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, 14);
+ /* Fallthrough */
+ default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */
+ progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total;
+ }
+
+ /* Draw nice progress bar :) */
+ DrawFrameRect(20, 18, (int)((w->width - 20) * progress / 100), 28, 10, 0);
+ } break;
+
+ case WE_CLICK:
+ switch (e->we.click.widget) {
+ case 2: /* Disconnect button */
+ NetworkDisconnect();
+ DeleteWindow(w);
+ SwitchMode(SM_MENU);
+ ShowNetworkGameWindow();
+ break;
+ }
+ break;
+
+ /* If the server asks for a password, we need to fill it in */
+ case WE_ON_EDIT_TEXT_CANCEL:
+ NetworkDisconnect();
+ ShowNetworkGameWindow();
+ break;
+
+ case WE_ON_EDIT_TEXT:
+ SEND_COMMAND(PACKET_CLIENT_PASSWORD)(pw_type, e->we.edittext.str);
+ break;
+ }
+}
+
+static const Widget _network_join_status_window_widget[] = {
+{ WWT_CAPTION, RESIZE_NONE, 14, 0, 249, 0, 13, STR_NETWORK_CONNECTING, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PANEL, RESIZE_NONE, 14, 0, 249, 14, 84, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 75, 175, 69, 80, STR_NETWORK_DISCONNECT, STR_NULL},
+{ WIDGETS_END},
+};
+
+static const WindowDesc _network_join_status_window_desc = {
+ WDP_CENTER, WDP_CENTER, 250, 85,
+ WC_NETWORK_STATUS_WINDOW, 0,
+ WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_MODAL,
+ _network_join_status_window_widget,
+ NetworkJoinStatusWindowWndProc,
+};
+
+void ShowJoinStatusWindow(void)
+{
+ Window *w;
+ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+ w = AllocateWindowDesc(&_network_join_status_window_desc);
+ /* Parent the status window to the lobby */
+ if (w != NULL) w->parent = FindWindowById(WC_NETWORK_WINDOW, 0);
+}
+
+static void SendChat(const char *buf, DestType type, byte dest)
+{
+ if (buf[0] == '\0') return;
+ if (!_network_server) {
+ SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT + type, type, dest, buf);
+ } else {
+ NetworkServer_HandleChat(NETWORK_ACTION_CHAT + type, type, dest, buf, NETWORK_SERVER_INDEX);
+ }
+}
+
+/**
+ * Find the next item of the list of things that can be auto-completed.
+ * @param item The current indexed item to return. This function can, and most
+ * likely will, alter item, to skip empty items in the arrays.
+ * @return Returns the char that matched to the index.
+ */
+static const char *ChatTabCompletionNextItem(uint *item)
+{
+ static char chat_tab_temp_buffer[64];
+
+ /* First, try clients */
+ if (*item < MAX_CLIENT_INFO) {
+ /* Skip inactive clients */
+ while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
+ if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
+ }
+
+ /* Then, try townnames */
+ /* Not that the following assumes all town indices are adjacent, ie no
+ * towns have been deleted. */
+ if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
+ const Town *t;
+
+ FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
+ /* Get the town-name via the string-system */
+ SetDParam(0, t->townnameparts);
+ GetString(chat_tab_temp_buffer, t->townnametype, lastof(chat_tab_temp_buffer));
+ return &chat_tab_temp_buffer[0];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Find what text to complete. It scans for a space from the left and marks
+ * the word right from that as to complete. It also writes a \0 at the
+ * position of the space (if any). If nothing found, buf is returned.
+ */
+static char *ChatTabCompletionFindText(char *buf)
+{
+ char *p = strrchr(buf, ' ');
+ if (p == NULL) return buf;
+
+ *p = '\0';
+ return p + 1;
+}
+
+/**
+ * See if we can auto-complete the current text of the user.
+ */
+static void ChatTabCompletion(Window *w)
+{
+ static char _chat_tab_completion_buf[lengthof(_edit_str_buf)];
+ Textbuf *tb = &WP(w, querystr_d).text;
+ uint len, tb_len;
+ uint item;
+ char *tb_buf, *pre_buf;
+ const char *cur_name;
+ bool second_scan = false;
+
+ item = 0;
+
+ /* Copy the buffer so we can modify it without damaging the real data */
+ pre_buf = (_chat_tab_completion_active) ? strdup(_chat_tab_completion_buf) : strdup(tb->buf);
+
+ tb_buf = ChatTabCompletionFindText(pre_buf);
+ tb_len = strlen(tb_buf);
+
+ while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
+ item++;
+
+ if (_chat_tab_completion_active) {
+ /* We are pressing TAB again on the same name, is there an other name
+ * that starts with this? */
+ if (!second_scan) {
+ uint offset;
+ uint length;
+
+ /* If we are completing at the begin of the line, skip the ': ' we added */
+ if (tb_buf == pre_buf) {
+ offset = 0;
+ length = tb->length - 2;
+ } else {
+ /* Else, find the place we are completing at */
+ offset = strlen(pre_buf) + 1;
+ length = tb->length - offset;
+ }
+
+ /* Compare if we have a match */
+ if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
+
+ continue;
+ }
+
+ /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
+ }
+
+ len = strlen(cur_name);
+ if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
+ /* Save the data it was before completion */
+ if (!second_scan) snprintf(_chat_tab_completion_buf, lengthof(_chat_tab_completion_buf), "%s", tb->buf);
+ _chat_tab_completion_active = true;
+
+ /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
+ if (pre_buf == tb_buf) {
+ snprintf(tb->buf, lengthof(_edit_str_buf), "%s: ", cur_name);
+ } else {
+ snprintf(tb->buf, lengthof(_edit_str_buf), "%s %s", pre_buf, cur_name);
+ }
+
+ /* Update the textbuffer */
+ UpdateTextBufferSize(&WP(w, querystr_d).text);
+
+ SetWindowDirty(w);
+ free(pre_buf);
+ return;
+ }
+ }
+
+ if (second_scan) {
+ /* We walked all posibilities, and the user presses tab again.. revert to original text */
+ strcpy(tb->buf, _chat_tab_completion_buf);
+ _chat_tab_completion_active = false;
+
+ /* Update the textbuffer */
+ UpdateTextBufferSize(&WP(w, querystr_d).text);
+
+ SetWindowDirty(w);
+ }
+ free(pre_buf);
+}
+
+/* uses querystr_d WP macro
+ * uses querystr_d->caption to store
+ * - type of chat message (Private/Team/All) in bytes 0-7
+ * - destination of chat message in the case of Team/Private in bytes 8-15 */
+static void ChatWindowWndProc(Window *w, WindowEvent *e)
+{
+ switch (e->event) {
+ case WE_CREATE:
+ SendWindowMessage(WC_NEWS_WINDOW, 0, WE_CREATE, w->height, 0);
+ SETBIT(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
+ break;
+
+ case WE_PAINT: {
+ static const StringID chat_captions[] = {
+ STR_NETWORK_CHAT_ALL_CAPTION,
+ STR_NETWORK_CHAT_COMPANY_CAPTION,
+ STR_NETWORK_CHAT_CLIENT_CAPTION
+ };
+ StringID msg;
+
+ DrawWindowWidgets(w);
+
+ assert(GB(WP(w, querystr_d).caption, 0, 8) < lengthof(chat_captions));
+ msg = chat_captions[GB(WP(w, querystr_d).caption, 0, 8)];
+ DrawStringRightAligned(w->widget[2].left - 2, w->widget[2].top + 1, msg, 16);
+ DrawEditBox(w, &WP(w, querystr_d), 2);
+ } break;
+
+ case WE_CLICK:
+ switch (e->we.click.widget) {
+ case 3: { /* Send */
+ DestType type = GB(WP(w, querystr_d).caption, 0, 8);
+ byte dest = GB(WP(w, querystr_d).caption, 8, 8);
+ SendChat(WP(w, querystr_d).text.buf, type, dest);
+ } /* FALLTHROUGH */
+ case 0: /* Cancel */ DeleteWindow(w); break;
+ }
+ break;
+
+ case WE_MOUSELOOP:
+ HandleEditBox(w, &WP(w, querystr_d), 2);
+ break;
+
+ case WE_KEYPRESS:
+ if (e->we.keypress.keycode == WKC_TAB) {
+ ChatTabCompletion(w);
+ } else {
+ _chat_tab_completion_active = false;
+ switch (HandleEditBoxKey(w, &WP(w, querystr_d), 2, e)) {
+ case 1: { /* Return */
+ DestType type = GB(WP(w, querystr_d).caption, 0, 8);
+ byte dest = GB(WP(w, querystr_d).caption, 8, 8);
+ SendChat(WP(w, querystr_d).text.buf, type, dest);
+ } /* FALLTHROUGH */
+ case 2: /* Escape */ DeleteWindow(w); break;
+ }
+ }
+ break;
+
+ case WE_DESTROY:
+ SendWindowMessage(WC_NEWS_WINDOW, 0, WE_DESTROY, 0, 0);
+ CLRBIT(_no_scroll, SCROLL_CHAT);
+ break;
+ }
+}
+
+static const Widget _chat_window_widgets[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_PANEL, RESIZE_NONE, 14, 11, 639, 0, 13, 0x0, STR_NULL}, // background
+{ WWT_PANEL, RESIZE_NONE, 14, 75, 577, 1, 12, 0x0, STR_NULL}, // text box
+{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 578, 639, 1, 12, STR_NETWORK_SEND, STR_NULL}, // send button
+{ WIDGETS_END},
+};
+
+static const WindowDesc _chat_window_desc = {
+ WDP_CENTER, -26, 640, 14, // x, y, width, height
+ WC_SEND_NETWORK_MSG,0,
+ WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
+ _chat_window_widgets,
+ ChatWindowWndProc
+};
+
+void ShowNetworkChatQueryWindow(DestType type, byte dest)
+{
+ Window *w;
+
+ DeleteWindowById(WC_SEND_NETWORK_MSG, 0);
+
+ _edit_str_buf[0] = '\0';
+ _chat_tab_completion_active = false;
+
+ w = AllocateWindowDesc(&_chat_window_desc);
+
+ LowerWindowWidget(w, 2);
+ WP(w, querystr_d).caption = GB(type, 0, 8) | (dest << 8); // Misuse of caption
+ WP(w, querystr_d).afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, lengthof(_edit_str_buf), 0);
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_gui.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,26 @@
+/* $Id$ */
+
+#ifndef NETWORK_GUI_H
+#define NETWORK_GUI_H
+
+#ifdef ENABLE_NETWORK
+
+#include "network_data.h"
+
+void ShowNetworkNeedPassword(NetworkPasswordType npt);
+void ShowNetworkGiveMoneyWindow(byte player); // PlayerID
+void ShowNetworkChatQueryWindow(DestType type, byte dest);
+void ShowJoinStatusWindow(void);
+void ShowNetworkGameWindow(void);
+void ShowClientList(void);
+
+#else /* ENABLE_NETWORK */
+/* Network function stubs when networking is disabled */
+
+static inline void ShowNetworkChatQueryWindow(byte desttype, byte dest) {}
+static inline void ShowClientList(void) {}
+static inline void ShowNetworkGameWindow(void) {}
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_GUI_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_server.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,1528 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../stdafx.h"
+#include "../openttd.h" // XXX StringID
+#include "../debug.h"
+#include "../string.h"
+#include "../strings.h"
+#include "network_data.h"
+#include "core/tcp.h"
+#include "../train.h"
+#include "../date.h"
+#include "../table/strings.h"
+#include "../functions.h"
+#include "network_server.h"
+#include "network_udp.h"
+#include "../console.h"
+#include "../command.h"
+#include "../saveload.h"
+#include "../vehicle.h"
+#include "../station.h"
+#include "../variables.h"
+#include "../genworld.h"
+
+// This file handles all the server-commands
+
+static void NetworkHandleCommandQueue(NetworkClientState* cs);
+
+// **********
+// Sending functions
+// DEF_SERVER_SEND_COMMAND has parameter: NetworkClientState *cs
+// **********
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkClientState *cs, NetworkClientInfo *ci)
+{
+ //
+ // Packet: SERVER_CLIENT_INFO
+ // Function: Sends info about a client
+ // Data:
+ // uint16: The index of the client (always unique on a server. 1 = server)
+ // uint8: As which player the client is playing
+ // String: The name of the client
+ // String: The unique id of the client
+ //
+
+ if (ci->client_index != NETWORK_EMPTY_INDEX) {
+ Packet *p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
+ NetworkSend_uint16(p, ci->client_index);
+ NetworkSend_uint8 (p, ci->client_playas);
+ NetworkSend_string(p, ci->client_name);
+ NetworkSend_string(p, ci->unique_id);
+
+ NetworkSend_Packet(p, cs);
+ }
+}
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)
+{
+//
+ // Packet: SERVER_COMPANY_INFO
+ // Function: Sends info about the companies
+ // Data:
+ //
+
+ int i;
+
+ Player *player;
+ Packet *p;
+
+ byte active = ActivePlayerCount();
+
+ if (active == 0) {
+ p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
+
+ NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
+ NetworkSend_uint8 (p, active);
+
+ NetworkSend_Packet(p, cs);
+ return;
+ }
+
+ NetworkPopulateCompanyInfo();
+
+ FOR_ALL_PLAYERS(player) {
+ if (!player->is_active) continue;
+
+ p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
+
+ NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
+ NetworkSend_uint8 (p, active);
+ NetworkSend_uint8 (p, player->index);
+
+ NetworkSend_string(p, _network_player_info[player->index].company_name);
+ NetworkSend_uint32(p, _network_player_info[player->index].inaugurated_year);
+ NetworkSend_uint64(p, _network_player_info[player->index].company_value);
+ NetworkSend_uint64(p, _network_player_info[player->index].money);
+ NetworkSend_uint64(p, _network_player_info[player->index].income);
+ NetworkSend_uint16(p, _network_player_info[player->index].performance);
+
+ /* Send 1 if there is a passord for the company else send 0 */
+ if (_network_player_info[player->index].password[0] != '\0') {
+ NetworkSend_uint8(p, 1);
+ } else {
+ NetworkSend_uint8(p, 0);
+ }
+
+ for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) {
+ NetworkSend_uint16(p, _network_player_info[player->index].num_vehicle[i]);
+ }
+
+ for (i = 0; i < NETWORK_STATION_TYPES; i++) {
+ NetworkSend_uint16(p, _network_player_info[player->index].num_station[i]);
+ }
+
+ if (_network_player_info[player->index].players[0] == '\0') {
+ NetworkSend_string(p, "<none>");
+ } else {
+ NetworkSend_string(p, _network_player_info[player->index].players);
+ }
+
+ NetworkSend_Packet(p, cs);
+ }
+
+ p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
+
+ NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
+ NetworkSend_uint8 (p, 0);
+
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error)
+{
+ //
+ // Packet: SERVER_ERROR
+ // Function: The client made an error
+ // Data:
+ // uint8: ErrorID (see network_data.h, NetworkErrorCode)
+ //
+
+ char str[100];
+ Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
+
+ NetworkSend_uint8(p, error);
+ NetworkSend_Packet(p, cs);
+
+ GetNetworkErrorMsg(str, error, lastof(str));
+
+ // Only send when the current client was in game
+ if (cs->status > STATUS_AUTH) {
+ NetworkClientState *new_cs;
+ char client_name[NETWORK_CLIENT_NAME_LENGTH];
+
+ NetworkGetClientName(client_name, sizeof(client_name), cs);
+
+ DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
+
+ NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status > STATUS_AUTH && new_cs != cs) {
+ // Some errors we filter to a more general error. Clients don't have to know the real
+ // reason a joining failed.
+ if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
+ error = NETWORK_ERROR_ILLEGAL_PACKET;
+
+ SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, error);
+ }
+ }
+ } else {
+ DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->index, str);
+ }
+
+ cs->has_quit = true;
+
+ // Make sure the data get's there before we close the connection
+ NetworkSend_Packets(cs);
+
+ // The client made a mistake, so drop his connection now!
+ NetworkCloseClient(cs);
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientState *cs, NetworkPasswordType type)
+{
+ //
+ // Packet: SERVER_NEED_PASSWORD
+ // Function: Indication to the client that the server needs a password
+ // Data:
+ // uint8: Type of password
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
+ NetworkSend_uint8(p, type);
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
+{
+ //
+ // Packet: SERVER_WELCOME
+ // Function: The client is joined and ready to receive his map
+ // Data:
+ // uint16: Own ClientID
+ //
+
+ Packet *p;
+ const NetworkClientState *new_cs;
+
+ // Invalid packet when status is AUTH or higher
+ if (cs->status >= STATUS_AUTH) return;
+
+ cs->status = STATUS_AUTH;
+ _network_game_info.clients_on++;
+
+ p = NetworkSend_Init(PACKET_SERVER_WELCOME);
+ NetworkSend_uint16(p, cs->index);
+ NetworkSend_Packet(p, cs);
+
+ // Transmit info about all the active clients
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs != cs && new_cs->status > STATUS_AUTH)
+ SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, DEREF_CLIENT_INFO(new_cs));
+ }
+ // Also send the info of the server
+ SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX));
+}
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WAIT)
+{
+ //
+ // Packet: PACKET_SERVER_WAIT
+ // Function: The client can not receive the map at the moment because
+ // someone else is already receiving the map
+ // Data:
+ // uint8: Clients awaiting map
+ //
+ int waiting = 0;
+ NetworkClientState *new_cs;
+ Packet *p;
+
+ // Count how many players are waiting in the queue
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status == STATUS_MAP_WAIT) waiting++;
+ }
+
+ p = NetworkSend_Init(PACKET_SERVER_WAIT);
+ NetworkSend_uint8(p, waiting);
+ NetworkSend_Packet(p, cs);
+}
+
+// This sends the map to the client
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
+{
+ //
+ // Packet: SERVER_MAP
+ // Function: Sends the map to the client, or a part of it (it is splitted in
+ // a lot of multiple packets)
+ // Data:
+ // uint8: packet-type (MAP_PACKET_START, MAP_PACKET_NORMAL and MAP_PACKET_END)
+ // if MAP_PACKET_START:
+ // uint32: The current FrameCounter
+ // if MAP_PACKET_NORMAL:
+ // piece of the map (till max-size of packet)
+ // if MAP_PACKET_END:
+ // uint32: seed0 of player
+ // uint32: seed1 of player
+ // last 2 are repeated MAX_PLAYERS time
+ //
+
+ static FILE *file_pointer;
+ static uint sent_packets; // How many packets we did send succecfully last time
+
+ if (cs->status < STATUS_AUTH) {
+ // Illegal call, return error and ignore the packet
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
+ return;
+ }
+
+ if (cs->status == STATUS_AUTH) {
+ char filename[256];
+ Packet *p;
+
+ // Make a dump of the current game
+ snprintf(filename, lengthof(filename), "%s%snetwork_server.tmp", _paths.autosave_dir, PATHSEP);
+ if (SaveOrLoad(filename, SL_SAVE) != SL_OK) error("network savedump failed");
+
+ file_pointer = fopen(filename, "rb");
+ fseek(file_pointer, 0, SEEK_END);
+
+ // Now send the _frame_counter and how many packets are coming
+ p = NetworkSend_Init(PACKET_SERVER_MAP);
+ NetworkSend_uint8(p, MAP_PACKET_START);
+ NetworkSend_uint32(p, _frame_counter);
+ NetworkSend_uint32(p, ftell(file_pointer));
+ NetworkSend_Packet(p, cs);
+
+ fseek(file_pointer, 0, SEEK_SET);
+
+ sent_packets = 4; // We start with trying 4 packets
+
+ cs->status = STATUS_MAP;
+ /* Mark the start of download */
+ cs->last_frame = _frame_counter;
+ cs->last_frame_server = _frame_counter;
+ }
+
+ if (cs->status == STATUS_MAP) {
+ uint i;
+ int res;
+ for (i = 0; i < sent_packets; i++) {
+ Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
+ NetworkSend_uint8(p, MAP_PACKET_NORMAL);
+ res = (int)fread(p->buffer + p->size, 1, SEND_MTU - p->size, file_pointer);
+
+ if (ferror(file_pointer)) error("Error reading temporary network savegame!");
+
+ p->size += res;
+ NetworkSend_Packet(p, cs);
+ if (feof(file_pointer)) {
+ // Done reading!
+ Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
+ NetworkSend_uint8(p, MAP_PACKET_END);
+ NetworkSend_Packet(p, cs);
+
+ // Set the status to DONE_MAP, no we will wait for the client
+ // to send it is ready (maybe that happens like never ;))
+ cs->status = STATUS_DONE_MAP;
+ fclose(file_pointer);
+
+ {
+ NetworkClientState *new_cs;
+ bool new_map_client = false;
+ // Check if there is a client waiting for receiving the map
+ // and start sending him the map
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status == STATUS_MAP_WAIT) {
+ // Check if we already have a new client to send the map to
+ if (!new_map_client) {
+ // If not, this client will get the map
+ new_cs->status = STATUS_AUTH;
+ new_map_client = true;
+ SEND_COMMAND(PACKET_SERVER_MAP)(new_cs);
+ } else {
+ // Else, send the other clients how many clients are in front of them
+ SEND_COMMAND(PACKET_SERVER_WAIT)(new_cs);
+ }
+ }
+ }
+ }
+
+ // There is no more data, so break the for
+ break;
+ }
+ }
+
+ // Send all packets (forced) and check if we have send it all
+ NetworkSend_Packets(cs);
+ if (cs->packet_queue == NULL) {
+ // All are sent, increase the sent_packets
+ sent_packets *= 2;
+ } else {
+ // Not everything is sent, decrease the sent_packets
+ if (sent_packets > 1) sent_packets /= 2;
+ }
+ }
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkClientState *cs, uint16 client_index)
+{
+ //
+ // Packet: SERVER_JOIN
+ // Function: A client is joined (all active clients receive this after a
+ // PACKET_CLIENT_MAP_OK) Mostly what directly follows is a
+ // PACKET_SERVER_CLIENT_INFO
+ // Data:
+ // uint16: Client-Index
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_JOIN);
+
+ NetworkSend_uint16(p, client_index);
+
+ NetworkSend_Packet(p, cs);
+}
+
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_FRAME)
+{
+ //
+ // Packet: SERVER_FRAME
+ // Function: Sends the current frame-counter to the client
+ // Data:
+ // uint32: Frame Counter
+ // uint32: Frame Counter Max (how far may the client walk before the server?)
+ // [uint32: general-seed-1]
+ // [uint32: general-seed-2]
+ // (last two depends on compile-settings, and are not default settings)
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_FRAME);
+ NetworkSend_uint32(p, _frame_counter);
+ NetworkSend_uint32(p, _frame_counter_max);
+#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
+ NetworkSend_uint32(p, _sync_seed_1);
+#ifdef NETWORK_SEND_DOUBLE_SEED
+ NetworkSend_uint32(p, _sync_seed_2);
+#endif
+#endif
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SYNC)
+{
+ //
+ // Packet: SERVER_SYNC
+ // Function: Sends a sync-check to the client
+ // Data:
+ // uint32: Frame Counter
+ // uint32: General-seed-1
+ // [uint32: general-seed-2]
+ // (last one depends on compile-settings, and are not default settings)
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_SYNC);
+ NetworkSend_uint32(p, _frame_counter);
+ NetworkSend_uint32(p, _sync_seed_1);
+
+#ifdef NETWORK_SEND_DOUBLE_SEED
+ NetworkSend_uint32(p, _sync_seed_2);
+#endif
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMMAND)(NetworkClientState *cs, CommandPacket *cp)
+{
+ //
+ // Packet: SERVER_COMMAND
+ // Function: Sends a DoCommand to the client
+ // Data:
+ // uint8: PlayerID (0..MAX_PLAYERS-1)
+ // uint32: CommandID (see command.h)
+ // uint32: P1 (free variables used in DoCommand)
+ // uint32: P2
+ // uint32: Tile
+ // string: text
+ // uint8: CallBackID (see callback_table.c)
+ // uint32: Frame of execution
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_COMMAND);
+
+ NetworkSend_uint8(p, cp->player);
+ NetworkSend_uint32(p, cp->cmd);
+ NetworkSend_uint32(p, cp->p1);
+ NetworkSend_uint32(p, cp->p2);
+ NetworkSend_uint32(p, cp->tile);
+ NetworkSend_string(p, cp->text);
+ NetworkSend_uint8(p, cp->callback);
+ NetworkSend_uint32(p, cp->frame);
+
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkClientState *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg)
+{
+ //
+ // Packet: SERVER_CHAT
+ // Function: Sends a chat-packet to the client
+ // Data:
+ // uint8: ActionID (see network_data.h, NetworkAction)
+ // uint16: Client-index
+ // String: Message (max MAX_TEXT_MSG_LEN)
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_CHAT);
+
+ NetworkSend_uint8(p, action);
+ NetworkSend_uint16(p, client_index);
+ NetworkSend_uint8(p, self_send);
+ NetworkSend_string(p, msg);
+
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, uint16 client_index, NetworkErrorCode errorno)
+{
+ //
+ // Packet: SERVER_ERROR_QUIT
+ // Function: One of the clients made an error and is quiting the game
+ // This packet informs the other clients of that.
+ // Data:
+ // uint16: Client-index
+ // uint8: ErrorID (see network_data.h, NetworkErrorCode)
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR_QUIT);
+
+ NetworkSend_uint16(p, client_index);
+ NetworkSend_uint8(p, errorno);
+
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkClientState *cs, uint16 client_index, const char *leavemsg)
+{
+ //
+ // Packet: SERVER_ERROR_QUIT
+ // Function: A client left the game, and this packets informs the other clients
+ // of that.
+ // Data:
+ // uint16: Client-index
+ // String: leave-message
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_QUIT);
+
+ NetworkSend_uint16(p, client_index);
+ NetworkSend_string(p, leavemsg);
+
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN)
+{
+ //
+ // Packet: SERVER_SHUTDOWN
+ // Function: Let the clients know that the server is closing
+ // Data:
+ // <none>
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_SHUTDOWN);
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME)
+{
+ //
+ // Packet: PACKET_SERVER_NEWGAME
+ // Function: Let the clients know that the server is loading a new map
+ // Data:
+ // <none>
+ //
+
+ Packet *p = NetworkSend_Init(PACKET_SERVER_NEWGAME);
+ NetworkSend_Packet(p, cs);
+}
+
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command)
+{
+ Packet *p = NetworkSend_Init(PACKET_SERVER_RCON);
+
+ NetworkSend_uint16(p, color);
+ NetworkSend_string(p, command);
+ NetworkSend_Packet(p, cs);
+}
+
+// **********
+// Receiving functions
+// DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientState *cs, Packet *p
+// **********
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
+{
+ SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
+{
+ char name[NETWORK_CLIENT_NAME_LENGTH];
+ char unique_id[NETWORK_NAME_LENGTH];
+ NetworkClientInfo *ci;
+ byte playas;
+ NetworkLanguage client_lang;
+ char client_revision[NETWORK_REVISION_LENGTH];
+
+ NetworkRecv_string(cs, p, client_revision, sizeof(client_revision));
+
+#if defined(WITH_REV) || defined(WITH_REV_HACK)
+ // Check if the client has revision control enabled
+ if (strcmp(NOREV_STRING, client_revision) != 0 &&
+ strcmp(_network_game_info.server_revision, client_revision) != 0) {
+ // Different revisions!!
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION);
+ return;
+ }
+#endif
+
+ NetworkRecv_string(cs, p, name, sizeof(name));
+ playas = NetworkRecv_uint8(cs, p);
+ client_lang = NetworkRecv_uint8(cs, p);
+ NetworkRecv_string(cs, p, unique_id, sizeof(unique_id));
+
+ if (cs->has_quit) return;
+
+ // join another company does not affect these values
+ switch (playas) {
+ case PLAYER_NEW_COMPANY: /* New company */
+ if (ActivePlayerCount() >= _network_game_info.companies_max) {
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
+ return;
+ }
+ break;
+ case PLAYER_SPECTATOR: /* Spectator */
+ if (NetworkSpectatorCount() >= _network_game_info.spectators_max) {
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
+ return;
+ }
+ break;
+ default: /* Join another company (companies 1-8 (index 0-7)) */
+ if (!IsValidPlayer(playas)) {
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
+ return;
+ }
+ break;
+ }
+
+ // We need a valid name.. make it Player
+ if (*name == '\0') ttd_strlcpy(name, "Player", sizeof(name));
+
+ if (!NetworkFindName(name)) { // Change name if duplicate
+ // We could not create a name for this player
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
+ return;
+ }
+
+ ci = DEREF_CLIENT_INFO(cs);
+
+ ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
+ ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
+ ci->client_playas = playas;
+ ci->client_lang = client_lang;
+
+ // We now want a password from the client
+ // else we do not allow him in!
+ if (_network_game_info.use_password) {
+ SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
+ } else {
+ if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
+ SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
+ } else {
+ SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
+ }
+ }
+
+ /* Make sure companies to which people try to join are not autocleaned */
+ if (IsValidPlayer(playas)) _network_player_info[playas].months_empty = 0;
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
+{
+ NetworkPasswordType type;
+ char password[NETWORK_PASSWORD_LENGTH];
+ const NetworkClientInfo *ci;
+
+ type = NetworkRecv_uint8(cs, p);
+ NetworkRecv_string(cs, p, password, sizeof(password));
+
+ if (cs->status == STATUS_INACTIVE && type == NETWORK_GAME_PASSWORD) {
+ // Check game-password
+ if (strcmp(password, _network_game_info.server_password) != 0) {
+ // Password is invalid
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
+ return;
+ }
+
+ ci = DEREF_CLIENT_INFO(cs);
+
+ if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
+ SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
+ return;
+ }
+
+ // Valid password, allow user
+ SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
+ return;
+ } else if (cs->status == STATUS_INACTIVE && type == NETWORK_COMPANY_PASSWORD) {
+ ci = DEREF_CLIENT_INFO(cs);
+
+ if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
+ // Password is invalid
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
+ return;
+ }
+
+ SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
+ return;
+ }
+
+
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+ return;
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
+{
+ const NetworkClientState *new_cs;
+
+ // The client was never joined.. so this is impossible, right?
+ // Ignore the packet, give the client a warning, and close his connection
+ if (cs->status < STATUS_AUTH || cs->has_quit) {
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
+ return;
+ }
+
+ // Check if someone else is receiving the map
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status == STATUS_MAP) {
+ // Tell the new client to wait
+ cs->status = STATUS_MAP_WAIT;
+ SEND_COMMAND(PACKET_SERVER_WAIT)(cs);
+ return;
+ }
+ }
+
+ // We receive a request to upload the map.. give it to the client!
+ SEND_COMMAND(PACKET_SERVER_MAP)(cs);
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
+{
+ // Client has the map, now start syncing
+ if (cs->status == STATUS_DONE_MAP && !cs->has_quit) {
+ char client_name[NETWORK_CLIENT_NAME_LENGTH];
+ NetworkClientState *new_cs;
+
+ NetworkGetClientName(client_name, sizeof(client_name), cs);
+
+ NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, client_name, "");
+
+ // Mark the client as pre-active, and wait for an ACK
+ // so we know he is done loading and in sync with us
+ cs->status = STATUS_PRE_ACTIVE;
+ NetworkHandleCommandQueue(cs);
+ SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
+ SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
+
+ // This is the frame the client receives
+ // we need it later on to make sure the client is not too slow
+ cs->last_frame = _frame_counter;
+ cs->last_frame_server = _frame_counter;
+
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status > STATUS_AUTH) {
+ SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, DEREF_CLIENT_INFO(cs));
+ SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->index);
+ }
+ }
+
+ if (_network_pause_on_join) {
+ /* Now pause the game till the client is in sync */
+ DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
+
+ NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
+ }
+ } else {
+ // Wrong status for this packet, give a warning to client, and close connection
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+ }
+}
+
+/** Enforce the command flags.
+ * Eg a server-only command can only be executed by a server, etc.
+ * @param *cp the commandpacket that is going to be checked
+ * @param *ci client information for debugging output to console
+ */
+static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *ci)
+{
+ byte flags = GetCommandFlags(cp->cmd);
+
+ if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
+ IConsolePrintF(_icolour_err, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
+ return false;
+ }
+
+ if (flags & CMD_OFFLINE) {
+ IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
+ return false;
+ }
+
+ return true;
+}
+
+/** The client has done a command and wants us to handle it
+ * @param *cs the connected client that has sent the command
+ * @param *p the packet in which the command was sent
+ */
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
+{
+ NetworkClientState *new_cs;
+ const NetworkClientInfo *ci;
+ byte callback;
+
+ CommandPacket *cp = malloc(sizeof(CommandPacket));
+
+ // The client was never joined.. so this is impossible, right?
+ // Ignore the packet, give the client a warning, and close his connection
+ if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+ return;
+ }
+
+ cp->player = NetworkRecv_uint8(cs, p);
+ cp->cmd = NetworkRecv_uint32(cs, p);
+ cp->p1 = NetworkRecv_uint32(cs, p);
+ cp->p2 = NetworkRecv_uint32(cs, p);
+ cp->tile = NetworkRecv_uint32(cs, p);
+ NetworkRecv_string(cs, p, cp->text, lengthof(cp->text));
+
+ callback = NetworkRecv_uint8(cs, p);
+
+ if (cs->has_quit) return;
+
+ ci = DEREF_CLIENT_INFO(cs);
+
+ /* Check if cp->cmd is valid */
+ if (!IsValidCommand(cp->cmd)) {
+ IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+ return;
+ }
+
+ if (!CheckCommandFlags(cp, ci)) {
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
+ return;
+ }
+
+ /** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs
+ * to match the player in the packet. If it doesn't, the client has done
+ * something pretty naughty (or a bug), and will be kicked
+ */
+ if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) {
+ IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
+ ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1);
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
+ return;
+ }
+
+ /** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the
+ * player the correct ID, the server injects p2 and executes the command. Any other p1
+ * is prohibited. Pretty ugly and should be redone together with its function.
+ * @see CmdPlayerCtrl() players.c:655
+ */
+ if (cp->cmd == CMD_PLAYER_CTRL) {
+ if (cp->p1 != 0) {
+ SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
+ return;
+ }
+
+ /* XXX - Execute the command as a valid player. Normally this would be done by a
+ * spectator, but that is not allowed any commands. So do an impersonation. The drawback
+ * of this is that the first company's last_built_tile is also updated... */
+ cp->player = 0;
+ cp->p2 = cs - _clients; // XXX - UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
+ }
+
+ // The frame can be executed in the same frame as the next frame-packet
+ // That frame just before that frame is saved in _frame_counter_max
+ cp->frame = _frame_counter_max + 1;
+ cp->next = NULL;
+
+ // Queue the command for the clients (are send at the end of the frame
+ // if they can handle it ;))
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status >= STATUS_MAP) {
+ // Callbacks are only send back to the client who sent them in the
+ // first place. This filters that out.
+ cp->callback = (new_cs != cs) ? 0 : callback;
+ NetworkAddCommandQueue(new_cs, cp);
+ }
+ }
+
+ cp->callback = 0;
+ // Queue the command on the server
+ if (_local_command_queue == NULL) {
+ _local_command_queue = cp;
+ } else {
+ // Find last packet
+ CommandPacket *c = _local_command_queue;
+ while (c->next != NULL) c = c->next;
+ c->next = cp;
+ }
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
+{
+ // This packets means a client noticed an error and is reporting this
+ // to us. Display the error and report it to the other clients
+ NetworkClientState *new_cs;
+ char str[100];
+ char client_name[NETWORK_CLIENT_NAME_LENGTH];
+ NetworkErrorCode errorno = NetworkRecv_uint8(cs, p);
+
+ // The client was never joined.. thank the client for the packet, but ignore it
+ if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
+ cs->has_quit = true;
+ return;
+ }
+
+ NetworkGetClientName(client_name, sizeof(client_name), cs);
+
+ GetNetworkErrorMsg(str, errorno, lastof(str));
+
+ DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
+
+ NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status > STATUS_AUTH) {
+ SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
+ }
+ }
+
+ cs->has_quit = true;
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
+{
+ // The client wants to leave. Display this and report it to the other
+ // clients.
+ NetworkClientState *new_cs;
+ char str[100];
+ char client_name[NETWORK_CLIENT_NAME_LENGTH];
+
+ // The client was never joined.. thank the client for the packet, but ignore it
+ if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
+ cs->has_quit = true;
+ return;
+ }
+
+ NetworkRecv_string(cs, p, str, lengthof(str));
+
+ NetworkGetClientName(client_name, sizeof(client_name), cs);
+
+ NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+
+ FOR_ALL_CLIENTS(new_cs) {
+ if (new_cs->status > STATUS_AUTH) {
+ SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->index, str);
+ }
+ }
+
+ cs->has_quit = true;
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
+{
+ uint32 frame = NetworkRecv_uint32(cs, p);
+
+ /* The client is trying to catch up with the server */
+ if (cs->status == STATUS_PRE_ACTIVE) {
+ /* The client is not yet catched up? */
+ if (frame + DAY_TICKS < _frame_counter) return;
+
+ /* Now he is! Unpause the game */
+ cs->status = STATUS_ACTIVE;
+
+ if (_network_pause_on_join) {
+ DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
+ NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
+ }
+
+ CheckMinPlayers();
+
+ /* Execute script for, e.g. MOTD */
+ IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
+ }
+
+ // The client received the frame, make note of it
+ cs->last_frame = frame;
+ // With those 2 values we can calculate the lag realtime
+ cs->last_frame_server = _frame_counter;
+}
+
+
+
+void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
+{
+ NetworkClientState *cs;
+ const NetworkClientInfo *ci, *ci_own, *ci_to;
+
+ switch (desttype) {
+ case DESTTYPE_CLIENT:
+ /* Are we sending to the server? */
+ if (dest == NETWORK_SERVER_INDEX) {
+ ci = NetworkFindClientInfoFromIndex(from_index);
+ /* Display the text locally, and that is it */
+ if (ci != NULL)
+ NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
+ } else {
+ /* Else find the client to send the message to */
+ FOR_ALL_CLIENTS(cs) {
+ if (cs->index == dest) {
+ SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
+ break;
+ }
+ }
+ }
+
+ // Display the message locally (so you know you have sent it)
+ if (from_index != dest) {
+ if (from_index == NETWORK_SERVER_INDEX) {
+ ci = NetworkFindClientInfoFromIndex(from_index);
+ ci_to = NetworkFindClientInfoFromIndex(dest);
+ if (ci != NULL && ci_to != NULL)
+ NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
+ } else {
+ FOR_ALL_CLIENTS(cs) {
+ if (cs->index == from_index) {
+ SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, dest, true, msg);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case DESTTYPE_TEAM: {
+ bool show_local = true; // If this is false, the message is already displayed
+ // on the client who did sent it.
+ /* Find all clients that belong to this player */
+ ci_to = NULL;
+ FOR_ALL_CLIENTS(cs) {
+ ci = DEREF_CLIENT_INFO(cs);
+ if (ci->client_playas == dest) {
+ SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
+ if (cs->index == from_index) show_local = false;
+ ci_to = ci; // Remember a client that is in the company for company-name
+ }
+ }
+
+ ci = NetworkFindClientInfoFromIndex(from_index);
+ ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+ if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
+ NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
+ if (from_index == NETWORK_SERVER_INDEX) show_local = false;
+ ci_to = ci_own;
+ }
+
+ /* There is no such player */
+ if (ci_to == NULL) break;
+
+ // Display the message locally (so you know you have sent it)
+ if (ci != NULL && show_local) {
+ if (from_index == NETWORK_SERVER_INDEX) {
+ char name[NETWORK_NAME_LENGTH];
+ StringID str = IsValidPlayer(ci_to->client_playas) ? GetPlayer(ci_to->client_playas)->name_1 : STR_NETWORK_SPECTATORS;
+ GetString(name, str, lastof(name));
+ NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
+ } else {
+ FOR_ALL_CLIENTS(cs) {
+ if (cs->index == from_index) {
+ SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_index, true, msg);
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
+ /* fall-through to next case */
+ case DESTTYPE_BROADCAST:
+ FOR_ALL_CLIENTS(cs) {
+ SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
+ }
+ ci = NetworkFindClientInfoFromIndex(from_index);
+ if (ci != NULL)
+ NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
+ break;
+ }
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
+{
+ NetworkAction action = NetworkRecv_uint8(cs, p);
+ DestType desttype = NetworkRecv_uint8(cs, p);
+ int dest = NetworkRecv_uint8(cs, p);
+ char msg[MAX_TEXT_MSG_LEN];
+
+ NetworkRecv_string(cs, p, msg, MAX_TEXT_MSG_LEN);
+
+ NetworkServer_HandleChat(action, desttype, dest, msg, cs->index);
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
+{
+ char password[NETWORK_PASSWORD_LENGTH];
+ const NetworkClientInfo *ci;
+
+ NetworkRecv_string(cs, p, password, sizeof(password));
+ ci = DEREF_CLIENT_INFO(cs);
+
+ if (IsValidPlayer(ci->client_playas)) {
+ ttd_strlcpy(_network_player_info[ci->client_playas].password, password, sizeof(_network_player_info[0].password));
+ }
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
+{
+ char client_name[NETWORK_CLIENT_NAME_LENGTH];
+ NetworkClientInfo *ci;
+
+ NetworkRecv_string(cs, p, client_name, sizeof(client_name));
+ ci = DEREF_CLIENT_INFO(cs);
+
+ if (cs->has_quit) return;
+
+ if (ci != NULL) {
+ // Display change
+ if (NetworkFindName(client_name)) {
+ NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", client_name);
+ ttd_strlcpy(ci->client_name, client_name, sizeof(ci->client_name));
+ NetworkUpdateClientInfo(ci->client_index);
+ }
+ }
+}
+
+DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
+{
+ char pass[NETWORK_PASSWORD_LENGTH];
+ char command[NETWORK_RCONCOMMAND_LENGTH];
+
+ if (_network_game_info.rcon_password[0] == '\0') return;
+
+ NetworkRecv_string(cs, p, pass, sizeof(pass));
+ NetworkRecv_string(cs, p, command, sizeof(command));
+
+ if (strcmp(pass, _network_game_info.rcon_password) != 0) {
+ DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
+ return;
+ }
+
+ DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->index, command);
+
+ _redirect_console_to_client = cs->index;
+ IConsoleCmdExec(command);
+ _redirect_console_to_client = 0;
+ return;
+}
+
+// The layout for the receive-functions by the server
+typedef void NetworkServerPacket(NetworkClientState *cs, Packet *p);
+
+
+// This array matches PacketType. At an incoming
+// packet it is matches against this array
+// and that way the right function to handle that
+// packet is found.
+static NetworkServerPacket* const _network_server_packet[] = {
+ NULL, /*PACKET_SERVER_FULL,*/
+ NULL, /*PACKET_SERVER_BANNED,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_JOIN),
+ NULL, /*PACKET_SERVER_ERROR,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO),
+ NULL, /*PACKET_SERVER_COMPANY_INFO,*/
+ NULL, /*PACKET_SERVER_CLIENT_INFO,*/
+ NULL, /*PACKET_SERVER_NEED_PASSWORD,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD),
+ NULL, /*PACKET_SERVER_WELCOME,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_GETMAP),
+ NULL, /*PACKET_SERVER_WAIT,*/
+ NULL, /*PACKET_SERVER_MAP,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK),
+ NULL, /*PACKET_SERVER_JOIN,*/
+ NULL, /*PACKET_SERVER_FRAME,*/
+ NULL, /*PACKET_SERVER_SYNC,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_ACK),
+ RECEIVE_COMMAND(PACKET_CLIENT_COMMAND),
+ NULL, /*PACKET_SERVER_COMMAND,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_CHAT),
+ NULL, /*PACKET_SERVER_CHAT,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD),
+ RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME),
+ RECEIVE_COMMAND(PACKET_CLIENT_QUIT),
+ RECEIVE_COMMAND(PACKET_CLIENT_ERROR),
+ NULL, /*PACKET_SERVER_QUIT,*/
+ NULL, /*PACKET_SERVER_ERROR_QUIT,*/
+ NULL, /*PACKET_SERVER_SHUTDOWN,*/
+ NULL, /*PACKET_SERVER_NEWGAME,*/
+ NULL, /*PACKET_SERVER_RCON,*/
+ RECEIVE_COMMAND(PACKET_CLIENT_RCON),
+};
+
+// If this fails, check the array above with network_data.h
+assert_compile(lengthof(_network_server_packet) == PACKET_END);
+
+// This update the company_info-stuff
+void NetworkPopulateCompanyInfo(void)
+{
+ char password[NETWORK_PASSWORD_LENGTH];
+ const Player *p;
+ const Vehicle *v;
+ const Station *s;
+ const NetworkClientState *cs;
+ const NetworkClientInfo *ci;
+ uint i;
+ uint16 months_empty;
+
+ FOR_ALL_PLAYERS(p) {
+ if (!p->is_active) {
+ memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
+ continue;
+ }
+
+ // Clean the info but not the password
+ ttd_strlcpy(password, _network_player_info[p->index].password, sizeof(password));
+ months_empty = _network_player_info[p->index].months_empty;
+ memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
+ _network_player_info[p->index].months_empty = months_empty;
+ ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password));
+
+ // Grap the company name
+ SetDParam(0, p->name_1);
+ SetDParam(1, p->name_2);
+ GetString(_network_player_info[p->index].company_name, STR_JUST_STRING, lastof(_network_player_info[p->index].company_name));
+
+ // Check the income
+ if (_cur_year - 1 == p->inaugurated_year) {
+ // The player is here just 1 year, so display [2], else display[1]
+ for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) {
+ _network_player_info[p->index].income -= p->yearly_expenses[2][i];
+ }
+ } else {
+ for (i = 0; i < lengthof(p->yearly_expenses[1]); i++) {
+ _network_player_info[p->index].income -= p->yearly_expenses[1][i];
+ }
+ }
+
+ // Set some general stuff
+ _network_player_info[p->index].inaugurated_year = p->inaugurated_year;
+ _network_player_info[p->index].company_value = p->old_economy[0].company_value;
+ _network_player_info[p->index].money = p->money64;
+ _network_player_info[p->index].performance = p->old_economy[0].performance_history;
+ }
+
+ // Go through all vehicles and count the type of vehicles
+ FOR_ALL_VEHICLES(v) {
+ if (!IsValidPlayer(v->owner)) continue;
+
+ switch (v->type) {
+ case VEH_Train:
+ if (IsFrontEngine(v)) _network_player_info[v->owner].num_vehicle[0]++;
+ break;
+
+ case VEH_Road:
+ if (v->cargo_type != CT_PASSENGERS) {
+ _network_player_info[v->owner].num_vehicle[1]++;
+ } else {
+ _network_player_info[v->owner].num_vehicle[2]++;
+ }
+ break;
+
+ case VEH_Aircraft:
+ if (v->subtype <= 2) _network_player_info[v->owner].num_vehicle[3]++;
+ break;
+
+ case VEH_Ship:
+ _network_player_info[v->owner].num_vehicle[4]++;
+ break;
+
+ case VEH_Special:
+ case VEH_Disaster:
+ break;
+ }
+ }
+
+ // Go through all stations and count the types of stations
+ FOR_ALL_STATIONS(s) {
+ if (IsValidPlayer(s->owner)) {
+ NetworkPlayerInfo *npi = &_network_player_info[s->owner];
+
+ if (s->facilities & FACIL_TRAIN) npi->num_station[0]++;
+ if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[1]++;
+ if (s->facilities & FACIL_BUS_STOP) npi->num_station[2]++;
+ if (s->facilities & FACIL_AIRPORT) npi->num_station[3]++;
+ if (s->facilities & FACIL_DOCK) npi->num_station[4]++;
+ }
+ }
+
+ ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+ // Register local player (if not dedicated)
+ if (ci != NULL && IsValidPlayer(ci->client_playas))
+ ttd_strlcpy(_network_player_info[ci->client_playas].players, ci->client_name, sizeof(_network_player_info[0].players));
+
+ FOR_ALL_CLIENTS(cs) {
+ char client_name[NETWORK_CLIENT_NAME_LENGTH];
+
+ NetworkGetClientName(client_name, sizeof(client_name), cs);
+
+ ci = DEREF_CLIENT_INFO(cs);
+ if (ci != NULL && IsValidPlayer(ci->client_playas)) {
+ if (strlen(_network_player_info[ci->client_playas].players) != 0)
+ ttd_strlcat(_network_player_info[ci->client_playas].players, ", ", lengthof(_network_player_info[0].players));
+
+ ttd_strlcat(_network_player_info[ci->client_playas].players, client_name, lengthof(_network_player_info[0].players));
+ }
+ }
+}
+
+// Send a packet to all clients with updated info about this client_index
+void NetworkUpdateClientInfo(uint16 client_index)
+{
+ NetworkClientState *cs;
+ NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
+
+ if (ci == NULL) return;
+
+ FOR_ALL_CLIENTS(cs) {
+ SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, ci);
+ }
+}
+
+/* Check if we want to restart the map */
+static void NetworkCheckRestartMap(void)
+{
+ if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
+ DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
+
+ StartNewGameWithoutGUI(GENERATE_NEW_SEED);
+ }
+}
+
+/* Check if the server has autoclean_companies activated
+ Two things happen:
+ 1) If a company is not protected, it is closed after 1 year (for example)
+ 2) If a company is protected, protection is disabled after 3 years (for example)
+ (and item 1. happens a year later) */
+static void NetworkAutoCleanCompanies(void)
+{
+ const NetworkClientState *cs;
+ const NetworkClientInfo *ci;
+ const Player *p;
+ bool clients_in_company[MAX_PLAYERS];
+
+ if (!_network_autoclean_companies) return;
+
+ memset(clients_in_company, 0, sizeof(clients_in_company));
+
+ /* Detect the active companies */
+ FOR_ALL_CLIENTS(cs) {
+ ci = DEREF_CLIENT_INFO(cs);
+ if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
+ }
+
+ if (!_network_dedicated) {
+ ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+ if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
+ }
+
+ /* Go through all the comapnies */
+ FOR_ALL_PLAYERS(p) {
+ /* Skip the non-active once */
+ if (!p->is_active || p->is_ai) continue;
+
+ if (!clients_in_company[p->index]) {
+ /* The company is empty for one month more */
+ _network_player_info[p->index].months_empty++;
+
+ /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
+ if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
+ /* Shut the company down */
+ DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
+ IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1);
+ }
+ /* Is the compnay empty for autoclean_protected-months, and there is a protection? */
+ if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
+ /* Unprotect the company */
+ _network_player_info[p->index].password[0] = '\0';
+ IConsolePrintF(_icolour_def, "Auto-removed protection from company #%d", p->index+1);
+ _network_player_info[p->index].months_empty = 0;
+ }
+ } else {
+ /* It is not empty, reset the date */
+ _network_player_info[p->index].months_empty = 0;
+ }
+ }
+}
+
+// This function changes new_name to a name that is unique (by adding #1 ...)
+// and it returns true if that succeeded.
+bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
+{
+ NetworkClientState *new_cs;
+ bool found_name = false;
+ byte number = 0;
+ char original_name[NETWORK_CLIENT_NAME_LENGTH];
+
+ // We use NETWORK_CLIENT_NAME_LENGTH in here, because new_name is really a pointer
+ ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
+
+ while (!found_name) {
+ const NetworkClientInfo *ci;
+
+ found_name = true;
+ FOR_ALL_CLIENTS(new_cs) {
+ ci = DEREF_CLIENT_INFO(new_cs);
+ if (strcmp(ci->client_name, new_name) == 0) {
+ // Name already in use
+ found_name = false;
+ break;
+ }
+ }
+ // Check if it is the same as the server-name
+ ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+ if (ci != NULL) {
+ if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
+ }
+
+ if (!found_name) {
+ // Try a new name (<name> #1, <name> #2, and so on)
+
+ // Stop if we tried for more than 50 times..
+ if (number++ > 50) break;
+ snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
+ }
+ }
+
+ return found_name;
+}
+
+// Reads a packet from the stream
+bool NetworkServer_ReadPackets(NetworkClientState *cs)
+{
+ Packet *p;
+ NetworkRecvStatus res;
+ while ((p = NetworkRecv_Packet(cs, &res)) != NULL) {
+ byte type = NetworkRecv_uint8(cs, p);
+ if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->has_quit) {
+ _network_server_packet[type](cs, p);
+ } else {
+ DEBUG(net, 0, "[server] received invalid packet type %d", type);
+ }
+ free(p);
+ }
+
+ return true;
+}
+
+// Handle the local command-queue
+static void NetworkHandleCommandQueue(NetworkClientState* cs)
+{
+ CommandPacket *cp;
+
+ while ( (cp = cs->command_queue) != NULL) {
+ SEND_COMMAND(PACKET_SERVER_COMMAND)(cs, cp);
+
+ cs->command_queue = cp->next;
+ free(cp);
+ }
+}
+
+// This is called every tick if this is a _network_server
+void NetworkServer_Tick(bool send_frame)
+{
+ NetworkClientState *cs;
+#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
+ bool send_sync = false;
+#endif
+
+#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
+ if (_frame_counter >= _last_sync_frame + _network_sync_freq) {
+ _last_sync_frame = _frame_counter;
+ send_sync = true;
+ }
+#endif
+
+ // Now we are done with the frame, inform the clients that they can
+ // do their frame!
+ FOR_ALL_CLIENTS(cs) {
+ // Check if the speed of the client is what we can expect from a client
+ if (cs->status == STATUS_ACTIVE) {
+ // 1 lag-point per day
+ int lag = NetworkCalculateLag(cs) / DAY_TICKS;
+ if (lag > 0) {
+ if (lag > 3) {
+ // Client did still not report in after 4 game-day, drop him
+ // (that is, the 3 of above, + 1 before any lag is counted)
+ IConsolePrintF(_icolour_err,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
+ NetworkCloseClient(cs);
+ continue;
+ }
+
+ // Report once per time we detect the lag
+ if (cs->lag_test == 0) {
+ IConsolePrintF(_icolour_warn,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
+ cs->lag_test = 1;
+ }
+ } else {
+ cs->lag_test = 0;
+ }
+ } else if (cs->status == STATUS_PRE_ACTIVE) {
+ int lag = NetworkCalculateLag(cs);
+ if (lag > _network_max_join_time) {
+ IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
+ NetworkCloseClient(cs);
+ }
+ }
+
+ if (cs->status >= STATUS_PRE_ACTIVE) {
+ // Check if we can send command, and if we have anything in the queue
+ NetworkHandleCommandQueue(cs);
+
+ // Send an updated _frame_counter_max to the client
+ if (send_frame) SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
+
+#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
+ // Send a sync-check packet
+ if (send_sync) SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
+#endif
+ }
+ }
+
+ /* See if we need to advertise */
+ NetworkUDPAdvertise();
+}
+
+void NetworkServerYearlyLoop(void)
+{
+ NetworkCheckRestartMap();
+}
+
+void NetworkServerMonthlyLoop(void)
+{
+ NetworkAutoCleanCompanies();
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_server.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,39 @@
+/* $Id$ */
+
+#ifndef NETWORK_SERVER_H
+#define NETWORK_SERVER_H
+
+#ifdef ENABLE_NETWORK
+
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP);
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, uint16 client_index, NetworkErrorCode errorno);
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error);
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN);
+DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command);
+
+bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
+void NetworkServer_HandleChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
+
+bool NetworkServer_ReadPackets(NetworkClientState *cs);
+void NetworkServer_Tick(bool send_frame);
+void NetworkServerMonthlyLoop(void);
+void NetworkServerYearlyLoop(void);
+
+static inline const char* GetPlayerIP(const NetworkClientInfo* ci)
+{
+ struct in_addr addr;
+
+ addr.s_addr = ci->client_ip;
+ return inet_ntoa(addr);
+}
+
+#else /* ENABLE_NETWORK */
+/* Network function stubs when networking is disabled */
+
+static inline void NetworkServerMonthlyLoop(void) {}
+static inline void NetworkServerYearlyLoop(void) {}
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_SERVER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_udp.c Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,663 @@
+/* $Id$ */
+
+#ifdef ENABLE_NETWORK
+
+#include "../stdafx.h"
+#include "../debug.h"
+#include "../string.h"
+#include "network_data.h"
+#include "../date.h"
+#include "../map.h"
+#include "network_gamelist.h"
+#include "network_udp.h"
+#include "../variables.h"
+#include "../newgrf_config.h"
+
+#include "core/udp.h"
+
+/**
+ * @file network_udp.c This file handles the UDP related communication.
+ *
+ * This is the GameServer <-> MasterServer and GameServer <-> GameClient
+ * communication before the game is being joined.
+ */
+
+enum {
+ ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes)
+ ADVERTISE_RETRY_INTERVAL = 300, // readvertise when no response after this many ticks (9 seconds)
+ ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries
+};
+
+#define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, struct sockaddr_in *client_addr)
+
+static NetworkClientState _udp_cs;
+
+DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER)
+{
+ Packet *packet;
+ // Just a fail-safe.. should never happen
+ if (!_network_udp_server)
+ return;
+
+ packet = NetworkSend_Init(PACKET_UDP_SERVER_RESPONSE);
+
+ // Update some game_info
+ _network_game_info.game_date = _date;
+ _network_game_info.map_width = MapSizeX();
+ _network_game_info.map_height = MapSizeY();
+ _network_game_info.map_set = _opt.landscape;
+ _network_game_info.companies_on = ActivePlayerCount();
+ _network_game_info.spectators_on = NetworkSpectatorCount();
+ _network_game_info.grfconfig = _grfconfig;
+
+ NetworkSend_NetworkGameInfo(p, &_network_game_info);
+
+ // Let the client know that we are here
+ NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
+
+ free(packet);
+
+ DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr));
+}
+
+void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
+{
+ /* Find the matching GRF file */
+ const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum);
+ if (f == NULL) {
+ /* Don't know the GRF, so mark game incompatible and the (possibly)
+ * already resolved name for this GRF (another server has sent the
+ * name of the GRF already */
+ config->name = FindUnknownGRFName(config->grfid, config->md5sum, true);
+ SETBIT(config->flags, GCF_NOT_FOUND);
+ } else {
+ config->filename = f->filename;
+ config->name = f->name;
+ config->info = f->info;
+ }
+ SETBIT(config->flags, GCF_COPY);
+}
+
+DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE)
+{
+ extern const char _openttd_revision[];
+ NetworkGameList *item;
+
+ // Just a fail-safe.. should never happen
+ if (_network_udp_server || _udp_cs.has_quit) return;
+
+ DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
+
+ // Find next item
+ item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
+
+ NetworkRecv_NetworkGameInfo(&_udp_cs, p, &item->info);
+
+ item->info.compatible = true;
+ {
+ /* Checks whether there needs to be a request for names of GRFs and makes
+ * the request if necessary. GRFs that need to be requested are the GRFs
+ * that do not exist on the clients system and we do not have the name
+ * resolved of, i.e. the name is still UNKNOWN_GRF_NAME_PLACEHOLDER.
+ * The in_request array and in_request_count are used so there is no need
+ * to do a second loop over the GRF list, which can be relatively expensive
+ * due to the string comparisons. */
+ const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT];
+ const GRFConfig *c;
+ uint in_request_count = 0;
+ struct sockaddr_in out_addr;
+
+ for (c = item->info.grfconfig; c != NULL; c = c->next) {
+ if (HASBIT(c->flags, GCF_NOT_FOUND)) item->info.compatible = false;
+ if (!HASBIT(c->flags, GCF_NOT_FOUND) || strcmp(c->name, UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue;
+ in_request[in_request_count] = c;
+ in_request_count++;
+ }
+
+ if (in_request_count > 0) {
+ /* There are 'unknown' GRFs, now send a request for them */
+ uint i;
+ Packet *packet = NetworkSend_Init(PACKET_UDP_CLIENT_GET_NEWGRFS);
+
+ NetworkSend_uint8 (packet, in_request_count);
+ for (i = 0; i < in_request_count; i++) {
+ NetworkSend_GRFIdentifier(packet, in_request[i]);
+ }
+
+ out_addr.sin_family = AF_INET;
+ out_addr.sin_port = htons(item->port);
+ out_addr.sin_addr.s_addr = item->ip;
+ NetworkSendUDP_Packet(_udp_client_socket, packet, &out_addr);
+ free(packet);
+ }
+ }
+
+ if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
+ if (item->info.map_set >= NUM_LANDSCAPE ) item->info.map_set = 0;
+
+ if (item->info.hostname[0] == '\0')
+ snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
+
+ /* Check if we are allowed on this server based on the revision-match */
+ item->info.version_compatible =
+ strcmp(item->info.server_revision, _openttd_revision) == 0 ||
+ strcmp(item->info.server_revision, NOREV_STRING) == 0;
+ item->info.compatible &= item->info.version_compatible; // Already contains match for GRFs
+
+ item->online = true;
+
+ UpdateNetworkGameWindow(false);
+}
+
+DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO)
+{
+ NetworkClientState *cs;
+ NetworkClientInfo *ci;
+ Packet *packet;
+ Player *player;
+ byte current = 0;
+ int i;
+
+ // Just a fail-safe.. should never happen
+ if (!_network_udp_server) return;
+
+ packet = NetworkSend_Init(PACKET_UDP_SERVER_DETAIL_INFO);
+
+ /* Send the amount of active companies */
+ NetworkSend_uint8 (packet, NETWORK_COMPANY_INFO_VERSION);
+ NetworkSend_uint8 (packet, ActivePlayerCount());
+
+ /* Fetch the latest version of everything */
+ NetworkPopulateCompanyInfo();
+
+ /* Go through all the players */
+ FOR_ALL_PLAYERS(player) {
+ /* Skip non-active players */
+ if (!player->is_active) continue;
+
+ current++;
+
+ /* Send the information */
+ NetworkSend_uint8(packet, current);
+
+ NetworkSend_string(packet, _network_player_info[player->index].company_name);
+ NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year);
+ NetworkSend_uint64(packet, _network_player_info[player->index].company_value);
+ NetworkSend_uint64(packet, _network_player_info[player->index].money);
+ NetworkSend_uint64(packet, _network_player_info[player->index].income);
+ NetworkSend_uint16(packet, _network_player_info[player->index].performance);
+
+ /* Send 1 if there is a passord for the company else send 0 */
+ if (_network_player_info[player->index].password[0] != '\0') {
+ NetworkSend_uint8(packet, 1);
+ } else {
+ NetworkSend_uint8(packet, 0);
+ }
+
+ for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
+ NetworkSend_uint16(packet, _network_player_info[player->index].num_vehicle[i]);
+
+ for (i = 0; i < NETWORK_STATION_TYPES; i++)
+ NetworkSend_uint16(packet, _network_player_info[player->index].num_station[i]);
+
+ /* Find the clients that are connected to this player */
+ FOR_ALL_CLIENTS(cs) {
+ ci = DEREF_CLIENT_INFO(cs);
+ if (ci->client_playas == player->index) {
+ /* The uint8 == 1 indicates that a client is following */
+ NetworkSend_uint8(packet, 1);
+ NetworkSend_string(packet, ci->client_name);
+ NetworkSend_string(packet, ci->unique_id);
+ NetworkSend_uint32(packet, ci->join_date);
+ }
+ }
+ /* Also check for the server itself */
+ ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+ if (ci->client_playas == player->index) {
+ /* The uint8 == 1 indicates that a client is following */
+ NetworkSend_uint8(packet, 1);
+ NetworkSend_string(packet, ci->client_name);
+ NetworkSend_string(packet, ci->unique_id);
+ NetworkSend_uint32(packet, ci->join_date);
+ }
+
+ /* Indicates end of client list */
+ NetworkSend_uint8(packet, 0);
+ }
+
+ /* And check if we have any spectators */
+ FOR_ALL_CLIENTS(cs) {
+ ci = DEREF_CLIENT_INFO(cs);
+ if (!IsValidPlayer(ci->client_playas)) {
+ /* The uint8 == 1 indicates that a client is following */
+ NetworkSend_uint8(packet, 1);
+ NetworkSend_string(packet, ci->client_name);
+ NetworkSend_string(packet, ci->unique_id);
+ NetworkSend_uint32(packet, ci->join_date);
+ }
+ }
+
+ /* Also check for the server itself */
+ ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+ if (!IsValidPlayer(ci->client_playas)) {
+ /* The uint8 == 1 indicates that a client is following */
+ NetworkSend_uint8(packet, 1);
+ NetworkSend_string(packet, ci->client_name);
+ NetworkSend_string(packet, ci->unique_id);
+ NetworkSend_uint32(packet, ci->join_date);
+ }
+
+ /* Indicates end of client list */
+ NetworkSend_uint8(packet, 0);
+
+ NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
+
+ free(packet);
+}
+
+DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST)
+{
+ int i;
+ struct in_addr ip;
+ uint16 port;
+ uint8 ver;
+
+ /* packet begins with the protocol version (uint8)
+ * then an uint16 which indicates how many
+ * ip:port pairs are in this packet, after that
+ * an uint32 (ip) and an uint16 (port) for each pair
+ */
+
+ ver = NetworkRecv_uint8(&_udp_cs, p);
+
+ if (_udp_cs.has_quit) return;
+
+ if (ver == 1) {
+ for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) {
+ ip.s_addr = TO_LE32(NetworkRecv_uint32(&_udp_cs, p));
+ port = NetworkRecv_uint16(&_udp_cs, p);
+ NetworkUDPQueryServer(inet_ntoa(ip), port);
+ }
+ }
+}
+
+DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER)
+{
+ _network_advertise_retries = 0;
+ DEBUG(net, 2, "[udp] advertising on master server successfull");
+
+ /* We are advertised, but we don't want to! */
+ if (!_network_advertise) NetworkUDPRemoveAdvertise();
+}
+
+/**
+ * A client has requested the names of some NewGRFs.
+ *
+ * Replying this can be tricky as we have a limit of SEND_MTU bytes
+ * in the reply packet and we can send up to 100 bytes per NewGRF
+ * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name).
+ * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it
+ * could be that a packet overflows. To stop this we only reply
+ * with the first N NewGRFs so that if the first N + 1 NewGRFs
+ * would be sent, the packet overflows.
+ * in_reply and in_reply_count are used to keep a list of GRFs to
+ * send in the reply.
+ */
+DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS)
+{
+ uint8 num_grfs;
+ uint i;
+
+ const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
+ Packet *packet;
+ uint8 in_reply_count = 0;
+ uint packet_len = 0;
+
+ /* Just a fail-safe.. should never happen */
+ if (_udp_cs.has_quit) return;
+
+ DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
+
+ num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
+ if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
+
+ for (i = 0; i < num_grfs; i++) {
+ GRFConfig c;
+ const GRFConfig *f;
+
+ NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
+
+ /* Find the matching GRF file */
+ f = FindGRFConfig(c.grfid, c.md5sum);
+ if (f == NULL) continue; // The GRF is unknown to this server
+
+ /* If the reply might exceed the size of the packet, only reply
+ * the current list and do not send the other data.
+ * The name could be an empty string, if so take the filename. */
+ packet_len += sizeof(c.grfid) + sizeof(c.md5sum) +
+ min(strlen((f->name != NULL && strlen(f->name) > 0) ? f->name : f->filename) + 1, NETWORK_GRF_NAME_LENGTH);
+ if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply
+ break;
+ }
+ in_reply[in_reply_count] = f;
+ in_reply_count++;
+ }
+
+ if (in_reply_count == 0) return;
+
+ packet = NetworkSend_Init(PACKET_UDP_SERVER_NEWGRFS);
+ NetworkSend_uint8 (packet, in_reply_count);
+ for (i = 0; i < in_reply_count; i++) {
+ char name[NETWORK_GRF_NAME_LENGTH];
+
+ /* The name could be an empty string, if so take the filename */
+ ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ?
+ in_reply[i]->name : in_reply[i]->filename, sizeof(name));
+ NetworkSend_GRFIdentifier(packet, in_reply[i]);
+ NetworkSend_string(packet, name);
+ }
+
+ NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
+ free(packet);
+}
+
+/** The return of the client's request of the names of some NewGRFs */
+DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS)
+{
+ uint8 num_grfs;
+ uint i;
+
+ /* Just a fail-safe.. should never happen */
+ if (_udp_cs.has_quit) return;
+
+ DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
+
+ num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
+ if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
+
+ for (i = 0; i < num_grfs; i++) {
+ char *unknown_name;
+ char name[NETWORK_GRF_NAME_LENGTH];
+ GRFConfig c;
+
+ NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
+ NetworkRecv_string(&_udp_cs, p, name, sizeof(name));
+
+ /* An empty name is not possible under normal circumstances
+ * and causes problems when showing the NewGRF list. */
+ if (strlen(name) == 0) continue;
+
+ /* Finds the fake GRFConfig for the just read GRF ID and MD5sum tuple.
+ * If it exists and not resolved yet, then name of the fake GRF is
+ * overwritten with the name from the reply. */
+ unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
+ if (unknown_name != NULL && strcmp(unknown_name, UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
+ ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH);
+ }
+ }
+}
+
+
+// The layout for the receive-functions by UDP
+typedef void NetworkUDPPacket(Packet *p, struct sockaddr_in *client_addr);
+
+static NetworkUDPPacket* const _network_udp_packet[] = {
+ RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER),
+ RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE),
+ RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO),
+ NULL,
+ NULL,
+ RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER),
+ NULL,
+ RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST),
+ NULL,
+ RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS),
+ RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS),
+};
+
+
+// If this fails, check the array above with network_data.h
+assert_compile(lengthof(_network_udp_packet) == PACKET_UDP_END);
+
+
+void NetworkHandleUDPPacket(Packet *p, struct sockaddr_in *client_addr)
+{
+ byte type;
+
+ /* Fake a client, so we can see when there is an illegal packet */
+ _udp_cs.socket = INVALID_SOCKET;
+ _udp_cs.has_quit = false;
+
+ type = NetworkRecv_uint8(&_udp_cs, p);
+
+ if (type < PACKET_UDP_END && _network_udp_packet[type] != NULL && !_udp_cs.has_quit) {
+ _network_udp_packet[type](p, client_addr);
+ } else {
+ if (!_udp_cs.has_quit) {
+ DEBUG(net, 0, "[udp] received invalid packet type %d", type);
+ } else {
+ DEBUG(net, 0, "[udp] received illegal packet");
+ }
+ }
+}
+
+
+// Close UDP connection
+void NetworkUDPClose(void)
+{
+ DEBUG(net, 1, "[udp] closed listeners");
+
+ if (_network_udp_server) {
+ if (_udp_server_socket != INVALID_SOCKET) {
+ closesocket(_udp_server_socket);
+ _udp_server_socket = INVALID_SOCKET;
+ }
+
+ if (_udp_master_socket != INVALID_SOCKET) {
+ closesocket(_udp_master_socket);
+ _udp_master_socket = INVALID_SOCKET;
+ }
+
+ _network_udp_server = false;
+ _network_udp_broadcast = 0;
+ } else {
+ if (_udp_client_socket != INVALID_SOCKET) {
+ closesocket(_udp_client_socket);
+ _udp_client_socket = INVALID_SOCKET;
+ }
+ _network_udp_broadcast = 0;
+ }
+}
+
+// Broadcast to all ips
+static void NetworkUDPBroadCast(SOCKET udp)
+{
+ Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
+ uint i;
+
+ for (i = 0; _broadcast_list[i] != 0; i++) {
+ struct sockaddr_in out_addr;
+
+ out_addr.sin_family = AF_INET;
+ out_addr.sin_port = htons(_network_server_port);
+ out_addr.sin_addr.s_addr = _broadcast_list[i];
+
+ DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
+
+ NetworkSendUDP_Packet(udp, p, &out_addr);
+ }
+
+ free(p);
+}
+
+
+// Request the the server-list from the master server
+void NetworkUDPQueryMasterServer(void)
+{
+ struct sockaddr_in out_addr;
+ Packet *p;
+
+ if (_udp_client_socket == INVALID_SOCKET)
+ if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
+ return;
+
+ p = NetworkSend_Init(PACKET_UDP_CLIENT_GET_LIST);
+
+ out_addr.sin_family = AF_INET;
+ out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
+ out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
+
+ // packet only contains protocol version
+ NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
+
+ NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
+
+ DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr),ntohs(out_addr.sin_port));
+
+ free(p);
+}
+
+// Find all servers
+void NetworkUDPSearchGame(void)
+{
+ // We are still searching..
+ if (_network_udp_broadcast > 0) return;
+
+ // No UDP-socket yet..
+ if (_udp_client_socket == INVALID_SOCKET)
+ if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
+ return;
+
+ DEBUG(net, 0, "[udp] searching server");
+
+ NetworkUDPBroadCast(_udp_client_socket);
+ _network_udp_broadcast = 300; // Stay searching for 300 ticks
+}
+
+NetworkGameList *NetworkUDPQueryServer(const char* host, unsigned short port)
+{
+ struct sockaddr_in out_addr;
+ Packet *p;
+ NetworkGameList *item;
+
+ // No UDP-socket yet..
+ if (_udp_client_socket == INVALID_SOCKET)
+ if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
+ return NULL;
+
+ out_addr.sin_family = AF_INET;
+ out_addr.sin_port = htons(port);
+ out_addr.sin_addr.s_addr = NetworkResolveHost(host);
+
+ // Clear item in gamelist
+ item = NetworkGameListAddItem(inet_addr(inet_ntoa(out_addr.sin_addr)), ntohs(out_addr.sin_port));
+ memset(&item->info, 0, sizeof(item->info));
+ ttd_strlcpy(item->info.server_name, host, lengthof(item->info.server_name));
+ ttd_strlcpy(item->info.hostname, host, lengthof(item->info.hostname));
+ item->online = false;
+
+ // Init the packet
+ p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
+
+ NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
+
+ free(p);
+
+ UpdateNetworkGameWindow(false);
+ return item;
+}
+
+/* Remove our advertise from the master-server */
+void NetworkUDPRemoveAdvertise(void)
+{
+ struct sockaddr_in out_addr;
+ Packet *p;
+
+ /* Check if we are advertising */
+ if (!_networking || !_network_server || !_network_udp_server) return;
+
+ /* check for socket */
+ if (_udp_master_socket == INVALID_SOCKET)
+ if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
+ return;
+
+ DEBUG(net, 1, "[udp] removing advertise from master server");
+
+ /* Find somewhere to send */
+ out_addr.sin_family = AF_INET;
+ out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
+ out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
+
+ /* Send the packet */
+ p = NetworkSend_Init(PACKET_UDP_SERVER_UNREGISTER);
+ /* Packet is: Version, server_port */
+ NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
+ NetworkSend_uint16(p, _network_server_port);
+ NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
+
+ free(p);
+}
+
+/* Register us to the master server
+ This function checks if it needs to send an advertise */
+void NetworkUDPAdvertise(void)
+{
+ struct sockaddr_in out_addr;
+ Packet *p;
+
+ /* Check if we should send an advertise */
+ if (!_networking || !_network_server || !_network_udp_server || !_network_advertise)
+ return;
+
+ /* check for socket */
+ if (_udp_master_socket == INVALID_SOCKET)
+ if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
+ return;
+
+ if (_network_need_advertise) {
+ _network_need_advertise = false;
+ _network_advertise_retries = ADVERTISE_RETRY_TIMES;
+ } else {
+ /* Only send once every ADVERTISE_NORMAL_INTERVAL ticks */
+ if (_network_advertise_retries == 0) {
+ if ((_network_last_advertise_frame + ADVERTISE_NORMAL_INTERVAL) > _frame_counter)
+ return;
+ _network_advertise_retries = ADVERTISE_RETRY_TIMES;
+ }
+
+ if ((_network_last_advertise_frame + ADVERTISE_RETRY_INTERVAL) > _frame_counter)
+ return;
+ }
+
+ _network_advertise_retries--;
+ _network_last_advertise_frame = _frame_counter;
+
+ /* Find somewhere to send */
+ out_addr.sin_family = AF_INET;
+ out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
+ out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
+
+ DEBUG(net, 1, "[udp] advertising to master server");
+
+ /* Send the packet */
+ p = NetworkSend_Init(PACKET_UDP_SERVER_REGISTER);
+ /* Packet is: WELCOME_MESSAGE, Version, server_port */
+ NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
+ NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
+ NetworkSend_uint16(p, _network_server_port);
+ NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
+
+ free(p);
+}
+
+void NetworkUDPInitialize(void)
+{
+ _udp_client_socket = INVALID_SOCKET;
+ _udp_server_socket = INVALID_SOCKET;
+ _udp_master_socket = INVALID_SOCKET;
+
+ _network_udp_server = false;
+ _network_udp_broadcast = 0;
+}
+
+#endif /* ENABLE_NETWORK */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network/network_udp.h Wed Jan 03 08:32:17 2007 +0000
@@ -0,0 +1,17 @@
+/* $Id$ */
+
+#ifndef NETWORK_UDP_H
+#define NETWORK_UDP_H
+
+#ifdef ENABLE_NETWORK
+
+void NetworkUDPInitialize(void);
+void NetworkUDPSearchGame(void);
+void NetworkUDPQueryMasterServer(void);
+NetworkGameList *NetworkUDPQueryServer(const char* host, unsigned short port);
+void NetworkUDPAdvertise(void);
+void NetworkUDPRemoveAdvertise(void);
+
+#endif /* ENABLE_NETWORK */
+
+#endif /* NETWORK_UDP_H */
--- a/network_client.c Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,818 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "stdafx.h"
-#include "debug.h"
-#include "string.h"
-#include "strings.h"
-#include "network_data.h"
-#include "date.h"
-#include "table/strings.h"
-#include "functions.h"
-#include "network_client.h"
-#include "network_gamelist.h"
-#include "network_gui.h"
-#include "saveload.h"
-#include "command.h"
-#include "window.h"
-#include "console.h"
-#include "variables.h"
-#include "ai/ai.h"
-
-
-// This file handles all the client-commands
-
-
-// So we don't make too much typos ;)
-#define MY_CLIENT DEREF_CLIENT(0)
-
-static uint32 last_ack_frame;
-
-// **********
-// Sending functions
-// DEF_CLIENT_SEND_COMMAND has no parameters
-// **********
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)
-{
- //
- // Packet: CLIENT_COMPANY_INFO
- // Function: Request company-info (in detail)
- // Data:
- // <none>
- //
- Packet *p;
- _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- p = NetworkSend_Init(PACKET_CLIENT_COMPANY_INFO);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_JOIN)
-{
- //
- // Packet: CLIENT_JOIN
- // Function: Try to join the server
- // Data:
- // String: OpenTTD Revision (norev000 if no revision)
- // String: Player Name (max NETWORK_NAME_LENGTH)
- // uint8: Play as Player id (1..MAX_PLAYERS)
- // uint8: Language ID
- // String: Unique id to find the player back in server-listing
- //
-
- extern const char _openttd_revision[];
- Packet *p;
- _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- p = NetworkSend_Init(PACKET_CLIENT_JOIN);
- NetworkSend_string(p, _openttd_revision);
- NetworkSend_string(p, _network_player_name); // Player name
- NetworkSend_uint8(p, _network_playas); // PlayAs
- NetworkSend_uint8(p, NETLANG_ANY); // Language
- NetworkSend_string(p, _network_unique_id);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password)
-{
- //
- // Packet: CLIENT_PASSWORD
- // Function: Send a password to the server to authorize
- // Data:
- // uint8: NetworkPasswordType
- // String: Password
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_PASSWORD);
- NetworkSend_uint8(p, type);
- NetworkSend_string(p, password);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GETMAP)
-{
- //
- // Packet: CLIENT_GETMAP
- // Function: Request the map from the server
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_GETMAP);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_MAP_OK)
-{
- //
- // Packet: CLIENT_MAP_OK
- // Function: Tell the server that we are done receiving/loading the map
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_MAP_OK);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK)
-{
- //
- // Packet: CLIENT_ACK
- // Function: Tell the server we are done with this frame
- // Data:
- // uint32: current FrameCounter of the client
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_ACK);
-
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send a command packet to the server
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(CommandPacket *cp)
-{
- //
- // Packet: CLIENT_COMMAND
- // Function: Send a DoCommand to the Server
- // Data:
- // uint8: PlayerID (0..MAX_PLAYERS-1)
- // uint32: CommandID (see command.h)
- // uint32: P1 (free variables used in DoCommand)
- // uint32: P2
- // uint32: Tile
- // string: text
- // uint8: CallBackID (see callback_table.c)
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_COMMAND);
-
- NetworkSend_uint8(p, cp->player);
- NetworkSend_uint32(p, cp->cmd);
- NetworkSend_uint32(p, cp->p1);
- NetworkSend_uint32(p, cp->p2);
- NetworkSend_uint32(p, (uint32)cp->tile);
- NetworkSend_string(p, cp->text);
- NetworkSend_uint8(p, cp->callback);
-
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send a chat-packet over the network
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType type, int dest, const char *msg)
-{
- //
- // Packet: CLIENT_CHAT
- // Function: Send a chat-packet to the serve
- // Data:
- // uint8: ActionID (see network_data.h, NetworkAction)
- // uint8: Destination Type (see network_data.h, DestType);
- // uint8: Destination Player (1..MAX_PLAYERS)
- // String: Message (max MAX_TEXT_MSG_LEN)
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_CHAT);
-
- NetworkSend_uint8(p, action);
- NetworkSend_uint8(p, type);
- NetworkSend_uint8(p, dest);
- NetworkSend_string(p, msg);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send an error-packet over the network
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno)
-{
- //
- // Packet: CLIENT_ERROR
- // Function: The client made an error and is quiting the game
- // Data:
- // uint8: ErrorID (see network_data.h, NetworkErrorCode)
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_ERROR);
-
- NetworkSend_uint8(p, errorno);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password)
-{
- //
- // Packet: PACKET_CLIENT_SET_PASSWORD
- // Function: Set the password for the clients current company
- // Data:
- // String: Password
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_PASSWORD);
-
- NetworkSend_string(p, password);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name)
-{
- //
- // Packet: PACKET_CLIENT_SET_NAME
- // Function: Gives the player a new name
- // Data:
- // String: Name
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_NAME);
-
- NetworkSend_string(p, name);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send an quit-packet over the network
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg)
-{
- //
- // Packet: CLIENT_QUIT
- // Function: The client is quiting the game
- // Data:
- // String: leave-message
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_QUIT);
-
- NetworkSend_string(p, leavemsg);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command)
-{
- Packet *p = NetworkSend_Init(PACKET_CLIENT_RCON);
- NetworkSend_string(p, pass);
- NetworkSend_string(p, command);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-
-// **********
-// Receiving functions
-// DEF_CLIENT_RECEIVE_COMMAND has parameter: Packet *p
-// **********
-
-extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FULL)
-{
- // We try to join a server which is full
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_SERVER_FULL;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_BANNED)
-{
- // We try to join a server where we are banned
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_BANNED;
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_SERVER_BANNED;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO)
-{
- byte company_info_version;
- int i;
-
- company_info_version = NetworkRecv_uint8(MY_CLIENT, p);
-
- if (!MY_CLIENT->has_quit && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
- byte total;
- byte current;
-
- total = NetworkRecv_uint8(MY_CLIENT, p);
-
- // There is no data at all..
- if (total == 0) return NETWORK_RECV_STATUS_CLOSE_QUERY;
-
- current = NetworkRecv_uint8(MY_CLIENT, p);
- if (!IsValidPlayer(current)) return NETWORK_RECV_STATUS_CLOSE_QUERY;
-
- NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].company_name, sizeof(_network_player_info[current].company_name));
- _network_player_info[current].inaugurated_year = NetworkRecv_uint32(MY_CLIENT, p);
- _network_player_info[current].company_value = NetworkRecv_uint64(MY_CLIENT, p);
- _network_player_info[current].money = NetworkRecv_uint64(MY_CLIENT, p);
- _network_player_info[current].income = NetworkRecv_uint64(MY_CLIENT, p);
- _network_player_info[current].performance = NetworkRecv_uint16(MY_CLIENT, p);
- _network_player_info[current].use_password = NetworkRecv_uint8(MY_CLIENT, p);
- for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
- _network_player_info[current].num_vehicle[i] = NetworkRecv_uint16(MY_CLIENT, p);
- for (i = 0; i < NETWORK_STATION_TYPES; i++)
- _network_player_info[current].num_station[i] = NetworkRecv_uint16(MY_CLIENT, p);
-
- NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].players, sizeof(_network_player_info[current].players));
-
- InvalidateWindow(WC_NETWORK_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- return NETWORK_RECV_STATUS_CLOSE_QUERY;
-}
-
-// This packet contains info about the client (playas and name)
-// as client we save this in NetworkClientInfo, linked via 'index'
-// which is always an unique number on a server.
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
-{
- NetworkClientInfo *ci;
- uint16 index = NetworkRecv_uint16(MY_CLIENT, p);
- PlayerID playas = NetworkRecv_uint8(MY_CLIENT, p);
- char name[NETWORK_NAME_LENGTH];
- char unique_id[NETWORK_NAME_LENGTH];
-
- NetworkRecv_string(MY_CLIENT, p, name, sizeof(name));
- NetworkRecv_string(MY_CLIENT, p, unique_id, sizeof(unique_id));
-
- if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
-
- /* Do we receive a change of data? Most likely we changed playas */
- if (index == _network_own_client_index) _network_playas = playas;
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL) {
- if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
- // Client name changed, display the change
- NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", name);
- } else if (playas != ci->client_playas) {
- // The player changed from client-player..
- // Do not display that for now
- }
-
- ci->client_playas = playas;
- ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- // We don't have this index yet, find an empty index, and put the data there
- ci = NetworkFindClientInfoFromIndex(NETWORK_EMPTY_INDEX);
- if (ci != NULL) {
- ci->client_index = index;
- ci->client_playas = playas;
-
- ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
- ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- // Here the program should never ever come.....
- return NETWORK_RECV_STATUS_MALFORMED_PACKET;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
-{
- NetworkErrorCode error = NetworkRecv_uint8(MY_CLIENT, p);
-
- switch (error) {
- /* We made an error in the protocol, and our connection is closed.... */
- case NETWORK_ERROR_NOT_AUTHORIZED:
- case NETWORK_ERROR_NOT_EXPECTED:
- case NETWORK_ERROR_PLAYER_MISMATCH:
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR;
- break;
- case NETWORK_ERROR_FULL:
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
- break;
- case NETWORK_ERROR_WRONG_REVISION:
- _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_REVISION;
- break;
- case NETWORK_ERROR_WRONG_PASSWORD:
- _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_PASSWORD;
- break;
- case NETWORK_ERROR_KICKED:
- _switch_mode_errorstr = STR_NETWORK_ERR_KICKED;
- break;
- case NETWORK_ERROR_CHEATER:
- _switch_mode_errorstr = STR_NETWORK_ERR_CHEATER;
- break;
- default:
- _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
- }
-
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_SERVER_ERROR;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
-{
- NetworkPasswordType type = NetworkRecv_uint8(MY_CLIENT, p);
-
- switch (type) {
- case NETWORK_GAME_PASSWORD:
- case NETWORK_COMPANY_PASSWORD:
- ShowNetworkNeedPassword(type);
- return NETWORK_RECV_STATUS_OKAY;
-
- default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
- }
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
-{
- _network_own_client_index = NetworkRecv_uint16(MY_CLIENT, p);
-
- // Start receiving the map
- SEND_COMMAND(PACKET_CLIENT_GETMAP)();
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
-{
- _network_join_status = NETWORK_JOIN_STATUS_WAITING;
- _network_join_waiting = NetworkRecv_uint8(MY_CLIENT, p);
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- // We are put on hold for receiving the map.. we need GUI for this ;)
- DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." );
- DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
-{
- static char filename[256];
- static FILE *file_pointer;
-
- byte maptype;
-
- maptype = NetworkRecv_uint8(MY_CLIENT, p);
-
- if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
-
- // First packet, init some stuff
- if (maptype == MAP_PACKET_START) {
- // The name for the temp-map
- snprintf(filename, lengthof(filename), "%s%snetwork_client.tmp", _paths.autosave_dir, PATHSEP);
-
- file_pointer = fopen(filename, "wb");
- if (file_pointer == NULL) {
- _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
- return NETWORK_RECV_STATUS_SAVEGAME;
- }
-
- _frame_counter = _frame_counter_server = _frame_counter_max = NetworkRecv_uint32(MY_CLIENT, p);
-
- _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
- _network_join_kbytes = 0;
- _network_join_kbytes_total = NetworkRecv_uint32(MY_CLIENT, p) / 1024;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- // The first packet does not contain any more data
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- if (maptype == MAP_PACKET_NORMAL) {
- // We are still receiving data, put it to the file
- fwrite(p->buffer + p->pos, 1, p->size - p->pos, file_pointer);
-
- _network_join_kbytes = ftell(file_pointer) / 1024;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
- }
-
- // Check if this was the last packet
- if (maptype == MAP_PACKET_END) {
- fclose(file_pointer);
-
- _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- /* The map is done downloading, load it */
- if (!SafeSaveOrLoad(filename, SL_LOAD, GM_NORMAL)) {
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
- _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
- return NETWORK_RECV_STATUS_SAVEGAME;
- }
- /* If the savegame has successfully loaded, ALL windows have been removed,
- * only toolbar/statusbar and gamefield are visible */
-
- _opt_ptr = &_opt; // during a network game you are always in-game
-
- // Say we received the map and loaded it correctly!
- SEND_COMMAND(PACKET_CLIENT_MAP_OK)();
-
- /* New company/spectator (invalid player) or company we want to join is not active
- * Switch local player to spectator and await the server's judgement */
- if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayer(_network_playas) ||
- !GetPlayer(_network_playas)->is_active) {
-
- SetLocalPlayer(PLAYER_SPECTATOR);
-
- if (_network_playas != PLAYER_SPECTATOR) {
- /* We have arrived and ready to start playing; send a command to make a new player;
- * the server will give us a client-id and let us in */
- _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
- ShowJoinStatusWindow();
- NetworkSend_Command(0, 0, 0, CMD_PLAYER_CTRL, NULL);
- }
- } else {
- // take control over an existing company
- SetLocalPlayer(_network_playas);
- }
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FRAME)
-{
- _frame_counter_server = NetworkRecv_uint32(MY_CLIENT, p);
- _frame_counter_max = NetworkRecv_uint32(MY_CLIENT, p);
-#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
- // Test if the server supports this option
- // and if we are at the frame the server is
- if (p->pos < p->size) {
- _sync_frame = _frame_counter_server;
- _sync_seed_1 = NetworkRecv_uint32(MY_CLIENT, p);
-#ifdef NETWORK_SEND_DOUBLE_SEED
- _sync_seed_2 = NetworkRecv_uint32(MY_CLIENT, p);
-#endif
- }
-#endif
- DEBUG(net, 5, "Received FRAME %d", _frame_counter_server);
-
- // Let the server know that we received this frame correctly
- // We do this only once per day, to save some bandwidth ;)
- if (!_network_first_time && last_ack_frame < _frame_counter) {
- last_ack_frame = _frame_counter + DAY_TICKS;
- DEBUG(net, 4, "Sent ACK at %d", _frame_counter);
- SEND_COMMAND(PACKET_CLIENT_ACK)();
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SYNC)
-{
- _sync_frame = NetworkRecv_uint32(MY_CLIENT, p);
- _sync_seed_1 = NetworkRecv_uint32(MY_CLIENT, p);
-#ifdef NETWORK_SEND_DOUBLE_SEED
- _sync_seed_2 = NetworkRecv_uint32(MY_CLIENT, p);
-#endif
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
-{
- CommandPacket *cp = malloc(sizeof(CommandPacket));
- cp->player = NetworkRecv_uint8(MY_CLIENT, p);
- cp->cmd = NetworkRecv_uint32(MY_CLIENT, p);
- cp->p1 = NetworkRecv_uint32(MY_CLIENT, p);
- cp->p2 = NetworkRecv_uint32(MY_CLIENT, p);
- cp->tile = NetworkRecv_uint32(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, cp->text, sizeof(cp->text));
- cp->callback = NetworkRecv_uint8(MY_CLIENT, p);
- cp->frame = NetworkRecv_uint32(MY_CLIENT, p);
- cp->next = NULL;
-
- // The server did send us this command..
- // queue it in our own queue, so we can handle it in the upcoming frame!
-
- if (_local_command_queue == NULL) {
- _local_command_queue = cp;
- } else {
- // Find last packet
- CommandPacket *c = _local_command_queue;
- while (c->next != NULL) c = c->next;
- c->next = cp;
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
-{
- char name[NETWORK_NAME_LENGTH], msg[MAX_TEXT_MSG_LEN];
- const NetworkClientInfo *ci = NULL, *ci_to;
-
- NetworkAction action = NetworkRecv_uint8(MY_CLIENT, p);
- uint16 index = NetworkRecv_uint16(MY_CLIENT, p);
- bool self_send = NetworkRecv_uint8(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, msg, MAX_TEXT_MSG_LEN);
-
- ci_to = NetworkFindClientInfoFromIndex(index);
- if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY;
-
- /* Did we initiate the action locally? */
- if (self_send) {
- switch (action) {
- case NETWORK_ACTION_CHAT_CLIENT:
- /* For speaking to client we need the client-name */
- snprintf(name, sizeof(name), "%s", ci_to->client_name);
- ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
- break;
-
- /* For speaking to company or giving money, we need the player-name */
- case NETWORK_ACTION_GIVE_MONEY:
- if (!IsValidPlayer(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY;
- /* fallthrough */
- case NETWORK_ACTION_CHAT_COMPANY: {
- StringID str = IsValidPlayer(ci_to->client_playas) ? GetPlayer(ci_to->client_playas)->name_1 : STR_NETWORK_SPECTATORS;
-
- GetString(name, str, lastof(name));
- ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
- } break;
-
- default: NOT_REACHED(); break;
- }
- } else {
- /* Display message from somebody else */
- snprintf(name, sizeof(name), "%s", ci_to->client_name);
- ci = ci_to;
- }
-
- if (ci != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg);
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
-{
- char str[100];
- uint16 index;
- NetworkClientInfo *ci;
-
- index = NetworkRecv_uint16(MY_CLIENT, p);
- GetNetworkErrorMsg(str, NetworkRecv_uint8(MY_CLIENT, p), lastof(str));
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL) {
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
-
- // The client is gone, give the NetworkClientInfo free
- ci->client_index = NETWORK_EMPTY_INDEX;
- }
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
-{
- char str[100];
- uint16 index;
- NetworkClientInfo *ci;
-
- index = NetworkRecv_uint16(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, str, lengthof(str));
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL) {
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
-
- // The client is gone, give the NetworkClientInfo free
- ci->client_index = NETWORK_EMPTY_INDEX;
- } else {
- DEBUG(net, 0, "Unknown client (%d) is leaving the game", index);
- }
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- // If we come here it means we could not locate the client.. strange :s
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
-{
- uint16 index;
- NetworkClientInfo *ci;
-
- index = NetworkRecv_uint16(MY_CLIENT, p);
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL)
- NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, ci->client_name, "");
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN)
-{
- _switch_mode_errorstr = STR_NETWORK_SERVER_SHUTDOWN;
-
- return NETWORK_RECV_STATUS_SERVER_ERROR;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME)
-{
- // To trottle the reconnects a bit, every clients waits
- // his _local_player value before reconnecting
- // PLAYER_SPECTATOR is currently 255, so to avoid long wait periods
- // set the max to 10.
- _network_reconnect = min(_local_player + 1, 10);
- _switch_mode_errorstr = STR_NETWORK_SERVER_REBOOT;
-
- return NETWORK_RECV_STATUS_SERVER_ERROR;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
-{
- char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
- uint16 color_code;
-
- color_code = NetworkRecv_uint16(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, rcon_out, sizeof(rcon_out));
-
- IConsolePrint(color_code, rcon_out);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-
-
-// The layout for the receive-functions by the client
-typedef NetworkRecvStatus NetworkClientPacket(Packet *p);
-
-// This array matches PacketType. At an incoming
-// packet it is matches against this array
-// and that way the right function to handle that
-// packet is found.
-static NetworkClientPacket* const _network_client_packet[] = {
- RECEIVE_COMMAND(PACKET_SERVER_FULL),
- RECEIVE_COMMAND(PACKET_SERVER_BANNED),
- NULL, /*PACKET_CLIENT_JOIN,*/
- RECEIVE_COMMAND(PACKET_SERVER_ERROR),
- NULL, /*PACKET_CLIENT_COMPANY_INFO,*/
- RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO),
- RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO),
- RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD),
- NULL, /*PACKET_CLIENT_PASSWORD,*/
- RECEIVE_COMMAND(PACKET_SERVER_WELCOME),
- NULL, /*PACKET_CLIENT_GETMAP,*/
- RECEIVE_COMMAND(PACKET_SERVER_WAIT),
- RECEIVE_COMMAND(PACKET_SERVER_MAP),
- NULL, /*PACKET_CLIENT_MAP_OK,*/
- RECEIVE_COMMAND(PACKET_SERVER_JOIN),
- RECEIVE_COMMAND(PACKET_SERVER_FRAME),
- RECEIVE_COMMAND(PACKET_SERVER_SYNC),
- NULL, /*PACKET_CLIENT_ACK,*/
- NULL, /*PACKET_CLIENT_COMMAND,*/
- RECEIVE_COMMAND(PACKET_SERVER_COMMAND),
- NULL, /*PACKET_CLIENT_CHAT,*/
- RECEIVE_COMMAND(PACKET_SERVER_CHAT),
- NULL, /*PACKET_CLIENT_SET_PASSWORD,*/
- NULL, /*PACKET_CLIENT_SET_NAME,*/
- NULL, /*PACKET_CLIENT_QUIT,*/
- NULL, /*PACKET_CLIENT_ERROR,*/
- RECEIVE_COMMAND(PACKET_SERVER_QUIT),
- RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT),
- RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN),
- RECEIVE_COMMAND(PACKET_SERVER_NEWGAME),
- RECEIVE_COMMAND(PACKET_SERVER_RCON),
- NULL, /*PACKET_CLIENT_RCON,*/
-};
-
-// If this fails, check the array above with network_data.h
-assert_compile(lengthof(_network_client_packet) == PACKET_END);
-
-// Is called after a client is connected to the server
-void NetworkClient_Connected(void)
-{
- // Set the frame-counter to 0 so nothing happens till we are ready
- _frame_counter = 0;
- _frame_counter_server = 0;
- last_ack_frame = 0;
- // Request the game-info
- SEND_COMMAND(PACKET_CLIENT_JOIN)();
-}
-
-// Reads the packets from the socket-stream, if available
-NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs)
-{
- Packet *p;
- NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY;
-
- while (res == NETWORK_RECV_STATUS_OKAY && (p = NetworkRecv_Packet(cs, &res)) != NULL) {
- byte type = NetworkRecv_uint8(MY_CLIENT, p);
- if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->has_quit) {
- res = _network_client_packet[type](p);
- } else {
- res = NETWORK_RECV_STATUS_MALFORMED_PACKET;
- DEBUG(net, 0, "[client] received invalid packet type %d", type);
- }
-
- free(p);
- }
-
- return res;
-}
-
-#endif /* ENABLE_NETWORK */
--- a/network_client.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CLIENT_H
-#define NETWORK_CLIENT_H
-
-#ifdef ENABLE_NETWORK
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GAME_INFO);
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(CommandPacket *cp);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType desttype, int dest, const char *msg);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name);
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command);
-
-NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs);
-void NetworkClient_Connected(void);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CLIENT_H */
--- a/network_core.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CORE_H
-#define NETWORK_CORE_H
-
-// Network stuff has many things that needs to be included
-// by default. All those things are in this file.
-
-// =============================
-// Include standard stuff per OS
-
-#ifdef ENABLE_NETWORK
-
-#if defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_2)
- // OSX 10.2 don't have socklen_t defined, so we will define it here
- typedef int socklen_t;
-#endif
-
-// Windows stuff
-#if defined(WIN32) || defined(WIN64)
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-
-#if !(defined(__MINGW32__) || defined(__CYGWIN__))
- // Windows has some different names for some types..
- typedef SSIZE_T ssize_t;
- typedef int socklen_t;
-#endif
-
-#define GET_LAST_ERROR() WSAGetLastError()
-#define EWOULDBLOCK WSAEWOULDBLOCK
-// Windows has some different names for some types..
-typedef unsigned long in_addr_t;
-#endif // WIN32
-
-// UNIX stuff
-#if defined(UNIX)
-# define SOCKET int
-# define INVALID_SOCKET -1
-# if !defined(__MORPHOS__) && !defined(__AMIGA__)
-# define ioctlsocket ioctl
-# if !defined(BEOS_NET_SERVER)
-# define closesocket close
-# endif
-# define GET_LAST_ERROR() (errno)
-# endif
-// Need this for FIONREAD on solaris
-# define BSD_COMP
-
-// Includes needed for UNIX-like systems
-# include <unistd.h>
-# include <sys/ioctl.h>
-# if defined(__BEOS__) && defined(BEOS_NET_SERVER)
-# include <be/net/socket.h>
-# include <be/kernel/OS.h> // snooze()
-# include <be/net/netdb.h>
- typedef unsigned long in_addr_t;
-# define INADDR_NONE INADDR_BROADCAST
-# else
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <netinet/tcp.h>
-# include <arpa/inet.h>
-# include <net/if.h>
-// According to glibc/NEWS, <ifaddrs.h> appeared in glibc-2.3.
-# if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__INNOTEK_LIBC__) \
- && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__)
-// If for any reason ifaddrs.h does not exist on your system, comment out
-// the following two lines and an alternative way will be used to fetch
-// the list of IPs from the system.
-# include <ifaddrs.h>
-# define HAVE_GETIFADDRS
-# endif
-# if defined(SUNOS) || defined(__MORPHOS__) || defined(__BEOS__)
-# define INADDR_NONE 0xffffffff
-# endif
-# if defined(__BEOS__) && !defined(BEOS_NET_SERVER)
- // needed on Zeta
-# include <sys/sockio.h>
-# endif
-# endif // BEOS_NET_SERVER
-
-# if !defined(__BEOS__) && defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
- typedef uint32_t in_addr_t;
-# endif
-
-# include <errno.h>
-# include <sys/time.h>
-# include <netdb.h>
-#endif // UNIX
-
-#ifdef __BEOS__
- typedef int socklen_t;
-#endif
-
-// OS/2 stuff
-#if defined(__OS2__)
-# define SOCKET int
-# define INVALID_SOCKET -1
-# define ioctlsocket ioctl
-# define closesocket close
-# define GET_LAST_ERROR() (sock_errno())
-
-// Includes needed for OS/2 systems
-# include <types.h>
-# include <unistd.h>
-# include <sys/ioctl.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <netinet/tcp.h>
-# include <arpa/inet.h>
-# include <net/if.h>
-# include <errno.h>
-# include <sys/time.h>
-# include <netdb.h>
-# include <nerrno.h>
-# define INADDR_NONE 0xffffffff
-
-typedef int socklen_t;
-#if !defined(__INNOTEK_LIBC__)
-typedef unsigned long in_addr_t;
-#endif /* __INNOTEK_LIBC__ */
-#endif // OS/2
-
-// MorphOS and Amiga stuff
-#if defined(__MORPHOS__) || defined(__AMIGA__)
-# include <exec/types.h>
-# include <proto/exec.h> // required for Open/CloseLibrary()
-# if defined(__MORPHOS__)
-# include <sys/filio.h> // FIO* defines
-# include <sys/sockio.h> // SIO* defines
-# include <netinet/in.h>
-# else // __AMIGA__
-# include <proto/socket.h>
-# endif
-
-// Make the names compatible
-# define closesocket(s) CloseSocket(s)
-# define GET_LAST_ERROR() Errno()
-# define ioctlsocket(s,request,status) IoctlSocket((LONG)s,(ULONG)request,(char*)status)
-# define ioctl ioctlsocket
-
- typedef unsigned int in_addr_t;
- typedef long socklen_t;
- extern struct Library *SocketBase;
-
-# ifdef __AMIGA__
- // for usleep() implementation
- extern struct Device *TimerBase;
- extern struct MsgPort *TimerPort;
- extern struct timerequest *TimerRequest;
-# endif
-#endif // __MORPHOS__ || __AMIGA__
-
-static inline bool SetNonBlocking(int d)
-{
- #ifdef WIN32
- u_long nonblocking = 1;
- #else
- int nonblocking = 1;
- #endif
- #if defined(__BEOS__) && defined(BEOS_NET_SERVER)
- return setsockopt(d, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(nonblocking)) == 0;
- #else
- return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
- #endif
-}
-
-static inline bool SetNoDelay(int d)
-{
- // XXX should this be done at all?
- #if !defined(BEOS_NET_SERVER) // not implemented on BeOS net_server
- int b = 1;
- // The (const char*) cast is needed for windows
- return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
- #else
- return true;
- #endif
-}
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CORE_H */
--- a/network_data.c Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,473 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "stdafx.h"
-#include "debug.h"
-#include "network_data.h"
-#include "functions.h"
-#include "string.h"
-#include "table/strings.h"
-#include "network_client.h"
-#include "command.h"
-#include "callback_table.h"
-#include "variables.h"
-
-// This files handles the send/receive of all packets
-
-// Create a packet for sending
-Packet *NetworkSend_Init(PacketType type)
-{
- Packet *packet = malloc(sizeof(Packet));
- // An error is inplace here, because it simply means we ran out of memory.
- if (packet == NULL) error("Failed to allocate Packet");
-
- // Skip the size so we can write that in before sending the packet
- packet->size = sizeof(packet->size);
- packet->buffer[packet->size++] = type;
- packet->pos = 0;
-
- return packet;
-}
-
-// The next couple of functions make sure we can send
-// uint8, uint16, uint32 and uint64 endian-safe
-// over the network. The order it uses is:
-//
-// 1 2 3 4
-//
-
-void NetworkSend_uint8(Packet *packet, uint8 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = data;
-}
-
-void NetworkSend_uint16(Packet *packet, uint16 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = GB(data, 0, 8);
- packet->buffer[packet->size++] = GB(data, 8, 8);
-}
-
-void NetworkSend_uint32(Packet *packet, uint32 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = GB(data, 0, 8);
- packet->buffer[packet->size++] = GB(data, 8, 8);
- packet->buffer[packet->size++] = GB(data, 16, 8);
- packet->buffer[packet->size++] = GB(data, 24, 8);
-}
-
-void NetworkSend_uint64(Packet *packet, uint64 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = GB(data, 0, 8);
- packet->buffer[packet->size++] = GB(data, 8, 8);
- packet->buffer[packet->size++] = GB(data, 16, 8);
- packet->buffer[packet->size++] = GB(data, 24, 8);
- packet->buffer[packet->size++] = GB(data, 32, 8);
- packet->buffer[packet->size++] = GB(data, 40, 8);
- packet->buffer[packet->size++] = GB(data, 48, 8);
- packet->buffer[packet->size++] = GB(data, 56, 8);
-}
-
-// Sends a string over the network. It sends out
-// the string + '\0'. No size-byte or something.
-void NetworkSend_string(Packet *packet, const char* data)
-{
- assert(data != NULL);
- assert(packet->size < sizeof(packet->buffer) - strlen(data) - 1);
- while ((packet->buffer[packet->size++] = *data++) != '\0') {}
-}
-
-// If PacketSize changes of size, you have to change the 2 packet->size
-// lines below matching the size of packet->size/PacketSize!
-// (line 'packet->buffer[0] = packet->size & 0xFF;' and below)
-assert_compile(sizeof(PacketSize) == 2);
-
-// This function puts the packet in the send-queue and it is send
-// as soon as possible
-// (that is: the next tick, or maybe one tick later if the
-// OS-network-buffer is full)
-void NetworkSend_Packet(Packet *packet, NetworkClientState *cs)
-{
- Packet *p;
- assert(packet != NULL);
-
- packet->pos = 0;
- packet->next = NULL;
-
- packet->buffer[0] = GB(packet->size, 0, 8);
- packet->buffer[1] = GB(packet->size, 8, 8);
-
- // Locate last packet buffered for the client
- p = cs->packet_queue;
- if (p == NULL) {
- // No packets yet
- cs->packet_queue = packet;
- } else {
- // Skip to the last packet
- while (p->next != NULL) p = p->next;
- p->next = packet;
- }
-}
-
-// Functions to help NetworkRecv_Packet/NetworkSend_Packet a bit
-// A socket can make errors. When that happens
-// this handles what to do.
-// For clients: close connection and drop back to main-menu
-// For servers: close connection and that is it
-static NetworkRecvStatus CloseConnection(NetworkClientState *cs)
-{
- NetworkCloseClient(cs);
-
- // Clients drop back to the main menu
- if (!_network_server && _networking) {
- _switch_mode = SM_MENU;
- _networking = false;
- _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
-
- return NETWORK_RECV_STATUS_CONN_LOST;
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-// Sends all the buffered packets out for this client
-// it stops when:
-// 1) all packets are send (queue is empty)
-// 2) the OS reports back that it can not send any more
-// data right now (full network-buffer, it happens ;))
-// 3) sending took too long
-bool NetworkSend_Packets(NetworkClientState *cs)
-{
- ssize_t res;
- Packet *p;
-
- // We can not write to this socket!!
- if (!cs->writable) return false;
- if (cs->socket == INVALID_SOCKET) return false;
-
- p = cs->packet_queue;
- while (p != NULL) {
- res = send(cs->socket, p->buffer + p->pos, p->size - p->pos, 0);
- if (res == -1) {
- int err = GET_LAST_ERROR();
- if (err != EWOULDBLOCK) { // Something went wrong.. close client!
- DEBUG(net, 0, "send failed with error %d", err);
- CloseConnection(cs);
- return false;
- }
- return true;
- }
- if (res == 0) {
- // Client/server has left us :(
- CloseConnection(cs);
- return false;
- }
-
- p->pos += res;
-
- // Is this packet sent?
- if (p->pos == p->size) {
- // Go to the next packet
- cs->packet_queue = p->next;
- free(p);
- p = cs->packet_queue;
- } else {
- return true;
- }
- }
-
- return true;
-}
-
-
-// Receiving commands
-// Again, the next couple of functions are endian-safe
-// see the comment around NetworkSend_uint8 for more info.
-uint8 NetworkRecv_uint8(NetworkClientState *cs, Packet *packet)
-{
- /* Don't allow reading from a closed socket */
- if (cs->has_quit) return 0;
-
- /* Check if variable is within packet-size */
- if (packet->pos + 1 > packet->size) {
- CloseConnection(cs);
- return 0;
- }
-
- return packet->buffer[packet->pos++];
-}
-
-uint16 NetworkRecv_uint16(NetworkClientState *cs, Packet *packet)
-{
- uint16 n;
-
- /* Don't allow reading from a closed socket */
- if (cs->has_quit) return 0;
-
- /* Check if variable is within packet-size */
- if (packet->pos + 2 > packet->size) {
- CloseConnection(cs);
- return 0;
- }
-
- n = (uint16)packet->buffer[packet->pos++];
- n += (uint16)packet->buffer[packet->pos++] << 8;
- return n;
-}
-
-uint32 NetworkRecv_uint32(NetworkClientState *cs, Packet *packet)
-{
- uint32 n;
-
- /* Don't allow reading from a closed socket */
- if (cs->has_quit) return 0;
-
- /* Check if variable is within packet-size */
- if (packet->pos + 4 > packet->size) {
- CloseConnection(cs);
- return 0;
- }
-
- n = (uint32)packet->buffer[packet->pos++];
- n += (uint32)packet->buffer[packet->pos++] << 8;
- n += (uint32)packet->buffer[packet->pos++] << 16;
- n += (uint32)packet->buffer[packet->pos++] << 24;
- return n;
-}
-
-uint64 NetworkRecv_uint64(NetworkClientState *cs, Packet *packet)
-{
- uint64 n;
-
- /* Don't allow reading from a closed socket */
- if (cs->has_quit) return 0;
-
- /* Check if variable is within packet-size */
- if (packet->pos + 8 > packet->size) {
- CloseConnection(cs);
- return 0;
- }
-
- n = (uint64)packet->buffer[packet->pos++];
- n += (uint64)packet->buffer[packet->pos++] << 8;
- n += (uint64)packet->buffer[packet->pos++] << 16;
- n += (uint64)packet->buffer[packet->pos++] << 24;
- n += (uint64)packet->buffer[packet->pos++] << 32;
- n += (uint64)packet->buffer[packet->pos++] << 40;
- n += (uint64)packet->buffer[packet->pos++] << 48;
- n += (uint64)packet->buffer[packet->pos++] << 56;
- return n;
-}
-
-// Reads a string till it finds a '\0' in the stream
-void NetworkRecv_string(NetworkClientState *cs, Packet *p, char *buffer, size_t size)
-{
- PacketSize pos;
- char *bufp = buffer;
-
- /* Don't allow reading from a closed socket */
- if (cs->has_quit) return;
-
- pos = p->pos;
- while (--size > 0 && pos < p->size && (*buffer++ = p->buffer[pos++]) != '\0') {}
-
- if (size == 0 || pos == p->size) {
- *buffer = '\0';
- // If size was sooner to zero then the string in the stream
- // skip till the \0, so the packet can be read out correctly for the rest
- while (pos < p->size && p->buffer[pos] != '\0') pos++;
- pos++;
- }
- p->pos = pos;
-
- str_validate(bufp);
-}
-
-// If PacketSize changes of size, you have to change the 2 packet->size
-// lines below matching the size of packet->size/PacketSize!
-// (the line: 'p->size = (uint16)p->buffer[0];' and below)
-assert_compile(sizeof(PacketSize) == 2);
-
-Packet *NetworkRecv_Packet(NetworkClientState *cs, NetworkRecvStatus *status)
-{
- ssize_t res;
- Packet *p;
-
- *status = NETWORK_RECV_STATUS_OKAY;
-
- if (cs->socket == INVALID_SOCKET) return NULL;
-
- if (cs->packet_recv == NULL) {
- cs->packet_recv = malloc(sizeof(Packet));
- if (cs->packet_recv == NULL) error("Failed to allocate packet");
- // Set pos to zero!
- cs->packet_recv->pos = 0;
- cs->packet_recv->size = 0; // Can be ommited, just for safety reasons
- }
-
- p = cs->packet_recv;
-
- // Read packet size
- if (p->pos < sizeof(PacketSize)) {
- while (p->pos < sizeof(PacketSize)) {
- // Read the size of the packet
- res = recv(cs->socket, p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0);
- if (res == -1) {
- int err = GET_LAST_ERROR();
- if (err != EWOULDBLOCK) {
- /* Something went wrong... (104 is connection reset by peer) */
- if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
- *status = CloseConnection(cs);
- return NULL;
- }
- // Connection would block, so stop for now
- return NULL;
- }
- if (res == 0) {
- // Client/server has left
- *status = CloseConnection(cs);
- return NULL;
- }
- p->pos += res;
- }
-
- p->size = (uint16)p->buffer[0];
- p->size += (uint16)p->buffer[1] << 8;
-
- if (p->size > SEND_MTU) {
- *status = CloseConnection(cs);
- return NULL;
- }
- }
-
- // Read rest of packet
- while (p->pos < p->size) {
- res = recv(cs->socket, p->buffer + p->pos, p->size - p->pos, 0);
- if (res == -1) {
- int err = GET_LAST_ERROR();
- if (err != EWOULDBLOCK) {
- /* Something went wrong... (104 is connection reset by peer) */
- if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
- *status = CloseConnection(cs);
- return NULL;
- }
- // Connection would block
- return NULL;
- }
- if (res == 0) {
- // Client/server has left
- *status = CloseConnection(cs);
- return NULL;
- }
-
- p->pos += res;
- }
-
- // We have a complete packet, return it!
- p->pos = 2;
- p->next = NULL; // Should not be needed, but who knows...
-
- // Prepare for receiving a new packet
- cs->packet_recv = NULL;
-
- return p;
-}
-
-// Add a command to the local command queue
-void NetworkAddCommandQueue(NetworkClientState *cs, CommandPacket *cp)
-{
- CommandPacket* new_cp = malloc(sizeof(*new_cp));
-
- *new_cp = *cp;
-
- if (cs->command_queue == NULL) {
- cs->command_queue = new_cp;
- } else {
- CommandPacket *c = cs->command_queue;
- while (c->next != NULL) c = c->next;
- c->next = new_cp;
- }
-}
-
-// Prepare a DoCommand to be send over the network
-void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback)
-{
- CommandPacket *c = malloc(sizeof(CommandPacket));
- byte temp_callback;
-
- c->player = _local_player;
- c->next = NULL;
- c->tile = tile;
- c->p1 = p1;
- c->p2 = p2;
- c->cmd = cmd;
- c->callback = 0;
-
- temp_callback = 0;
-
- while (temp_callback < _callback_table_count && _callback_table[temp_callback] != callback)
- temp_callback++;
- if (temp_callback == _callback_table_count) {
- DEBUG(net, 0, "Unknown callback. (Pointer: %p) No callback sent", callback);
- temp_callback = 0; /* _callback_table[0] == NULL */
- }
-
- if (_network_server) {
- // We are the server, so set the command to be executed next possible frame
- c->frame = _frame_counter_max + 1;
- } else {
- c->frame = 0; // The client can't tell which frame, so just make it 0
- }
-
- ttd_strlcpy(c->text, (_cmd_text != NULL) ? _cmd_text : "", lengthof(c->text));
-
- if (_network_server) {
- // If we are the server, we queue the command in our 'special' queue.
- // In theory, we could execute the command right away, but then the
- // client on the server can do everything 1 tick faster than others.
- // So to keep the game fair, we delay the command with 1 tick
- // which gives about the same speed as most clients.
- NetworkClientState *cs;
-
- // And we queue it for delivery to the clients
- FOR_ALL_CLIENTS(cs) {
- if (cs->status > STATUS_AUTH) NetworkAddCommandQueue(cs, c);
- }
-
- // Only the server gets the callback, because clients should not get them
- c->callback = temp_callback;
- if (_local_command_queue == NULL) {
- _local_command_queue = c;
- } else {
- // Find last packet
- CommandPacket *cp = _local_command_queue;
- while (cp->next != NULL) cp = cp->next;
- cp->next = c;
- }
-
- return;
- }
-
- // Clients send their command to the server and forget all about the packet
- c->callback = temp_callback;
- SEND_COMMAND(PACKET_CLIENT_COMMAND)(c);
-}
-
-// Execute a DoCommand we received from the network
-void NetworkExecuteCommand(CommandPacket *cp)
-{
- _current_player = cp->player;
- _cmd_text = cp->text;
- /* cp->callback is unsigned. so we don't need to do lower bounds checking. */
- if (cp->callback > _callback_table_count) {
- DEBUG(net, 0, "Received out-of-bounds callback (%d)", cp->callback);
- cp->callback = 0;
- }
- DoCommandP(cp->tile, cp->p1, cp->p2, _callback_table[cp->callback], cp->cmd | CMD_NETWORK_COMMAND);
-}
-
-#endif /* ENABLE_NETWORK */
--- a/network_data.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_DATA_H
-#define NETWORK_DATA_H
-
-#include "openttd.h"
-#include "network.h"
-#include "network_core.h"
-
-// Is the network enabled?
-#ifdef ENABLE_NETWORK
-
-#define SEND_MTU 1460
-#define MAX_TEXT_MSG_LEN 1024 /* long long long long sentences :-) */
-
-// The client-info-server-index is always 1
-#define NETWORK_SERVER_INDEX 1
-#define NETWORK_EMPTY_INDEX 0
-
-// What version of game-info do we use?
-#define NETWORK_GAME_INFO_VERSION 4
-// What version of company info is this?
-#define NETWORK_COMPANY_INFO_VERSION 4
-// What version of master-server-protocol do we use?
-#define NETWORK_MASTER_SERVER_VERSION 1
-
-typedef uint16 PacketSize;
-
-typedef struct Packet {
- struct Packet *next;
- PacketSize size;
- PacketSize pos;
- byte buffer[SEND_MTU];
-} Packet;
-
-typedef struct CommandPacket {
- struct CommandPacket *next;
- PlayerID player; /// player that is executing the command
- uint32 cmd; /// command being executed
- uint32 p1; /// parameter p1
- uint32 p2; /// parameter p2
- TileIndex tile; /// tile command being executed on
- char text[80];
- uint32 frame; /// the frame in which this packet is executed
- byte callback; /// any callback function executed upon successful completion of the command
-} CommandPacket;
-
-typedef enum {
- STATUS_INACTIVE,
- STATUS_AUTH, // This means that the client is authorized
- STATUS_MAP_WAIT, // This means that the client is put on hold because someone else is getting the map
- STATUS_MAP,
- STATUS_DONE_MAP,
- STATUS_PRE_ACTIVE,
- STATUS_ACTIVE,
-} ClientStatus;
-
-typedef enum {
- MAP_PACKET_START,
- MAP_PACKET_NORMAL,
- MAP_PACKET_END,
-} MapPacket;
-
-typedef enum {
- NETWORK_RECV_STATUS_OKAY,
- NETWORK_RECV_STATUS_DESYNC,
- NETWORK_RECV_STATUS_SAVEGAME,
- NETWORK_RECV_STATUS_CONN_LOST,
- NETWORK_RECV_STATUS_MALFORMED_PACKET,
- NETWORK_RECV_STATUS_SERVER_ERROR, // The server told us we made an error
- NETWORK_RECV_STATUS_SERVER_FULL,
- NETWORK_RECV_STATUS_SERVER_BANNED,
- NETWORK_RECV_STATUS_CLOSE_QUERY, // Done quering the server
-} NetworkRecvStatus;
-
-typedef enum {
- NETWORK_ERROR_GENERAL, // Try to use thisone like never
-
- // Signals from clients
- NETWORK_ERROR_DESYNC,
- NETWORK_ERROR_SAVEGAME_FAILED,
- NETWORK_ERROR_CONNECTION_LOST,
- NETWORK_ERROR_ILLEGAL_PACKET,
-
- // Signals from servers
- NETWORK_ERROR_NOT_AUTHORIZED,
- NETWORK_ERROR_NOT_EXPECTED,
- NETWORK_ERROR_WRONG_REVISION,
- NETWORK_ERROR_NAME_IN_USE,
- NETWORK_ERROR_WRONG_PASSWORD,
- NETWORK_ERROR_PLAYER_MISMATCH, // Happens in CLIENT_COMMAND
- NETWORK_ERROR_KICKED,
- NETWORK_ERROR_CHEATER,
- NETWORK_ERROR_FULL,
-} NetworkErrorCode;
-
-// Actions that can be used for NetworkTextMessage
-typedef enum {
- NETWORK_ACTION_JOIN,
- NETWORK_ACTION_LEAVE,
- NETWORK_ACTION_SERVER_MESSAGE,
- NETWORK_ACTION_CHAT,
- NETWORK_ACTION_CHAT_COMPANY,
- NETWORK_ACTION_CHAT_CLIENT,
- NETWORK_ACTION_GIVE_MONEY,
- NETWORK_ACTION_NAME_CHANGE,
-} NetworkAction;
-
-typedef enum {
- NETWORK_GAME_PASSWORD,
- NETWORK_COMPANY_PASSWORD,
-} NetworkPasswordType;
-
-// To keep the clients all together
-typedef struct NetworkClientState {
- SOCKET socket;
- uint16 index;
- uint32 last_frame;
- uint32 last_frame_server;
- byte lag_test; // This byte is used for lag-testing the client
-
- ClientStatus status;
- bool writable; // is client ready to write to?
- bool has_quit;
-
- Packet *packet_queue; // Packets that are awaiting delivery
- Packet *packet_recv; // Partially received packet
-
- CommandPacket *command_queue; // The command-queue awaiting delivery
-} NetworkClientState;
-
-// What packet types are there
-// WARNING: The first 3 packets can NEVER change order again
-// it protects old clients from joining newer servers (because SERVER_ERROR
-// is the respond to a wrong revision)
-typedef enum {
- PACKET_SERVER_FULL,
- PACKET_SERVER_BANNED,
- PACKET_CLIENT_JOIN,
- PACKET_SERVER_ERROR,
- PACKET_CLIENT_COMPANY_INFO,
- PACKET_SERVER_COMPANY_INFO,
- PACKET_SERVER_CLIENT_INFO,
- PACKET_SERVER_NEED_PASSWORD,
- PACKET_CLIENT_PASSWORD,
- PACKET_SERVER_WELCOME,
- PACKET_CLIENT_GETMAP,
- PACKET_SERVER_WAIT,
- PACKET_SERVER_MAP,
- PACKET_CLIENT_MAP_OK,
- PACKET_SERVER_JOIN,
- PACKET_SERVER_FRAME,
- PACKET_SERVER_SYNC,
- PACKET_CLIENT_ACK,
- PACKET_CLIENT_COMMAND,
- PACKET_SERVER_COMMAND,
- PACKET_CLIENT_CHAT,
- PACKET_SERVER_CHAT,
- PACKET_CLIENT_SET_PASSWORD,
- PACKET_CLIENT_SET_NAME,
- PACKET_CLIENT_QUIT,
- PACKET_CLIENT_ERROR,
- PACKET_SERVER_QUIT,
- PACKET_SERVER_ERROR_QUIT,
- PACKET_SERVER_SHUTDOWN,
- PACKET_SERVER_NEWGAME,
- PACKET_SERVER_RCON,
- PACKET_CLIENT_RCON,
- PACKET_END // Should ALWAYS be on the end of this list!! (period)
-} PacketType;
-
-typedef enum {
- DESTTYPE_BROADCAST, ///< Send message/notice to all players (All)
- DESTTYPE_TEAM, ///< Send message/notice to everyone playing the same company (Team)
- DESTTYPE_CLIENT, ///< Send message/notice to only a certain player (Private)
-} DestType;
-
-CommandPacket *_local_command_queue;
-
-SOCKET _udp_client_socket; // udp client socket
-SOCKET _udp_server_socket; // udp server socket
-SOCKET _udp_master_socket; // udp master socket
-
-// Here we keep track of the clients
-// (and the client uses [0] for his own communication)
-NetworkClientState _clients[MAX_CLIENTS];
-#define DEREF_CLIENT(i) (&_clients[i])
-// This returns the NetworkClientInfo from a NetworkClientState
-#define DEREF_CLIENT_INFO(cs) (&_network_client_info[cs - _clients])
-
-// Macros to make life a bit more easier
-#define DEF_CLIENT_RECEIVE_COMMAND(type) NetworkRecvStatus NetworkPacketReceive_ ## type ## _command(Packet *p)
-#define DEF_CLIENT_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(void)
-#define DEF_CLIENT_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
-#define DEF_SERVER_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(NetworkClientState *cs, Packet *p)
-#define DEF_SERVER_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(NetworkClientState *cs)
-#define DEF_SERVER_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
-
-#define SEND_COMMAND(type) NetworkPacketSend_ ## type ## _command
-#define RECEIVE_COMMAND(type) NetworkPacketReceive_ ## type ## _command
-
-#define FOR_ALL_CLIENTS(cs) for (cs = _clients; cs != endof(_clients) && cs->socket != INVALID_SOCKET; cs++)
-#define FOR_ALL_ACTIVE_CLIENT_INFOS(ci) for (ci = _network_client_info; ci != endof(_network_client_info); ci++) if (ci->client_index != NETWORK_EMPTY_INDEX)
-
-Packet *NetworkSend_Init(PacketType type);
-void NetworkSend_uint8(Packet *packet, uint8 data);
-void NetworkSend_uint16(Packet *packet, uint16 data);
-void NetworkSend_uint32(Packet *packet, uint32 data);
-void NetworkSend_uint64(Packet *packet, uint64 data);
-void NetworkSend_string(Packet *packet, const char* data);
-void NetworkSend_Packet(Packet *packet, NetworkClientState *cs);
-
-uint8 NetworkRecv_uint8(NetworkClientState *cs, Packet *packet);
-uint16 NetworkRecv_uint16(NetworkClientState *cs, Packet *packet);
-uint32 NetworkRecv_uint32(NetworkClientState *cs, Packet *packet);
-uint64 NetworkRecv_uint64(NetworkClientState *cs, Packet *packet);
-void NetworkRecv_string(NetworkClientState *cs, Packet *packet, char* buffer, size_t size);
-Packet *NetworkRecv_Packet(NetworkClientState *cs, NetworkRecvStatus *status);
-
-bool NetworkSend_Packets(NetworkClientState *cs);
-void NetworkExecuteCommand(CommandPacket *cp);
-void NetworkAddCommandQueue(NetworkClientState *cs, CommandPacket *cp);
-
-// from network.c
-void NetworkCloseClient(NetworkClientState *cs);
-void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...);
-void NetworkGetClientName(char *clientname, size_t size, const NetworkClientState *cs);
-uint NetworkCalculateLag(const NetworkClientState *cs);
-byte NetworkGetCurrentLanguageIndex(void);
-NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
-NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
-NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index);
-unsigned long NetworkResolveHost(const char *hostname);
-char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_DATA_H */
--- a/network_gamelist.c Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "stdafx.h"
-#include "debug.h"
-#include "network_data.h"
-#include "newgrf_config.h"
-
-// This file handles the GameList
-// Also, it handles the request to a server for data about the server
-
-/** Add a new item to the linked gamelist. If the IP and Port match
- * return the existing item instead of adding it again
- * @param ip the IP-address (inet_addr) of the to-be added item
- * @param port the port the server is running on
- * @return a point to the newly added or already existing item */
-NetworkGameList *NetworkGameListAddItem(uint32 ip, uint16 port)
-{
- NetworkGameList *item, *prev_item;
-
- prev_item = NULL;
- for (item = _network_game_list; item != NULL; item = item->next) {
- if (item->ip == ip && item->port == port) return item;
- prev_item = item;
- }
-
- item = malloc(sizeof(*item));
- memset(item, 0, sizeof(*item));
- item->next = NULL;
- item->ip = ip;
- item->port = port;
-
- if (prev_item == NULL) {
- _network_game_list = item;
- } else {
- prev_item->next = item;
- }
- DEBUG(net, 4, "[gamelist] added server to list");
-
- UpdateNetworkGameWindow(false);
-
- return item;
-}
-
-/** Remove an item from the gamelist linked list
- * @param remove pointer to the item to be removed */
-void NetworkGameListRemoveItem(NetworkGameList *remove)
-{
- NetworkGameList *item, *prev_item;
-
- prev_item = NULL;
- for (item = _network_game_list; item != NULL; item = item->next) {
- if (remove == item) {
- if (prev_item == NULL) {
- _network_game_list = remove->next;
- } else {
- prev_item->next = remove->next;
- }
-
- /* Remove GRFConfig information */
- ClearGRFConfigList(&remove->info.grfconfig);
- free(remove);
- remove = NULL;
-
- DEBUG(net, 4, "[gamelist] removed server from list");
- UpdateNetworkGameWindow(false);
- return;
- }
- prev_item = item;
- }
-}
-
-#endif /* ENABLE_NETWORK */
--- a/network_gamelist.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_GAMELIST_H
-#define NETWORK_GAMELIST_H
-
-void NetworkGameListClear(void);
-NetworkGameList *NetworkGameListAddItem(uint32 ip, uint16 port);
-void NetworkGameListRemoveItem(NetworkGameList *remove);
-void NetworkGameListAddQueriedItem(const NetworkGameInfo *info, bool server_online);
-
-#endif /* NETWORK_GAMELIST_H */
--- a/network_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1706 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-#include "stdafx.h"
-#include "openttd.h"
-#include "string.h"
-#include "strings.h"
-#include "table/sprites.h"
-#include "network.h"
-#include "date.h"
-
-#include "fios.h"
-#include "table/strings.h"
-#include "functions.h"
-#include "network_data.h"
-#include "network_client.h"
-#include "network_gui.h"
-#include "network_gamelist.h"
-#include "window.h"
-#include "gui.h"
-#include "gfx.h"
-#include "command.h"
-#include "variables.h"
-#include "network_server.h"
-#include "network_udp.h"
-#include "settings.h"
-#include "string.h"
-#include "town.h"
-#include "newgrf.h"
-
-#define BGC 5
-#define BTC 15
-
-typedef struct network_d {
- PlayerID company; // select company in network lobby
- byte field; // select text-field in start-server and game-listing
- NetworkGameList *server; // selected server in lobby and game-listing
- FiosItem *map; // selected map in start-server
-} network_d;
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_d));
-
-typedef struct network_ql_d {
- network_d n; // see above; general stuff
- querystr_d q; // text-input in start-server and game-listing
- NetworkGameList **sort_list; // list of games (sorted)
- list_d l; // accompanying list-administration
-} network_ql_d;
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_ql_d));
-
-/* Global to remember sorting after window has been closed */
-static Listing _ng_sorting;
-
-static char _edit_str_buf[150];
-static bool _chat_tab_completion_active;
-
-static void ShowNetworkStartServerWindow(void);
-static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
-extern void SwitchMode(int new_mode);
-
-static const StringID _connection_types_dropdown[] = {
- STR_NETWORK_LAN_INTERNET,
- STR_NETWORK_INTERNET_ADVERTISE,
- INVALID_STRING_ID
-};
-
-static const StringID _lan_internet_types_dropdown[] = {
- STR_NETWORK_LAN,
- STR_NETWORK_INTERNET,
- INVALID_STRING_ID
-};
-
-static const StringID _players_dropdown[] = {
- STR_NETWORK_0_PLAYERS,
- STR_NETWORK_1_PLAYERS,
- STR_NETWORK_2_PLAYERS,
- STR_NETWORK_3_PLAYERS,
- STR_NETWORK_4_PLAYERS,
- STR_NETWORK_5_PLAYERS,
- STR_NETWORK_6_PLAYERS,
- STR_NETWORK_7_PLAYERS,
- STR_NETWORK_8_PLAYERS,
- STR_NETWORK_9_PLAYERS,
- STR_NETWORK_10_PLAYERS,
- INVALID_STRING_ID
-};
-
-static const StringID _language_dropdown[] = {
- STR_NETWORK_LANG_ANY,
- STR_NETWORK_LANG_ENGLISH,
- STR_NETWORK_LANG_GERMAN,
- STR_NETWORK_LANG_FRENCH,
- INVALID_STRING_ID
-};
-
-enum {
- NET_PRC__OFFSET_TOP_WIDGET = 54,
- NET_PRC__OFFSET_TOP_WIDGET_COMPANY = 52,
- NET_PRC__SIZE_OF_ROW = 14,
-};
-
-/** Update the network new window because a new server is
- * found on the network.
- * @param unselect unselect the currently selected item */
-void UpdateNetworkGameWindow(bool unselect)
-{
- SendWindowMessage(WC_NETWORK_WINDOW, 0, unselect, 0, 0);
-}
-
-static bool _internal_sort_order; // Used for Qsort order-flipping
-typedef int CDECL NGameNameSortFunction(const void*, const void*);
-
-/** Qsort function to sort by name. */
-static int CDECL NGameNameSorter(const void *a, const void *b)
-{
- const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
- const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
- int r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
- return _internal_sort_order ? -r : r;
-}
-
-/** Qsort function to sort by the amount of clients online on a
- * server. If the two servers have the same amount, the one with the
- * higher maximum is preferred. */
-static int CDECL NGameClientSorter(const void *a, const void *b)
-{
- const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
- const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
- /* Reverse as per default we are interested in most-clients first */
- int r = cmp1->info.clients_on - cmp2->info.clients_on;
-
- if (r == 0) r = cmp1->info.clients_max - cmp2->info.clients_max;
- if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
- return _internal_sort_order ? -r : r;
-}
-
-/** Qsort function to sort by joinability. If both servers are the
- * same, prefer the non-passworded server first. */
-static int CDECL NGameAllowedSorter(const void *a, const void *b)
-{
- const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
- const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
- /* Reverse default as we are interested in compatible clients first */
- int r = cmp2->info.compatible - cmp1->info.compatible;
-
- if (r == 0) r = cmp1->info.use_password - cmp2->info.use_password;
- if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
- return _internal_sort_order ? -r : r;
-}
-
-/** (Re)build the network game list as its amount has changed because
- * an item has been added or deleted for example
- * @param ngl list_d struct that contains all necessary information for sorting */
-static void BuildNetworkGameList(network_ql_d *nqld)
-{
- NetworkGameList *ngl_temp;
- uint n = 0;
-
- if (!(nqld->l.flags & VL_REBUILD)) return;
-
- /* Count the number of games in the list */
- for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
- if (n == 0) return;
-
- /* Create temporary array of games to use for listing */
- free(nqld->sort_list);
- nqld->sort_list = malloc(n * sizeof(nqld->sort_list[0]));
- if (nqld->sort_list == NULL) error("Could not allocate memory for the network-game-sorting-list");
- nqld->l.list_length = n;
-
- for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
- nqld->sort_list[n++] = ngl_temp;
- }
-
- /* Force resort */
- nqld->l.flags &= ~VL_REBUILD;
- nqld->l.flags |= VL_RESORT;
-}
-
-static void SortNetworkGameList(network_ql_d *nqld)
-{
- static NGameNameSortFunction * const ngame_sorter[] = {
- &NGameNameSorter,
- &NGameClientSorter,
- &NGameAllowedSorter
- };
-
- NetworkGameList *item;
- uint i;
-
- if (!(nqld->l.flags & VL_RESORT)) return;
- if (nqld->l.list_length == 0) return;
-
- _internal_sort_order = !!(nqld->l.flags & VL_DESC);
- qsort(nqld->sort_list, nqld->l.list_length, sizeof(nqld->sort_list[0]), ngame_sorter[nqld->l.sort_type]);
-
- /* After sorting ngl->sort_list contains the sorted items. Put these back
- * into the original list. Basically nothing has changed, we are only
- * shuffling the ->next pointers */
- _network_game_list = nqld->sort_list[0];
- for (item = _network_game_list, i = 1; i != nqld->l.list_length; i++) {
- item->next = nqld->sort_list[i];
- item = item->next;
- }
- item->next = NULL;
-
- nqld->l.flags &= ~VL_RESORT;
-}
-
-/* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
-static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
- list_d *ld = &WP(w, network_ql_d).l;
-
- switch (e->event) {
- case WE_CREATE: /* Focus input box */
- nd->field = 3;
- nd->server = NULL;
-
- WP(w, network_ql_d).sort_list = NULL;
- ld->flags = VL_REBUILD | (_ng_sorting.order << (VL_DESC - 1));
- ld->sort_type = _ng_sorting.criteria;
- break;
-
- case WE_PAINT: {
- const NetworkGameList *sel = nd->server;
- const char *arrow = (ld->flags & VL_DESC) ? DOWNARROW : UPARROW;
-
- if (ld->flags & VL_REBUILD) {
- BuildNetworkGameList(&WP(w, network_ql_d));
- SetVScrollCount(w, ld->list_length);
- }
- if (ld->flags & VL_RESORT) SortNetworkGameList(&WP(w, network_ql_d));
-
- SetWindowWidgetDisabledState(w, 17, sel == NULL);
- /* Join Button disabling conditions */
- SetWindowWidgetDisabledState(w, 16, sel == NULL || // no Selected Server
- !sel->online || // Server offline
- sel->info.clients_on >= sel->info.clients_max || // Server full
- !sel->info.compatible); // Revision mismatch
-
- SetWindowWidgetHiddenState(w, 18, sel == NULL ||
- !sel->online ||
- sel->info.grfconfig == NULL);
-
- SetDParam(0, 0x00);
- SetDParam(7, _lan_internet_types_dropdown[_network_lan_internet]);
- DrawWindowWidgets(w);
-
- DrawEditBox(w, &WP(w, network_ql_d).q, 3);
-
- DrawString(9, 23, STR_NETWORK_CONNECTION, 2);
- DrawString(210, 23, STR_NETWORK_PLAYER_NAME, 2);
-
- /* Sort based on widgets: name, clients, compatibility */
- switch (ld->sort_type) {
- case 6 - 6: DoDrawString(arrow, w->widget[6].right - 10, 42, 0x10); break;
- case 7 - 6: DoDrawString(arrow, w->widget[7].right - 10, 42, 0x10); break;
- case 8 - 6: DoDrawString(arrow, w->widget[8].right - 10, 42, 0x10); break;
- }
-
- { // draw list of games
- uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
- int32 n = 0;
- int32 pos = w->vscroll.pos;
- uint max_name_width = w->widget[6].right - w->widget[6].left - 5;
- const NetworkGameList *cur_item = _network_game_list;
-
- while (pos > 0 && cur_item != NULL) {
- pos--;
- cur_item = cur_item->next;
- }
-
- while (cur_item != NULL) {
- // show highlighted item with a different colour
- if (cur_item == sel) GfxFillRect(w->widget[6].left + 1, y - 2, w->widget[8].right - 1, y + 9, 10);
-
- SetDParamStr(0, cur_item->info.server_name);
- DrawStringTruncated(w->widget[6].left + 5, y, STR_02BD, 16, max_name_width);
-
- SetDParam(0, cur_item->info.clients_on);
- SetDParam(1, cur_item->info.clients_max);
- SetDParam(2, cur_item->info.companies_on);
- SetDParam(3, cur_item->info.companies_max);
- DrawStringCentered(210, y, STR_NETWORK_GENERAL_ONLINE, 2);
-
- // only draw icons if the server is online
- if (cur_item->online) {
- // draw a lock if the server is password protected.
- if (cur_item->info.use_password) DrawSprite(SPR_LOCK, w->widget[8].left + 5, y - 1);
-
- // draw red or green icon, depending on compatibility with server.
- DrawSprite(SPR_BLOT | (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), w->widget[8].left + 15, y);
-
- // draw flag according to server language
- DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, w->widget[8].left + 25, y);
- }
-
- cur_item = cur_item->next;
- y += NET_PRC__SIZE_OF_ROW;
- if (++n == w->vscroll.cap) break; // max number of games in the window
- }
- }
-
- /* Draw the right menu */
- GfxFillRect(311, 43, 539, 92, 157);
- if (sel == NULL) {
- DrawStringCentered(425, 58, STR_NETWORK_GAME_INFO, 0);
- } else if (!sel->online) {
- SetDParamStr(0, sel->info.server_name);
- DrawStringCentered(425, 68, STR_ORANGE, 0); // game name
-
- DrawStringCentered(425, 132, STR_NETWORK_SERVER_OFFLINE, 0); // server offline
- } else { // show game info
- uint16 y = 100;
- const uint16 x = w->widget[15].left + 5;
-
- DrawStringCentered(425, 48, STR_NETWORK_GAME_INFO, 0);
-
-
- SetDParamStr(0, sel->info.server_name);
- DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 62, STR_ORANGE, 16); // game name
-
- SetDParamStr(0, sel->info.map_name);
- DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 74, STR_02BD, 16); // map name
-
- SetDParam(0, sel->info.clients_on);
- SetDParam(1, sel->info.clients_max);
- SetDParam(2, sel->info.companies_on);
- SetDParam(3, sel->info.companies_max);
- DrawString(x, y, STR_NETWORK_CLIENTS, 2);
- y += 10;
-
- SetDParam(0, _language_dropdown[sel->info.server_lang]);
- DrawString(x, y, STR_NETWORK_LANGUAGE, 2); // server language
- y += 10;
-
- SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
- DrawString(x, y, STR_NETWORK_TILESET, 2); // tileset
- y += 10;
-
- SetDParam(0, sel->info.map_width);
- SetDParam(1, sel->info.map_height);
- DrawString(x, y, STR_NETWORK_MAP_SIZE, 2); // map size
- y += 10;
-
- SetDParamStr(0, sel->info.server_revision);
- DrawString(x, y, STR_NETWORK_SERVER_VERSION, 2); // server version
- y += 10;
-
- SetDParamStr(0, sel->info.hostname);
- SetDParam(1, sel->port);
- DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, 2); // server address
- y += 10;
-
- SetDParam(0, sel->info.start_date);
- DrawString(x, y, STR_NETWORK_START_DATE, 2); // start date
- y += 10;
-
- SetDParam(0, sel->info.game_date);
- DrawString(x, y, STR_NETWORK_CURRENT_DATE, 2); // current date
- y += 10;
-
- y += 2;
-
- if (!sel->info.compatible) {
- DrawStringCentered(425, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, 0); // server mismatch
- } else if (sel->info.clients_on == sel->info.clients_max) {
- // Show: server full, when clients_on == clients_max
- DrawStringCentered(425, y, STR_NETWORK_SERVER_FULL, 0); // server full
- } else if (sel->info.use_password) {
- DrawStringCentered(425, y, STR_NETWORK_PASSWORD, 0); // password warning
- }
-
- y += 10;
- }
- } break;
-
- case WE_CLICK:
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case 0: case 14: /* Close 'X' | Cancel button */
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
- break;
- case 4: case 5:
- ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0, 0); // do it for widget 5
- break;
- case 6: /* Sort by name */
- case 7: /* Sort by connected clients */
- case 8: /* Connectivity (green dot) */
- if (ld->sort_type == e->we.click.widget - 6) ld->flags ^= VL_DESC;
- ld->flags |= VL_RESORT;
- ld->sort_type = e->we.click.widget - 6;
-
- _ng_sorting.order = !!(ld->flags & VL_DESC);
- _ng_sorting.criteria = ld->sort_type;
- SetWindowDirty(w);
- break;
- case 9: { /* Matrix to show networkgames */
- NetworkGameList *cur_item;
- uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
-
- if (id_v >= w->vscroll.cap) return; // click out of bounds
- id_v += w->vscroll.pos;
-
- cur_item = _network_game_list;
- for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
-
- nd->server = cur_item;
- SetWindowDirty(w);
- } break;
- case 11: /* Find server automatically */
- switch (_network_lan_internet) {
- case 0: NetworkUDPSearchGame(); break;
- case 1: NetworkUDPQueryMasterServer(); break;
- }
- break;
- case 12: { // Add a server
- ShowQueryString(
- BindCString(_network_default_ip),
- STR_NETWORK_ENTER_IP,
- 31 | 0x1000, // maximum number of characters OR
- 250, // characters up to this width pixels, whichever is satisfied first
- w, CS_ALPHANUMERAL);
- } break;
- case 13: /* Start server */
- ShowNetworkStartServerWindow();
- break;
- case 16: /* Join Game */
- if (nd->server != NULL) {
- snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&nd->server->ip));
- _network_last_port = nd->server->port;
- ShowNetworkLobbyWindow(nd->server);
- }
- break;
- case 17: // Refresh
- if (nd->server != NULL)
- NetworkQueryServer(nd->server->info.hostname, nd->server->port, true);
- break;
- case 18: // NewGRF Settings
- if (nd->server != NULL) ShowNewGRFSettings(false, false, false, &nd->server->info.grfconfig);
- break;
-
- } break;
-
- case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- switch (e->we.dropdown.button) {
- case 5:
- _network_lan_internet = e->we.dropdown.index;
- break;
- }
-
- SetWindowDirty(w);
- break;
-
- case WE_MOUSELOOP:
- if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
- break;
-
- case WE_MESSAGE:
- if (e->we.message.msg != 0) nd->server = NULL;
- ld->flags |= VL_REBUILD;
- SetWindowDirty(w);
- break;
-
- case WE_KEYPRESS:
- if (nd->field != 3) {
- if (nd->server != NULL) {
- if (e->we.keypress.keycode == WKC_DELETE) { /* Press 'delete' to remove servers */
- NetworkGameListRemoveItem(nd->server);
- NetworkRebuildHostList();
- nd->server = NULL;
- }
- }
- break;
- }
-
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
-
- // The name is only allowed when it starts with a letter!
- if (_edit_str_buf[0] != '\0' && _edit_str_buf[0] != ' ') {
- ttd_strlcpy(_network_player_name, _edit_str_buf, lengthof(_network_player_name));
- } else {
- ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
- }
-
- break;
-
- case WE_ON_EDIT_TEXT:
- NetworkAddServer(e->we.edittext.str);
- NetworkRebuildHostList();
- break;
-
- case WE_DESTROY: /* Nicely clean up the sort-list */
- free(WP(w, network_ql_d).sort_list);
- break;
- }
-}
-
-static const Widget _network_game_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 549, 0, 13, STR_NETWORK_MULTIPLAYER, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, BGC, 0, 549, 14, 263, 0x0, STR_NULL},
-
-/* LEFT SIDE */
-{ WWT_PANEL, RESIZE_NONE, BGC, 310, 461, 22, 33, 0x0, STR_NETWORK_ENTER_NAME_TIP},
-
-{ WWT_INSET, RESIZE_NONE, BGC, 90, 181, 22, 33, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 170, 180, 23, 32, STR_0225, STR_NETWORK_CONNECTION_TIP},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 170, 42, 53, STR_NETWORK_GAME_NAME, STR_NETWORK_GAME_NAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 171, 250, 42, 53, STR_NETWORK_CLIENTS_CAPTION, STR_NETWORK_CLIENTS_CAPTION_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 251, 290, 42, 53, STR_EMPTY, STR_NETWORK_INFO_ICONS_TIP},
-
-{ WWT_MATRIX, RESIZE_NONE, BGC, 10, 290, 54, 236, (13 << 8) + 1, STR_NETWORK_CLICK_GAME_TO_SELECT},
-{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 291, 302, 42, 236, STR_NULL, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 30, 130, 246, 257, STR_NETWORK_FIND_SERVER, STR_NETWORK_FIND_SERVER_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 180, 280, 246, 257, STR_NETWORK_ADD_SERVER, STR_NETWORK_ADD_SERVER_TIP},
-
-/* RIGHT SIDE */
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 315, 415, 246, 257, STR_NETWORK_START_SERVER, STR_NETWORK_START_SERVER_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 246, 257, STR_012E_CANCEL, STR_NULL},
-
-{ WWT_PANEL, RESIZE_NONE, BGC, 310, 540, 42, 236, 0x0, STR_NULL},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 315, 415, 215, 226, STR_NETWORK_JOIN_GAME, STR_NULL},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 215, 226, STR_NETWORK_REFRESH, STR_NETWORK_REFRESH_TIP},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 197, 208, STR_NEWGRF_SETTINGS_BUTTON, STR_NULL},
-
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_game_window_desc = {
- WDP_CENTER, WDP_CENTER, 550, 264,
- WC_NETWORK_WINDOW,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
- _network_game_window_widgets,
- NetworkGameWindowWndProc,
-};
-
-void ShowNetworkGameWindow(void)
-{
- static bool first = true;
- Window *w;
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
-
- /* Only show once */
- if (first) {
- char* const *srv;
-
- first = false;
- // add all servers from the config file to our list
- for (srv = &_network_host_list[0]; srv != endof(_network_host_list) && *srv != NULL; srv++) {
- NetworkAddServer(*srv);
- }
-
- _ng_sorting.criteria = 2; // sort default by collectivity (green-dots on top)
- _ng_sorting.order = 0; // sort ascending by default
- }
-
- w = AllocateWindowDesc(&_network_game_window_desc);
- if (w != NULL) {
- querystr_d *querystr = &WP(w, network_ql_d).q;
-
- ttd_strlcpy(_edit_str_buf, _network_player_name, lengthof(_edit_str_buf));
- w->vscroll.cap = 13;
-
- querystr->afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&querystr->text, _edit_str_buf, lengthof(_edit_str_buf), 120);
-
- UpdateNetworkGameWindow(true);
- }
-}
-
-enum {
- NSSWND_START = 64,
- NSSWND_ROWSIZE = 12
-};
-
-/* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
-static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
-
- switch (e->event) {
- case WE_CREATE: /* focus input box */
- nd->field = 3;
- _network_game_info.use_password = (_network_server_password[0] != '\0');
- break;
-
- case WE_PAINT: {
- int y = NSSWND_START, pos;
- const FiosItem *item;
-
- SetDParam( 7, _connection_types_dropdown[_network_advertise]);
- SetDParam( 9, _players_dropdown[_network_game_info.clients_max]);
- SetDParam(11, _players_dropdown[_network_game_info.companies_max]);
- SetDParam(13, _players_dropdown[_network_game_info.spectators_max]);
- SetDParam(15, _language_dropdown[_network_game_info.server_lang]);
- DrawWindowWidgets(w);
-
- GfxFillRect(11, 63, 258, 215, 0xD7);
- DrawEditBox(w, &WP(w, network_ql_d).q, 3);
-
- DrawString(10, 22, STR_NETWORK_NEW_GAME_NAME, 2);
-
- DrawString(10, 43, STR_NETWORK_SELECT_MAP, 2);
-
- DrawString(280, 63, STR_NETWORK_CONNECTION, 2);
- DrawString(280, 95, STR_NETWORK_NUMBER_OF_CLIENTS, 2);
- DrawString(280, 127, STR_NETWORK_NUMBER_OF_COMPANIES, 2);
- DrawString(280, 159, STR_NETWORK_NUMBER_OF_SPECTATORS, 2);
- DrawString(280, 191, STR_NETWORK_LANGUAGE_SPOKEN, 2);
-
- if (_network_game_info.use_password) DoDrawString("*", 408, 23, 3);
-
- // draw list of maps
- pos = w->vscroll.pos;
- while (pos < _fios_num + 1) {
- item = _fios_list + pos - 1;
- if (item == nd->map || (pos == 0 && nd->map == NULL))
- GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
-
- if (pos == 0) {
- DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, 9);
- } else {
- DoDrawString(item->title, 14, y, _fios_colors[item->type] );
- }
- pos++;
- y += NSSWND_ROWSIZE;
-
- if (y >= w->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
- }
- } break;
-
- case WE_CLICK:
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case 0: /* Close 'X' */
- case 19: /* Cancel button */
- ShowNetworkGameWindow();
- break;
-
- case 4: /* Set password button */
- ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
- break;
-
- case 5: { /* Select map */
- int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
-
- y += w->vscroll.pos;
- if (y >= w->vscroll.count) return;
-
- nd->map = (y == 0) ? NULL : _fios_list + y - 1;
- SetWindowDirty(w);
- } break;
- case 7: case 8: /* Connection type */
- ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
- break;
- case 9: case 10: /* Number of Players (hide 0 and 1 players) */
- ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max, 10, 0, 3);
- break;
- case 11: case 12: /* Number of Companies (hide 0, 9 and 10 companies; max is 8) */
- ShowDropDownMenu(w, _players_dropdown, _network_game_info.companies_max, 12, 0, 1537);
- break;
- case 13: case 14: /* Number of Spectators */
- ShowDropDownMenu(w, _players_dropdown, _network_game_info.spectators_max, 14, 0, 0);
- break;
- case 15: case 16: /* Language */
- ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 16, 0, 0);
- break;
- case 17: /* Start game */
- _is_network_server = true;
-
- if (nd->map == NULL) { // start random new game
- ShowGenerateLandscape();
- } else { // load a scenario
- char *name = FiosBrowseTo(nd->map);
- if (name != NULL) {
- SetFiosType(nd->map->type);
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, nd->map->title, sizeof(_file_to_saveload.title));
-
- DeleteWindow(w);
- SwitchMode(SM_START_SCENARIO);
- }
- }
- break;
- case 18: /* Load game */
- _is_network_server = true;
- /* XXX - WC_NETWORK_WINDOW should stay, but if it stays, it gets
- * copied all the elements of 'load game' and upon closing that, it segfaults */
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
- ShowSaveLoadDialog(SLD_LOAD_GAME);
- break;
- }
- break;
-
- case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- switch (e->we.dropdown.button) {
- case 8: _network_advertise = (e->we.dropdown.index != 0); break;
- case 10: _network_game_info.clients_max = e->we.dropdown.index; break;
- case 12: _network_game_info.companies_max = e->we.dropdown.index; break;
- case 14: _network_game_info.spectators_max = e->we.dropdown.index; break;
- case 16: _network_game_info.server_lang = e->we.dropdown.index; break;
- }
-
- SetWindowDirty(w);
- break;
-
- case WE_MOUSELOOP:
- if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
- break;
-
- case WE_KEYPRESS:
- if (nd->field == 3) {
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
-
- ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
- UpdateTextBufferSize(&WP(w, network_ql_d).q.text);
- }
- break;
-
- case WE_ON_EDIT_TEXT: {
- ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
- _network_game_info.use_password = (_network_server_password[0] != '\0');
- SetWindowDirty(w);
- } break;
- }
-}
-
-static const Widget _network_start_server_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
-{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 419, 0, 13, STR_NETWORK_START_GAME_WINDOW, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, BGC, 0, 419, 14, 243, 0x0, STR_NULL},
-
-{ WWT_PANEL, RESIZE_NONE, BGC, 100, 272, 22, 33, 0x0, STR_NETWORK_NEW_GAME_NAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 285, 405, 22, 33, STR_NETWORK_SET_PASSWORD, STR_NETWORK_PASSWORD_TIP},
-
-{ WWT_INSET, RESIZE_NONE, BGC, 10, 271, 62, 216, 0x0, STR_NETWORK_SELECT_MAP_TIP},
-{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 259, 270, 63, 215, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-/* Combo boxes to control Connection Type / Max Clients / Max Companies / Max Observers / Language */
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 77, 88, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 78, 87, STR_0225, STR_NETWORK_CONNECTION_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 109, 120, STR_NETWORK_COMBO2, STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 110, 119, STR_0225, STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 141, 152, STR_NETWORK_COMBO3, STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 142, 151, STR_0225, STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 173, 184, STR_NETWORK_COMBO4, STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 174, 183, STR_0225, STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 205, 216, STR_NETWORK_COMBO5, STR_NETWORK_LANGUAGE_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 206, 215, STR_0225, STR_NETWORK_LANGUAGE_TIP},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 40, 140, 224, 235, STR_NETWORK_START_GAME, STR_NETWORK_START_GAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 150, 250, 224, 235, STR_NETWORK_LOAD_GAME, STR_NETWORK_LOAD_GAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 260, 360, 224, 235, STR_012E_CANCEL, STR_NULL},
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_start_server_window_desc = {
- WDP_CENTER, WDP_CENTER, 420, 244,
- WC_NETWORK_WINDOW,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
- _network_start_server_window_widgets,
- NetworkStartServerWindowWndProc,
-};
-
-static void ShowNetworkStartServerWindow(void)
-{
- Window *w;
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
-
- w = AllocateWindowDesc(&_network_start_server_window_desc);
- ttd_strlcpy(_edit_str_buf, _network_server_name, lengthof(_edit_str_buf));
-
- _saveload_mode = SLD_NEW_GAME;
- BuildFileList();
- w->vscroll.cap = 12;
- w->vscroll.count = _fios_num+1;
-
- WP(w, network_ql_d).q.afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, network_ql_d).q.text, _edit_str_buf, lengthof(_edit_str_buf), 160);
-}
-
-static byte NetworkLobbyFindCompanyIndex(byte pos)
-{
- byte i;
-
- /* Scroll through all _network_player_info and get the 'pos' item
- that is not empty */
- for (i = 0; i < MAX_PLAYERS; i++) {
- if (_network_player_info[i].company_name[0] != '\0') {
- if (pos-- == 0) return i;
- }
- }
-
- return 0;
-}
-
-/* uses network_d WP macro */
-static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_d);
-
- switch (e->event) {
- case WE_CREATE:
- nd->company = (byte)-1;
- break;
-
- case WE_PAINT: {
- const NetworkGameInfo *gi = &nd->server->info;
- int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
-
- SetWindowWidgetDisabledState(w, 7, nd->company == (byte)-1);
- SetWindowWidgetDisabledState(w, 8, gi->companies_on >= gi->companies_max);
- /* You can not join a server as spectator when it has no companies active..
- * it causes some nasty crashes */
- SetWindowWidgetDisabledState(w, 9, gi->spectators_on >= gi->spectators_max ||
- gi->companies_on == 0);
-
- DrawWindowWidgets(w);
-
- SetDParamStr(0, gi->server_name);
- DrawString(10, 22, STR_NETWORK_PREPARE_TO_JOIN, 2);
-
- /* Draw company list */
- pos = w->vscroll.pos;
- while (pos < gi->companies_on) {
- byte company = NetworkLobbyFindCompanyIndex(pos);
- bool income = false;
- if (nd->company == company)
- GfxFillRect(11, y - 1, 154, y + 10, 10); // show highlighted item with a different colour
-
- DoDrawStringTruncated(_network_player_info[company].company_name, 13, y, 16, 135 - 13);
- if (_network_player_info[company].use_password != 0) DrawSprite(SPR_LOCK, 135, y);
-
- /* If the company's income was positive puts a green dot else a red dot */
- if (_network_player_info[company].income >= 0) income = true;
- DrawSprite(SPR_BLOT | (income ? PALETTE_TO_GREEN : PALETTE_TO_RED), 145, y);
-
- pos++;
- y += NET_PRC__SIZE_OF_ROW;
- if (pos >= w->vscroll.cap) break;
- }
-
- /* Draw info about selected company when it is selected in the left window */
- GfxFillRect(174, 39, 403, 75, 157);
- DrawStringCentered(290, 50, STR_NETWORK_COMPANY_INFO, 0);
- if (nd->company != (byte)-1) {
- const uint x = 183;
- const uint trunc_width = w->widget[6].right - x;
- y = 80;
-
- SetDParam(0, nd->server->info.clients_on);
- SetDParam(1, nd->server->info.clients_max);
- SetDParam(2, nd->server->info.companies_on);
- SetDParam(3, nd->server->info.companies_max);
- DrawString(x, y, STR_NETWORK_CLIENTS, 2);
- y += 10;
-
- SetDParamStr(0, _network_player_info[nd->company].company_name);
- DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, 2, trunc_width);
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].inaugurated_year);
- DrawString(x, y, STR_NETWORK_INAUGURATION_YEAR, 2); // inauguration year
- y += 10;
-
- SetDParam64(0, _network_player_info[nd->company].company_value);
- DrawString(x, y, STR_NETWORK_VALUE, 2); // company value
- y += 10;
-
- SetDParam64(0, _network_player_info[nd->company].money);
- DrawString(x, y, STR_NETWORK_CURRENT_BALANCE, 2); // current balance
- y += 10;
-
- SetDParam64(0, _network_player_info[nd->company].income);
- DrawString(x, y, STR_NETWORK_LAST_YEARS_INCOME, 2); // last year's income
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].performance);
- DrawString(x, y, STR_NETWORK_PERFORMANCE, 2); // performance
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].num_vehicle[0]);
- SetDParam(1, _network_player_info[nd->company].num_vehicle[1]);
- SetDParam(2, _network_player_info[nd->company].num_vehicle[2]);
- SetDParam(3, _network_player_info[nd->company].num_vehicle[3]);
- SetDParam(4, _network_player_info[nd->company].num_vehicle[4]);
- DrawString(x, y, STR_NETWORK_VEHICLES, 2); // vehicles
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].num_station[0]);
- SetDParam(1, _network_player_info[nd->company].num_station[1]);
- SetDParam(2, _network_player_info[nd->company].num_station[2]);
- SetDParam(3, _network_player_info[nd->company].num_station[3]);
- SetDParam(4, _network_player_info[nd->company].num_station[4]);
- DrawString(x, y, STR_NETWORK_STATIONS, 2); // stations
- y += 10;
-
- SetDParamStr(0, _network_player_info[nd->company].players);
- DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, 2, trunc_width); // players
- }
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 0: case 11: /* Close 'X' | Cancel button */
- ShowNetworkGameWindow();
- break;
- case 4: { /* Company list */
- uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET_COMPANY) / NET_PRC__SIZE_OF_ROW;
-
- if (id_v >= w->vscroll.cap) return;
-
- id_v += w->vscroll.pos;
- nd->company = (id_v >= nd->server->info.companies_on) ? (byte)-1 : NetworkLobbyFindCompanyIndex(id_v);
- SetWindowDirty(w);
- } break;
- case 7: /* Join company */
- if (nd->company != (byte)-1) {
- _network_playas = nd->company;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- }
- break;
- case 8: /* New company */
- _network_playas = PLAYER_NEW_COMPANY;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- break;
- case 9: /* Spectate game */
- _network_playas = PLAYER_SPECTATOR;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- break;
- case 10: /* Refresh */
- NetworkQueryServer(_network_last_host, _network_last_port, false); // company info
- NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
- break;
- } break;
-
- case WE_MESSAGE:
- SetWindowDirty(w);
- break;
- }
-}
-
-static const Widget _network_lobby_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
-{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 419, 0, 13, STR_NETWORK_GAME_LOBBY, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, BGC, 0, 419, 14, 234, 0x0, STR_NULL},
-
-// company list
-{ WWT_PANEL, RESIZE_NONE, BTC, 10, 155, 38, 49, 0x0, STR_NULL},
-{ WWT_MATRIX, RESIZE_NONE, BGC, 10, 155, 50, 190, (10 << 8) + 1, STR_NETWORK_COMPANY_LIST_TIP},
-{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 156, 167, 38, 190, STR_NULL, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-
-// company/player info
-{ WWT_PANEL, RESIZE_NONE, BGC, 173, 404, 38, 190, 0x0, STR_NULL},
-
-// buttons
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 151, 200, 211, STR_NETWORK_JOIN_COMPANY, STR_NETWORK_JOIN_COMPANY_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 151, 215, 226, STR_NETWORK_NEW_COMPANY, STR_NETWORK_NEW_COMPANY_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 158, 268, 200, 211, STR_NETWORK_SPECTATE_GAME, STR_NETWORK_SPECTATE_GAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 158, 268, 215, 226, STR_NETWORK_REFRESH, STR_NETWORK_REFRESH_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 278, 388, 200, 211, STR_012E_CANCEL, STR_NULL},
-
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_lobby_window_desc = {
- WDP_CENTER, WDP_CENTER, 420, 235,
- WC_NETWORK_WINDOW,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
- _network_lobby_window_widgets,
- NetworkLobbyWindowWndProc,
-};
-
-/* Show the networklobbywindow with the selected server
- * @param ngl Selected game pointer which is passed to the new window */
-static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
-{
- Window *w;
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
-
- NetworkQueryServer(_network_last_host, _network_last_port, false); // company info
- NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
-
- w = AllocateWindowDesc(&_network_lobby_window_desc);
- if (w != NULL) {
- WP(w, network_ql_d).n.server = ngl;
- strcpy(_edit_str_buf, "");
- w->vscroll.cap = 10;
- }
-}
-
-// The window below gives information about the connected clients
-// and also makes able to give money to them, kick them (if server)
-// and stuff like that.
-
-extern void DrawPlayerIcon(PlayerID pid, int x, int y);
-
-// Every action must be of this form
-typedef void ClientList_Action_Proc(byte client_no);
-
-// Max 10 actions per client
-#define MAX_CLIENTLIST_ACTION 10
-
-// Some standard bullshit.. defines variables ;)
-static void ClientListWndProc(Window *w, WindowEvent *e);
-static void ClientListPopupWndProc(Window *w, WindowEvent *e);
-static byte _selected_clientlist_item = 255;
-static byte _selected_clientlist_y = 0;
-static char _clientlist_action[MAX_CLIENTLIST_ACTION][50];
-static ClientList_Action_Proc *_clientlist_proc[MAX_CLIENTLIST_ACTION];
-
-enum {
- CLNWND_OFFSET = 16,
- CLNWND_ROWSIZE = 10
-};
-
-static const Widget _client_list_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, RESIZE_NONE, 14, 11, 249, 0, 13, STR_NETWORK_CLIENT_LIST, STR_018C_WINDOW_TITLE_DRAG_THIS},
-
-{ WWT_PANEL, RESIZE_NONE, 14, 0, 249, 14, 14 + CLNWND_ROWSIZE + 1, 0x0, STR_NULL},
-{ WIDGETS_END},
-};
-
-static const Widget _client_list_popup_widgets[] = {
-{ WWT_PANEL, RESIZE_NONE, 14, 0, 99, 0, 0, 0, STR_NULL},
-{ WIDGETS_END},
-};
-
-static WindowDesc _client_list_desc = {
- WDP_AUTO, WDP_AUTO, 250, 1,
- WC_CLIENT_LIST,0,
- WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
- _client_list_widgets,
- ClientListWndProc
-};
-
-// Finds the Xth client-info that is active
-static const NetworkClientInfo *NetworkFindClientInfo(byte client_no)
-{
- const NetworkClientInfo *ci;
-
- FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
- if (client_no == 0) return ci;
- client_no--;
- }
-
- return NULL;
-}
-
-// Here we start to define the options out of the menu
-static void ClientList_Kick(byte client_no)
-{
- if (client_no < MAX_PLAYERS)
- SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
-}
-
-static void ClientList_Ban(byte client_no)
-{
- uint i;
- uint32 ip = NetworkFindClientInfo(client_no)->client_ip;
-
- for (i = 0; i < lengthof(_network_ban_list); i++) {
- if (_network_ban_list[i] == NULL) {
- _network_ban_list[i] = strdup(inet_ntoa(*(struct in_addr *)&ip));
- break;
- }
- }
-
- if (client_no < MAX_PLAYERS)
- SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
-}
-
-static void ClientList_GiveMoney(byte client_no)
-{
- if (NetworkFindClientInfo(client_no) != NULL)
- ShowNetworkGiveMoneyWindow(NetworkFindClientInfo(client_no)->client_playas);
-}
-
-static void ClientList_SpeakToClient(byte client_no)
-{
- if (NetworkFindClientInfo(client_no) != NULL)
- ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, NetworkFindClientInfo(client_no)->client_index);
-}
-
-static void ClientList_SpeakToCompany(byte client_no)
-{
- if (NetworkFindClientInfo(client_no) != NULL)
- ShowNetworkChatQueryWindow(DESTTYPE_TEAM, NetworkFindClientInfo(client_no)->client_playas);
-}
-
-static void ClientList_SpeakToAll(byte client_no)
-{
- ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
-}
-
-static void ClientList_None(byte client_no)
-{
- // No action ;)
-}
-
-
-
-// Help, a action is clicked! What do we do?
-static void HandleClientListPopupClick(byte index, byte clientno) {
- // A click on the Popup of the ClientList.. handle the command
- if (index < MAX_CLIENTLIST_ACTION && _clientlist_proc[index] != NULL) {
- _clientlist_proc[index](clientno);
- }
-}
-
-// Finds the amount of clients and set the height correct
-static bool CheckClientListHeight(Window *w)
-{
- int num = 0;
- const NetworkClientInfo *ci;
-
- // Should be replaced with a loop through all clients
- FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
- num++;
- }
-
- num *= CLNWND_ROWSIZE;
-
- // If height is changed
- if (w->height != CLNWND_OFFSET + num + 1) {
- // XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
- SetWindowDirty(w);
- w->widget[2].bottom = w->widget[2].top + num + 2;
- w->height = CLNWND_OFFSET + num + 1;
- SetWindowDirty(w);
- return false;
- }
- return true;
-}
-
-// Finds the amount of actions in the popup and set the height correct
-static uint ClientListPopupHeigth(void) {
- int i, num = 0;
-
- // Find the amount of actions
- for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
- if (_clientlist_action[i][0] == '\0') continue;
- if (_clientlist_proc[i] == NULL) continue;
- num++;
- }
-
- num *= CLNWND_ROWSIZE;
-
- return num + 1;
-}
-
-// Show the popup (action list)
-static Window *PopupClientList(Window *w, int client_no, int x, int y)
-{
- int i, h;
- const NetworkClientInfo *ci;
- DeleteWindowById(WC_TOOLBAR_MENU, 0);
-
- // Clean the current actions
- for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
- _clientlist_action[i][0] = '\0';
- _clientlist_proc[i] = NULL;
- }
-
- // Fill the actions this client has
- // Watch is, max 50 chars long!
-
- ci = NetworkFindClientInfo(client_no);
- if (ci == NULL) return NULL;
-
- i = 0;
- if (_network_own_client_index != ci->client_index) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_SpeakToClient;
- }
-
- if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_SpeakToCompany;
- }
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_SpeakToAll;
-
- if (_network_own_client_index != ci->client_index) {
- /* We are no spectator and the player we want to give money to is no spectator */
- if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas)) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_GiveMoney;
- }
- }
-
- // A server can kick clients (but not himself)
- if (_network_server && _network_own_client_index != ci->client_index) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_Kick;
-
- sprintf(_clientlist_action[i],"Ban"); // XXX GetString?
- _clientlist_proc[i++] = &ClientList_Ban;
- }
-
- if (i == 0) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_None;
- }
-
- /* Calculate the height */
- h = ClientListPopupHeigth();
-
- // Allocate the popup
- w = AllocateWindow(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets);
- w->widget[0].bottom = w->widget[0].top + h;
- w->widget[0].right = w->widget[0].left + 150;
-
- w->flags4 &= ~WF_WHITE_BORDER_MASK;
- WP(w,menu_d).item_count = 0;
- // Save our client
- WP(w,menu_d).main_button = client_no;
- WP(w,menu_d).sel_index = 0;
- // We are a popup
- _popup_menu_active = true;
-
- return w;
-}
-
-/** Main handle for the client popup list
- * uses menu_d WP macro */
-static void ClientListPopupWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- int i, y, sel;
- byte colour;
- DrawWindowWidgets(w);
-
- // Draw the actions
- sel = WP(w,menu_d).sel_index;
- y = 1;
- for (i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) {
- if (_clientlist_action[i][0] == '\0') continue;
- if (_clientlist_proc[i] == NULL) continue;
-
- if (sel-- == 0) { // Selected item, highlight it
- GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0);
- colour = 0xC;
- } else {
- colour = 0x10;
- }
-
- DoDrawString(_clientlist_action[i], 4, y, colour);
- }
- } break;
-
- case WE_POPUPMENU_SELECT: {
- // We selected an action
- int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
-
- if (index >= 0 && e->we.popupmenu.pt.y >= w->top)
- HandleClientListPopupClick(index, WP(w,menu_d).main_button);
-
- DeleteWindowById(WC_TOOLBAR_MENU, 0);
- } break;
-
- case WE_POPUPMENU_OVER: {
- // Our mouse hoovers over an action? Select it!
- int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
-
- if (index == -1 || index == WP(w,menu_d).sel_index) return;
-
- WP(w,menu_d).sel_index = index;
- SetWindowDirty(w);
- } break;
-
- }
-}
-
-// Main handle for clientlist
-static void ClientListWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- NetworkClientInfo *ci;
- int y, i = 0;
- byte colour;
-
- // Check if we need to reset the height
- if (!CheckClientListHeight(w)) break;
-
- DrawWindowWidgets(w);
-
- y = CLNWND_OFFSET;
-
- FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
- if (_selected_clientlist_item == i++) { // Selected item, highlight it
- GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
- colour = 0xC;
- } else {
- colour = 0x10;
- }
-
- if (ci->client_index == NETWORK_SERVER_INDEX) {
- DrawString(4, y, STR_NETWORK_SERVER, colour);
- } else {
- DrawString(4, y, STR_NETWORK_CLIENT, colour);
- }
-
- // Filter out spectators
- if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1);
-
- DoDrawString(ci->client_name, 81, y, colour);
-
- y += CLNWND_ROWSIZE;
- }
- } break;
-
- case WE_CLICK:
- // Show the popup with option
- if (_selected_clientlist_item != 255) {
- PopupClientList(w, _selected_clientlist_item, e->we.click.pt.x + w->left, e->we.click.pt.y + w->top);
- }
-
- break;
-
- case WE_MOUSEOVER:
- // -1 means we left the current window
- if (e->we.mouseover.pt.y == -1) {
- _selected_clientlist_y = 0;
- _selected_clientlist_item = 255;
- SetWindowDirty(w);
- break;
- }
- // It did not change.. no update!
- if (e->we.mouseover.pt.y == _selected_clientlist_y) break;
-
- // Find the new selected item (if any)
- _selected_clientlist_y = e->we.mouseover.pt.y;
- if (e->we.mouseover.pt.y > CLNWND_OFFSET) {
- _selected_clientlist_item = (e->we.mouseover.pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE;
- } else {
- _selected_clientlist_item = 255;
- }
-
- // Repaint
- SetWindowDirty(w);
- break;
-
- case WE_DESTROY: case WE_CREATE:
- // When created or destroyed, data is reset
- _selected_clientlist_item = 255;
- _selected_clientlist_y = 0;
- break;
- }
-}
-
-void ShowClientList(void)
-{
- AllocateWindowDescFront(&_client_list_desc, 0);
-}
-
-
-static NetworkPasswordType pw_type;
-
-
-void ShowNetworkNeedPassword(NetworkPasswordType npt)
-{
- StringID caption;
-
- pw_type = npt;
- switch (npt) {
- default: NOT_REACHED();
- case NETWORK_GAME_PASSWORD: caption = STR_NETWORK_NEED_GAME_PASSWORD_CAPTION; break;
- case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break;
- }
- ShowQueryString(STR_EMPTY, caption, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL);
-}
-
-
-static void NetworkJoinStatusWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- uint8 progress; // used for progress bar
- DrawWindowWidgets(w);
-
- DrawStringCentered(125, 35, STR_NETWORK_CONNECTING_1 + _network_join_status, 14);
- switch (_network_join_status) {
- case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
- case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
- progress = 10; // first two stages 10%
- break;
- case NETWORK_JOIN_STATUS_WAITING:
- SetDParam(0, _network_join_waiting);
- DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_WAITING, 14);
- progress = 15; // third stage is 15%
- break;
- case NETWORK_JOIN_STATUS_DOWNLOADING:
- SetDParam(0, _network_join_kbytes);
- SetDParam(1, _network_join_kbytes_total);
- DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, 14);
- /* Fallthrough */
- default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */
- progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total;
- }
-
- /* Draw nice progress bar :) */
- DrawFrameRect(20, 18, (int)((w->width - 20) * progress / 100), 28, 10, 0);
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 2: /* Disconnect button */
- NetworkDisconnect();
- DeleteWindow(w);
- SwitchMode(SM_MENU);
- ShowNetworkGameWindow();
- break;
- }
- break;
-
- /* If the server asks for a password, we need to fill it in */
- case WE_ON_EDIT_TEXT_CANCEL:
- NetworkDisconnect();
- ShowNetworkGameWindow();
- break;
-
- case WE_ON_EDIT_TEXT:
- SEND_COMMAND(PACKET_CLIENT_PASSWORD)(pw_type, e->we.edittext.str);
- break;
- }
-}
-
-static const Widget _network_join_status_window_widget[] = {
-{ WWT_CAPTION, RESIZE_NONE, 14, 0, 249, 0, 13, STR_NETWORK_CONNECTING, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PANEL, RESIZE_NONE, 14, 0, 249, 14, 84, 0x0, STR_NULL},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 75, 175, 69, 80, STR_NETWORK_DISCONNECT, STR_NULL},
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_join_status_window_desc = {
- WDP_CENTER, WDP_CENTER, 250, 85,
- WC_NETWORK_STATUS_WINDOW, 0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_MODAL,
- _network_join_status_window_widget,
- NetworkJoinStatusWindowWndProc,
-};
-
-void ShowJoinStatusWindow(void)
-{
- Window *w;
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
- w = AllocateWindowDesc(&_network_join_status_window_desc);
- /* Parent the status window to the lobby */
- if (w != NULL) w->parent = FindWindowById(WC_NETWORK_WINDOW, 0);
-}
-
-static void SendChat(const char *buf, DestType type, byte dest)
-{
- if (buf[0] == '\0') return;
- if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT + type, type, dest, buf);
- } else {
- NetworkServer_HandleChat(NETWORK_ACTION_CHAT + type, type, dest, buf, NETWORK_SERVER_INDEX);
- }
-}
-
-/**
- * Find the next item of the list of things that can be auto-completed.
- * @param item The current indexed item to return. This function can, and most
- * likely will, alter item, to skip empty items in the arrays.
- * @return Returns the char that matched to the index.
- */
-static const char *ChatTabCompletionNextItem(uint *item)
-{
- static char chat_tab_temp_buffer[64];
-
- /* First, try clients */
- if (*item < MAX_CLIENT_INFO) {
- /* Skip inactive clients */
- while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
- if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
- }
-
- /* Then, try townnames */
- /* Not that the following assumes all town indices are adjacent, ie no
- * towns have been deleted. */
- if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
- const Town *t;
-
- FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
- /* Get the town-name via the string-system */
- SetDParam(0, t->townnameparts);
- GetString(chat_tab_temp_buffer, t->townnametype, lastof(chat_tab_temp_buffer));
- return &chat_tab_temp_buffer[0];
- }
- }
-
- return NULL;
-}
-
-/**
- * Find what text to complete. It scans for a space from the left and marks
- * the word right from that as to complete. It also writes a \0 at the
- * position of the space (if any). If nothing found, buf is returned.
- */
-static char *ChatTabCompletionFindText(char *buf)
-{
- char *p = strrchr(buf, ' ');
- if (p == NULL) return buf;
-
- *p = '\0';
- return p + 1;
-}
-
-/**
- * See if we can auto-complete the current text of the user.
- */
-static void ChatTabCompletion(Window *w)
-{
- static char _chat_tab_completion_buf[lengthof(_edit_str_buf)];
- Textbuf *tb = &WP(w, querystr_d).text;
- uint len, tb_len;
- uint item;
- char *tb_buf, *pre_buf;
- const char *cur_name;
- bool second_scan = false;
-
- item = 0;
-
- /* Copy the buffer so we can modify it without damaging the real data */
- pre_buf = (_chat_tab_completion_active) ? strdup(_chat_tab_completion_buf) : strdup(tb->buf);
-
- tb_buf = ChatTabCompletionFindText(pre_buf);
- tb_len = strlen(tb_buf);
-
- while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
- item++;
-
- if (_chat_tab_completion_active) {
- /* We are pressing TAB again on the same name, is there an other name
- * that starts with this? */
- if (!second_scan) {
- uint offset;
- uint length;
-
- /* If we are completing at the begin of the line, skip the ': ' we added */
- if (tb_buf == pre_buf) {
- offset = 0;
- length = tb->length - 2;
- } else {
- /* Else, find the place we are completing at */
- offset = strlen(pre_buf) + 1;
- length = tb->length - offset;
- }
-
- /* Compare if we have a match */
- if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
-
- continue;
- }
-
- /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
- }
-
- len = strlen(cur_name);
- if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
- /* Save the data it was before completion */
- if (!second_scan) snprintf(_chat_tab_completion_buf, lengthof(_chat_tab_completion_buf), "%s", tb->buf);
- _chat_tab_completion_active = true;
-
- /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
- if (pre_buf == tb_buf) {
- snprintf(tb->buf, lengthof(_edit_str_buf), "%s: ", cur_name);
- } else {
- snprintf(tb->buf, lengthof(_edit_str_buf), "%s %s", pre_buf, cur_name);
- }
-
- /* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, querystr_d).text);
-
- SetWindowDirty(w);
- free(pre_buf);
- return;
- }
- }
-
- if (second_scan) {
- /* We walked all posibilities, and the user presses tab again.. revert to original text */
- strcpy(tb->buf, _chat_tab_completion_buf);
- _chat_tab_completion_active = false;
-
- /* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, querystr_d).text);
-
- SetWindowDirty(w);
- }
- free(pre_buf);
-}
-
-/* uses querystr_d WP macro
- * uses querystr_d->caption to store
- * - type of chat message (Private/Team/All) in bytes 0-7
- * - destination of chat message in the case of Team/Private in bytes 8-15 */
-static void ChatWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_CREATE:
- SendWindowMessage(WC_NEWS_WINDOW, 0, WE_CREATE, w->height, 0);
- SETBIT(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
- break;
-
- case WE_PAINT: {
- static const StringID chat_captions[] = {
- STR_NETWORK_CHAT_ALL_CAPTION,
- STR_NETWORK_CHAT_COMPANY_CAPTION,
- STR_NETWORK_CHAT_CLIENT_CAPTION
- };
- StringID msg;
-
- DrawWindowWidgets(w);
-
- assert(GB(WP(w, querystr_d).caption, 0, 8) < lengthof(chat_captions));
- msg = chat_captions[GB(WP(w, querystr_d).caption, 0, 8)];
- DrawStringRightAligned(w->widget[2].left - 2, w->widget[2].top + 1, msg, 16);
- DrawEditBox(w, &WP(w, querystr_d), 2);
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 3: { /* Send */
- DestType type = GB(WP(w, querystr_d).caption, 0, 8);
- byte dest = GB(WP(w, querystr_d).caption, 8, 8);
- SendChat(WP(w, querystr_d).text.buf, type, dest);
- } /* FALLTHROUGH */
- case 0: /* Cancel */ DeleteWindow(w); break;
- }
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, &WP(w, querystr_d), 2);
- break;
-
- case WE_KEYPRESS:
- if (e->we.keypress.keycode == WKC_TAB) {
- ChatTabCompletion(w);
- } else {
- _chat_tab_completion_active = false;
- switch (HandleEditBoxKey(w, &WP(w, querystr_d), 2, e)) {
- case 1: { /* Return */
- DestType type = GB(WP(w, querystr_d).caption, 0, 8);
- byte dest = GB(WP(w, querystr_d).caption, 8, 8);
- SendChat(WP(w, querystr_d).text.buf, type, dest);
- } /* FALLTHROUGH */
- case 2: /* Escape */ DeleteWindow(w); break;
- }
- }
- break;
-
- case WE_DESTROY:
- SendWindowMessage(WC_NEWS_WINDOW, 0, WE_DESTROY, 0, 0);
- CLRBIT(_no_scroll, SCROLL_CHAT);
- break;
- }
-}
-
-static const Widget _chat_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_PANEL, RESIZE_NONE, 14, 11, 639, 0, 13, 0x0, STR_NULL}, // background
-{ WWT_PANEL, RESIZE_NONE, 14, 75, 577, 1, 12, 0x0, STR_NULL}, // text box
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 578, 639, 1, 12, STR_NETWORK_SEND, STR_NULL}, // send button
-{ WIDGETS_END},
-};
-
-static const WindowDesc _chat_window_desc = {
- WDP_CENTER, -26, 640, 14, // x, y, width, height
- WC_SEND_NETWORK_MSG,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
- _chat_window_widgets,
- ChatWindowWndProc
-};
-
-void ShowNetworkChatQueryWindow(DestType type, byte dest)
-{
- Window *w;
-
- DeleteWindowById(WC_SEND_NETWORK_MSG, 0);
-
- _edit_str_buf[0] = '\0';
- _chat_tab_completion_active = false;
-
- w = AllocateWindowDesc(&_chat_window_desc);
-
- LowerWindowWidget(w, 2);
- WP(w, querystr_d).caption = GB(type, 0, 8) | (dest << 8); // Misuse of caption
- WP(w, querystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, lengthof(_edit_str_buf), 0);
-}
-
-#endif /* ENABLE_NETWORK */
--- a/network_gui.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_GUI_H
-#define NETWORK_GUI_H
-
-#ifdef ENABLE_NETWORK
-
-#include "network_data.h"
-
-void ShowNetworkNeedPassword(NetworkPasswordType npt);
-void ShowNetworkGiveMoneyWindow(byte player); // PlayerID
-void ShowNetworkChatQueryWindow(DestType type, byte dest);
-void ShowJoinStatusWindow(void);
-void ShowNetworkGameWindow(void);
-void ShowClientList(void);
-
-#else /* ENABLE_NETWORK */
-/* Network function stubs when networking is disabled */
-
-static inline void ShowNetworkChatQueryWindow(byte desttype, byte dest) {}
-static inline void ShowClientList(void) {}
-static inline void ShowNetworkGameWindow(void) {}
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_GUI_H */
--- a/network_server.c Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1527 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "stdafx.h"
-#include "openttd.h" // XXX StringID
-#include "debug.h"
-#include "string.h"
-#include "strings.h"
-#include "network_data.h"
-#include "train.h"
-#include "date.h"
-#include "table/strings.h"
-#include "functions.h"
-#include "network_server.h"
-#include "network_udp.h"
-#include "console.h"
-#include "command.h"
-#include "saveload.h"
-#include "vehicle.h"
-#include "station.h"
-#include "variables.h"
-#include "genworld.h"
-
-// This file handles all the server-commands
-
-static void NetworkHandleCommandQueue(NetworkClientState* cs);
-
-// **********
-// Sending functions
-// DEF_SERVER_SEND_COMMAND has parameter: NetworkClientState *cs
-// **********
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkClientState *cs, NetworkClientInfo *ci)
-{
- //
- // Packet: SERVER_CLIENT_INFO
- // Function: Sends info about a client
- // Data:
- // uint16: The index of the client (always unique on a server. 1 = server)
- // uint8: As which player the client is playing
- // String: The name of the client
- // String: The unique id of the client
- //
-
- if (ci->client_index != NETWORK_EMPTY_INDEX) {
- Packet *p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
- NetworkSend_uint16(p, ci->client_index);
- NetworkSend_uint8 (p, ci->client_playas);
- NetworkSend_string(p, ci->client_name);
- NetworkSend_string(p, ci->unique_id);
-
- NetworkSend_Packet(p, cs);
- }
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)
-{
-//
- // Packet: SERVER_COMPANY_INFO
- // Function: Sends info about the companies
- // Data:
- //
-
- int i;
-
- Player *player;
- Packet *p;
-
- byte active = ActivePlayerCount();
-
- if (active == 0) {
- p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
-
- NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (p, active);
-
- NetworkSend_Packet(p, cs);
- return;
- }
-
- NetworkPopulateCompanyInfo();
-
- FOR_ALL_PLAYERS(player) {
- if (!player->is_active) continue;
-
- p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
-
- NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (p, active);
- NetworkSend_uint8 (p, player->index);
-
- NetworkSend_string(p, _network_player_info[player->index].company_name);
- NetworkSend_uint32(p, _network_player_info[player->index].inaugurated_year);
- NetworkSend_uint64(p, _network_player_info[player->index].company_value);
- NetworkSend_uint64(p, _network_player_info[player->index].money);
- NetworkSend_uint64(p, _network_player_info[player->index].income);
- NetworkSend_uint16(p, _network_player_info[player->index].performance);
-
- /* Send 1 if there is a passord for the company else send 0 */
- if (_network_player_info[player->index].password[0] != '\0') {
- NetworkSend_uint8(p, 1);
- } else {
- NetworkSend_uint8(p, 0);
- }
-
- for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) {
- NetworkSend_uint16(p, _network_player_info[player->index].num_vehicle[i]);
- }
-
- for (i = 0; i < NETWORK_STATION_TYPES; i++) {
- NetworkSend_uint16(p, _network_player_info[player->index].num_station[i]);
- }
-
- if (_network_player_info[player->index].players[0] == '\0') {
- NetworkSend_string(p, "<none>");
- } else {
- NetworkSend_string(p, _network_player_info[player->index].players);
- }
-
- NetworkSend_Packet(p, cs);
- }
-
- p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
-
- NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (p, 0);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error)
-{
- //
- // Packet: SERVER_ERROR
- // Function: The client made an error
- // Data:
- // uint8: ErrorID (see network_data.h, NetworkErrorCode)
- //
-
- char str[100];
- Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
-
- NetworkSend_uint8(p, error);
- NetworkSend_Packet(p, cs);
-
- GetNetworkErrorMsg(str, error, lastof(str));
-
- // Only send when the current client was in game
- if (cs->status > STATUS_AUTH) {
- NetworkClientState *new_cs;
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH && new_cs != cs) {
- // Some errors we filter to a more general error. Clients don't have to know the real
- // reason a joining failed.
- if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
- error = NETWORK_ERROR_ILLEGAL_PACKET;
-
- SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, error);
- }
- }
- } else {
- DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->index, str);
- }
-
- cs->has_quit = true;
-
- // Make sure the data get's there before we close the connection
- NetworkSend_Packets(cs);
-
- // The client made a mistake, so drop his connection now!
- NetworkCloseClient(cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientState *cs, NetworkPasswordType type)
-{
- //
- // Packet: SERVER_NEED_PASSWORD
- // Function: Indication to the client that the server needs a password
- // Data:
- // uint8: Type of password
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
- NetworkSend_uint8(p, type);
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
-{
- //
- // Packet: SERVER_WELCOME
- // Function: The client is joined and ready to receive his map
- // Data:
- // uint16: Own ClientID
- //
-
- Packet *p;
- const NetworkClientState *new_cs;
-
- // Invalid packet when status is AUTH or higher
- if (cs->status >= STATUS_AUTH) return;
-
- cs->status = STATUS_AUTH;
- _network_game_info.clients_on++;
-
- p = NetworkSend_Init(PACKET_SERVER_WELCOME);
- NetworkSend_uint16(p, cs->index);
- NetworkSend_Packet(p, cs);
-
- // Transmit info about all the active clients
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs != cs && new_cs->status > STATUS_AUTH)
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, DEREF_CLIENT_INFO(new_cs));
- }
- // Also send the info of the server
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX));
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WAIT)
-{
- //
- // Packet: PACKET_SERVER_WAIT
- // Function: The client can not receive the map at the moment because
- // someone else is already receiving the map
- // Data:
- // uint8: Clients awaiting map
- //
- int waiting = 0;
- NetworkClientState *new_cs;
- Packet *p;
-
- // Count how many players are waiting in the queue
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status == STATUS_MAP_WAIT) waiting++;
- }
-
- p = NetworkSend_Init(PACKET_SERVER_WAIT);
- NetworkSend_uint8(p, waiting);
- NetworkSend_Packet(p, cs);
-}
-
-// This sends the map to the client
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
-{
- //
- // Packet: SERVER_MAP
- // Function: Sends the map to the client, or a part of it (it is splitted in
- // a lot of multiple packets)
- // Data:
- // uint8: packet-type (MAP_PACKET_START, MAP_PACKET_NORMAL and MAP_PACKET_END)
- // if MAP_PACKET_START:
- // uint32: The current FrameCounter
- // if MAP_PACKET_NORMAL:
- // piece of the map (till max-size of packet)
- // if MAP_PACKET_END:
- // uint32: seed0 of player
- // uint32: seed1 of player
- // last 2 are repeated MAX_PLAYERS time
- //
-
- static FILE *file_pointer;
- static uint sent_packets; // How many packets we did send succecfully last time
-
- if (cs->status < STATUS_AUTH) {
- // Illegal call, return error and ignore the packet
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
- return;
- }
-
- if (cs->status == STATUS_AUTH) {
- char filename[256];
- Packet *p;
-
- // Make a dump of the current game
- snprintf(filename, lengthof(filename), "%s%snetwork_server.tmp", _paths.autosave_dir, PATHSEP);
- if (SaveOrLoad(filename, SL_SAVE) != SL_OK) error("network savedump failed");
-
- file_pointer = fopen(filename, "rb");
- fseek(file_pointer, 0, SEEK_END);
-
- // Now send the _frame_counter and how many packets are coming
- p = NetworkSend_Init(PACKET_SERVER_MAP);
- NetworkSend_uint8(p, MAP_PACKET_START);
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_uint32(p, ftell(file_pointer));
- NetworkSend_Packet(p, cs);
-
- fseek(file_pointer, 0, SEEK_SET);
-
- sent_packets = 4; // We start with trying 4 packets
-
- cs->status = STATUS_MAP;
- /* Mark the start of download */
- cs->last_frame = _frame_counter;
- cs->last_frame_server = _frame_counter;
- }
-
- if (cs->status == STATUS_MAP) {
- uint i;
- int res;
- for (i = 0; i < sent_packets; i++) {
- Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
- NetworkSend_uint8(p, MAP_PACKET_NORMAL);
- res = (int)fread(p->buffer + p->size, 1, SEND_MTU - p->size, file_pointer);
-
- if (ferror(file_pointer)) error("Error reading temporary network savegame!");
-
- p->size += res;
- NetworkSend_Packet(p, cs);
- if (feof(file_pointer)) {
- // Done reading!
- Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
- NetworkSend_uint8(p, MAP_PACKET_END);
- NetworkSend_Packet(p, cs);
-
- // Set the status to DONE_MAP, no we will wait for the client
- // to send it is ready (maybe that happens like never ;))
- cs->status = STATUS_DONE_MAP;
- fclose(file_pointer);
-
- {
- NetworkClientState *new_cs;
- bool new_map_client = false;
- // Check if there is a client waiting for receiving the map
- // and start sending him the map
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status == STATUS_MAP_WAIT) {
- // Check if we already have a new client to send the map to
- if (!new_map_client) {
- // If not, this client will get the map
- new_cs->status = STATUS_AUTH;
- new_map_client = true;
- SEND_COMMAND(PACKET_SERVER_MAP)(new_cs);
- } else {
- // Else, send the other clients how many clients are in front of them
- SEND_COMMAND(PACKET_SERVER_WAIT)(new_cs);
- }
- }
- }
- }
-
- // There is no more data, so break the for
- break;
- }
- }
-
- // Send all packets (forced) and check if we have send it all
- NetworkSend_Packets(cs);
- if (cs->packet_queue == NULL) {
- // All are sent, increase the sent_packets
- sent_packets *= 2;
- } else {
- // Not everything is sent, decrease the sent_packets
- if (sent_packets > 1) sent_packets /= 2;
- }
- }
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkClientState *cs, uint16 client_index)
-{
- //
- // Packet: SERVER_JOIN
- // Function: A client is joined (all active clients receive this after a
- // PACKET_CLIENT_MAP_OK) Mostly what directly follows is a
- // PACKET_SERVER_CLIENT_INFO
- // Data:
- // uint16: Client-Index
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_JOIN);
-
- NetworkSend_uint16(p, client_index);
-
- NetworkSend_Packet(p, cs);
-}
-
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_FRAME)
-{
- //
- // Packet: SERVER_FRAME
- // Function: Sends the current frame-counter to the client
- // Data:
- // uint32: Frame Counter
- // uint32: Frame Counter Max (how far may the client walk before the server?)
- // [uint32: general-seed-1]
- // [uint32: general-seed-2]
- // (last two depends on compile-settings, and are not default settings)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_FRAME);
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_uint32(p, _frame_counter_max);
-#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
- NetworkSend_uint32(p, _sync_seed_1);
-#ifdef NETWORK_SEND_DOUBLE_SEED
- NetworkSend_uint32(p, _sync_seed_2);
-#endif
-#endif
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SYNC)
-{
- //
- // Packet: SERVER_SYNC
- // Function: Sends a sync-check to the client
- // Data:
- // uint32: Frame Counter
- // uint32: General-seed-1
- // [uint32: general-seed-2]
- // (last one depends on compile-settings, and are not default settings)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_SYNC);
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_uint32(p, _sync_seed_1);
-
-#ifdef NETWORK_SEND_DOUBLE_SEED
- NetworkSend_uint32(p, _sync_seed_2);
-#endif
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMMAND)(NetworkClientState *cs, CommandPacket *cp)
-{
- //
- // Packet: SERVER_COMMAND
- // Function: Sends a DoCommand to the client
- // Data:
- // uint8: PlayerID (0..MAX_PLAYERS-1)
- // uint32: CommandID (see command.h)
- // uint32: P1 (free variables used in DoCommand)
- // uint32: P2
- // uint32: Tile
- // string: text
- // uint8: CallBackID (see callback_table.c)
- // uint32: Frame of execution
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_COMMAND);
-
- NetworkSend_uint8(p, cp->player);
- NetworkSend_uint32(p, cp->cmd);
- NetworkSend_uint32(p, cp->p1);
- NetworkSend_uint32(p, cp->p2);
- NetworkSend_uint32(p, cp->tile);
- NetworkSend_string(p, cp->text);
- NetworkSend_uint8(p, cp->callback);
- NetworkSend_uint32(p, cp->frame);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkClientState *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg)
-{
- //
- // Packet: SERVER_CHAT
- // Function: Sends a chat-packet to the client
- // Data:
- // uint8: ActionID (see network_data.h, NetworkAction)
- // uint16: Client-index
- // String: Message (max MAX_TEXT_MSG_LEN)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_CHAT);
-
- NetworkSend_uint8(p, action);
- NetworkSend_uint16(p, client_index);
- NetworkSend_uint8(p, self_send);
- NetworkSend_string(p, msg);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, uint16 client_index, NetworkErrorCode errorno)
-{
- //
- // Packet: SERVER_ERROR_QUIT
- // Function: One of the clients made an error and is quiting the game
- // This packet informs the other clients of that.
- // Data:
- // uint16: Client-index
- // uint8: ErrorID (see network_data.h, NetworkErrorCode)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR_QUIT);
-
- NetworkSend_uint16(p, client_index);
- NetworkSend_uint8(p, errorno);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkClientState *cs, uint16 client_index, const char *leavemsg)
-{
- //
- // Packet: SERVER_ERROR_QUIT
- // Function: A client left the game, and this packets informs the other clients
- // of that.
- // Data:
- // uint16: Client-index
- // String: leave-message
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_QUIT);
-
- NetworkSend_uint16(p, client_index);
- NetworkSend_string(p, leavemsg);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN)
-{
- //
- // Packet: SERVER_SHUTDOWN
- // Function: Let the clients know that the server is closing
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_SHUTDOWN);
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME)
-{
- //
- // Packet: PACKET_SERVER_NEWGAME
- // Function: Let the clients know that the server is loading a new map
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_NEWGAME);
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command)
-{
- Packet *p = NetworkSend_Init(PACKET_SERVER_RCON);
-
- NetworkSend_uint16(p, color);
- NetworkSend_string(p, command);
- NetworkSend_Packet(p, cs);
-}
-
-// **********
-// Receiving functions
-// DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientState *cs, Packet *p
-// **********
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
-{
- SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
-{
- char name[NETWORK_CLIENT_NAME_LENGTH];
- char unique_id[NETWORK_NAME_LENGTH];
- NetworkClientInfo *ci;
- byte playas;
- NetworkLanguage client_lang;
- char client_revision[NETWORK_REVISION_LENGTH];
-
- NetworkRecv_string(cs, p, client_revision, sizeof(client_revision));
-
-#if defined(WITH_REV) || defined(WITH_REV_HACK)
- // Check if the client has revision control enabled
- if (strcmp(NOREV_STRING, client_revision) != 0 &&
- strcmp(_network_game_info.server_revision, client_revision) != 0) {
- // Different revisions!!
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION);
- return;
- }
-#endif
-
- NetworkRecv_string(cs, p, name, sizeof(name));
- playas = NetworkRecv_uint8(cs, p);
- client_lang = NetworkRecv_uint8(cs, p);
- NetworkRecv_string(cs, p, unique_id, sizeof(unique_id));
-
- if (cs->has_quit) return;
-
- // join another company does not affect these values
- switch (playas) {
- case PLAYER_NEW_COMPANY: /* New company */
- if (ActivePlayerCount() >= _network_game_info.companies_max) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
- return;
- }
- break;
- case PLAYER_SPECTATOR: /* Spectator */
- if (NetworkSpectatorCount() >= _network_game_info.spectators_max) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
- return;
- }
- break;
- default: /* Join another company (companies 1-8 (index 0-7)) */
- if (!IsValidPlayer(playas)) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
- return;
- }
- break;
- }
-
- // We need a valid name.. make it Player
- if (*name == '\0') ttd_strlcpy(name, "Player", sizeof(name));
-
- if (!NetworkFindName(name)) { // Change name if duplicate
- // We could not create a name for this player
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
- return;
- }
-
- ci = DEREF_CLIENT_INFO(cs);
-
- ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
- ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
- ci->client_playas = playas;
- ci->client_lang = client_lang;
-
- // We now want a password from the client
- // else we do not allow him in!
- if (_network_game_info.use_password) {
- SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
- } else {
- if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
- SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
- } else {
- SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
- }
- }
-
- /* Make sure companies to which people try to join are not autocleaned */
- if (IsValidPlayer(playas)) _network_player_info[playas].months_empty = 0;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
-{
- NetworkPasswordType type;
- char password[NETWORK_PASSWORD_LENGTH];
- const NetworkClientInfo *ci;
-
- type = NetworkRecv_uint8(cs, p);
- NetworkRecv_string(cs, p, password, sizeof(password));
-
- if (cs->status == STATUS_INACTIVE && type == NETWORK_GAME_PASSWORD) {
- // Check game-password
- if (strcmp(password, _network_game_info.server_password) != 0) {
- // Password is invalid
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
- return;
- }
-
- ci = DEREF_CLIENT_INFO(cs);
-
- if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
- SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
- return;
- }
-
- // Valid password, allow user
- SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
- return;
- } else if (cs->status == STATUS_INACTIVE && type == NETWORK_COMPANY_PASSWORD) {
- ci = DEREF_CLIENT_INFO(cs);
-
- if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
- // Password is invalid
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
- return;
- }
-
- SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
- return;
- }
-
-
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- return;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
-{
- const NetworkClientState *new_cs;
-
- // The client was never joined.. so this is impossible, right?
- // Ignore the packet, give the client a warning, and close his connection
- if (cs->status < STATUS_AUTH || cs->has_quit) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
- return;
- }
-
- // Check if someone else is receiving the map
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status == STATUS_MAP) {
- // Tell the new client to wait
- cs->status = STATUS_MAP_WAIT;
- SEND_COMMAND(PACKET_SERVER_WAIT)(cs);
- return;
- }
- }
-
- // We receive a request to upload the map.. give it to the client!
- SEND_COMMAND(PACKET_SERVER_MAP)(cs);
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
-{
- // Client has the map, now start syncing
- if (cs->status == STATUS_DONE_MAP && !cs->has_quit) {
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkClientState *new_cs;
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, client_name, "");
-
- // Mark the client as pre-active, and wait for an ACK
- // so we know he is done loading and in sync with us
- cs->status = STATUS_PRE_ACTIVE;
- NetworkHandleCommandQueue(cs);
- SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
- SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
-
- // This is the frame the client receives
- // we need it later on to make sure the client is not too slow
- cs->last_frame = _frame_counter;
- cs->last_frame_server = _frame_counter;
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH) {
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, DEREF_CLIENT_INFO(cs));
- SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->index);
- }
- }
-
- if (_network_pause_on_join) {
- /* Now pause the game till the client is in sync */
- DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
-
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
- }
- } else {
- // Wrong status for this packet, give a warning to client, and close connection
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- }
-}
-
-/** Enforce the command flags.
- * Eg a server-only command can only be executed by a server, etc.
- * @param *cp the commandpacket that is going to be checked
- * @param *ci client information for debugging output to console
- */
-static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *ci)
-{
- byte flags = GetCommandFlags(cp->cmd);
-
- if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
- IConsolePrintF(_icolour_err, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
- return false;
- }
-
- if (flags & CMD_OFFLINE) {
- IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
- return false;
- }
-
- return true;
-}
-
-/** The client has done a command and wants us to handle it
- * @param *cs the connected client that has sent the command
- * @param *p the packet in which the command was sent
- */
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
-{
- NetworkClientState *new_cs;
- const NetworkClientInfo *ci;
- byte callback;
-
- CommandPacket *cp = malloc(sizeof(CommandPacket));
-
- // The client was never joined.. so this is impossible, right?
- // Ignore the packet, give the client a warning, and close his connection
- if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- return;
- }
-
- cp->player = NetworkRecv_uint8(cs, p);
- cp->cmd = NetworkRecv_uint32(cs, p);
- cp->p1 = NetworkRecv_uint32(cs, p);
- cp->p2 = NetworkRecv_uint32(cs, p);
- cp->tile = NetworkRecv_uint32(cs, p);
- NetworkRecv_string(cs, p, cp->text, lengthof(cp->text));
-
- callback = NetworkRecv_uint8(cs, p);
-
- if (cs->has_quit) return;
-
- ci = DEREF_CLIENT_INFO(cs);
-
- /* Check if cp->cmd is valid */
- if (!IsValidCommand(cp->cmd)) {
- IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- return;
- }
-
- if (!CheckCommandFlags(cp, ci)) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
- return;
- }
-
- /** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs
- * to match the player in the packet. If it doesn't, the client has done
- * something pretty naughty (or a bug), and will be kicked
- */
- if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) {
- IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
- ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1);
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
- return;
- }
-
- /** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the
- * player the correct ID, the server injects p2 and executes the command. Any other p1
- * is prohibited. Pretty ugly and should be redone together with its function.
- * @see CmdPlayerCtrl() players.c:655
- */
- if (cp->cmd == CMD_PLAYER_CTRL) {
- if (cp->p1 != 0) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
- return;
- }
-
- /* XXX - Execute the command as a valid player. Normally this would be done by a
- * spectator, but that is not allowed any commands. So do an impersonation. The drawback
- * of this is that the first company's last_built_tile is also updated... */
- cp->player = 0;
- cp->p2 = cs - _clients; // XXX - UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
- }
-
- // The frame can be executed in the same frame as the next frame-packet
- // That frame just before that frame is saved in _frame_counter_max
- cp->frame = _frame_counter_max + 1;
- cp->next = NULL;
-
- // Queue the command for the clients (are send at the end of the frame
- // if they can handle it ;))
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status >= STATUS_MAP) {
- // Callbacks are only send back to the client who sent them in the
- // first place. This filters that out.
- cp->callback = (new_cs != cs) ? 0 : callback;
- NetworkAddCommandQueue(new_cs, cp);
- }
- }
-
- cp->callback = 0;
- // Queue the command on the server
- if (_local_command_queue == NULL) {
- _local_command_queue = cp;
- } else {
- // Find last packet
- CommandPacket *c = _local_command_queue;
- while (c->next != NULL) c = c->next;
- c->next = cp;
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
-{
- // This packets means a client noticed an error and is reporting this
- // to us. Display the error and report it to the other clients
- NetworkClientState *new_cs;
- char str[100];
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkErrorCode errorno = NetworkRecv_uint8(cs, p);
-
- // The client was never joined.. thank the client for the packet, but ignore it
- if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
- cs->has_quit = true;
- return;
- }
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- GetNetworkErrorMsg(str, errorno, lastof(str));
-
- DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH) {
- SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
- }
- }
-
- cs->has_quit = true;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
-{
- // The client wants to leave. Display this and report it to the other
- // clients.
- NetworkClientState *new_cs;
- char str[100];
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
-
- // The client was never joined.. thank the client for the packet, but ignore it
- if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
- cs->has_quit = true;
- return;
- }
-
- NetworkRecv_string(cs, p, str, lengthof(str));
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH) {
- SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->index, str);
- }
- }
-
- cs->has_quit = true;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
-{
- uint32 frame = NetworkRecv_uint32(cs, p);
-
- /* The client is trying to catch up with the server */
- if (cs->status == STATUS_PRE_ACTIVE) {
- /* The client is not yet catched up? */
- if (frame + DAY_TICKS < _frame_counter) return;
-
- /* Now he is! Unpause the game */
- cs->status = STATUS_ACTIVE;
-
- if (_network_pause_on_join) {
- DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
- }
-
- CheckMinPlayers();
-
- /* Execute script for, e.g. MOTD */
- IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
- }
-
- // The client received the frame, make note of it
- cs->last_frame = frame;
- // With those 2 values we can calculate the lag realtime
- cs->last_frame_server = _frame_counter;
-}
-
-
-
-void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
-{
- NetworkClientState *cs;
- const NetworkClientInfo *ci, *ci_own, *ci_to;
-
- switch (desttype) {
- case DESTTYPE_CLIENT:
- /* Are we sending to the server? */
- if (dest == NETWORK_SERVER_INDEX) {
- ci = NetworkFindClientInfoFromIndex(from_index);
- /* Display the text locally, and that is it */
- if (ci != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
- } else {
- /* Else find the client to send the message to */
- FOR_ALL_CLIENTS(cs) {
- if (cs->index == dest) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
- break;
- }
- }
- }
-
- // Display the message locally (so you know you have sent it)
- if (from_index != dest) {
- if (from_index == NETWORK_SERVER_INDEX) {
- ci = NetworkFindClientInfoFromIndex(from_index);
- ci_to = NetworkFindClientInfoFromIndex(dest);
- if (ci != NULL && ci_to != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
- } else {
- FOR_ALL_CLIENTS(cs) {
- if (cs->index == from_index) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, dest, true, msg);
- break;
- }
- }
- }
- }
- break;
- case DESTTYPE_TEAM: {
- bool show_local = true; // If this is false, the message is already displayed
- // on the client who did sent it.
- /* Find all clients that belong to this player */
- ci_to = NULL;
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (ci->client_playas == dest) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
- if (cs->index == from_index) show_local = false;
- ci_to = ci; // Remember a client that is in the company for company-name
- }
- }
-
- ci = NetworkFindClientInfoFromIndex(from_index);
- ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
- if (from_index == NETWORK_SERVER_INDEX) show_local = false;
- ci_to = ci_own;
- }
-
- /* There is no such player */
- if (ci_to == NULL) break;
-
- // Display the message locally (so you know you have sent it)
- if (ci != NULL && show_local) {
- if (from_index == NETWORK_SERVER_INDEX) {
- char name[NETWORK_NAME_LENGTH];
- StringID str = IsValidPlayer(ci_to->client_playas) ? GetPlayer(ci_to->client_playas)->name_1 : STR_NETWORK_SPECTATORS;
- GetString(name, str, lastof(name));
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
- } else {
- FOR_ALL_CLIENTS(cs) {
- if (cs->index == from_index) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_index, true, msg);
- }
- }
- }
- }
- }
- break;
- default:
- DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
- /* fall-through to next case */
- case DESTTYPE_BROADCAST:
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
- }
- ci = NetworkFindClientInfoFromIndex(from_index);
- if (ci != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
- break;
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
-{
- NetworkAction action = NetworkRecv_uint8(cs, p);
- DestType desttype = NetworkRecv_uint8(cs, p);
- int dest = NetworkRecv_uint8(cs, p);
- char msg[MAX_TEXT_MSG_LEN];
-
- NetworkRecv_string(cs, p, msg, MAX_TEXT_MSG_LEN);
-
- NetworkServer_HandleChat(action, desttype, dest, msg, cs->index);
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
-{
- char password[NETWORK_PASSWORD_LENGTH];
- const NetworkClientInfo *ci;
-
- NetworkRecv_string(cs, p, password, sizeof(password));
- ci = DEREF_CLIENT_INFO(cs);
-
- if (IsValidPlayer(ci->client_playas)) {
- ttd_strlcpy(_network_player_info[ci->client_playas].password, password, sizeof(_network_player_info[0].password));
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
-{
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkClientInfo *ci;
-
- NetworkRecv_string(cs, p, client_name, sizeof(client_name));
- ci = DEREF_CLIENT_INFO(cs);
-
- if (cs->has_quit) return;
-
- if (ci != NULL) {
- // Display change
- if (NetworkFindName(client_name)) {
- NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", client_name);
- ttd_strlcpy(ci->client_name, client_name, sizeof(ci->client_name));
- NetworkUpdateClientInfo(ci->client_index);
- }
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
-{
- char pass[NETWORK_PASSWORD_LENGTH];
- char command[NETWORK_RCONCOMMAND_LENGTH];
-
- if (_network_game_info.rcon_password[0] == '\0') return;
-
- NetworkRecv_string(cs, p, pass, sizeof(pass));
- NetworkRecv_string(cs, p, command, sizeof(command));
-
- if (strcmp(pass, _network_game_info.rcon_password) != 0) {
- DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
- return;
- }
-
- DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->index, command);
-
- _redirect_console_to_client = cs->index;
- IConsoleCmdExec(command);
- _redirect_console_to_client = 0;
- return;
-}
-
-// The layout for the receive-functions by the server
-typedef void NetworkServerPacket(NetworkClientState *cs, Packet *p);
-
-
-// This array matches PacketType. At an incoming
-// packet it is matches against this array
-// and that way the right function to handle that
-// packet is found.
-static NetworkServerPacket* const _network_server_packet[] = {
- NULL, /*PACKET_SERVER_FULL,*/
- NULL, /*PACKET_SERVER_BANNED,*/
- RECEIVE_COMMAND(PACKET_CLIENT_JOIN),
- NULL, /*PACKET_SERVER_ERROR,*/
- RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO),
- NULL, /*PACKET_SERVER_COMPANY_INFO,*/
- NULL, /*PACKET_SERVER_CLIENT_INFO,*/
- NULL, /*PACKET_SERVER_NEED_PASSWORD,*/
- RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD),
- NULL, /*PACKET_SERVER_WELCOME,*/
- RECEIVE_COMMAND(PACKET_CLIENT_GETMAP),
- NULL, /*PACKET_SERVER_WAIT,*/
- NULL, /*PACKET_SERVER_MAP,*/
- RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK),
- NULL, /*PACKET_SERVER_JOIN,*/
- NULL, /*PACKET_SERVER_FRAME,*/
- NULL, /*PACKET_SERVER_SYNC,*/
- RECEIVE_COMMAND(PACKET_CLIENT_ACK),
- RECEIVE_COMMAND(PACKET_CLIENT_COMMAND),
- NULL, /*PACKET_SERVER_COMMAND,*/
- RECEIVE_COMMAND(PACKET_CLIENT_CHAT),
- NULL, /*PACKET_SERVER_CHAT,*/
- RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD),
- RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME),
- RECEIVE_COMMAND(PACKET_CLIENT_QUIT),
- RECEIVE_COMMAND(PACKET_CLIENT_ERROR),
- NULL, /*PACKET_SERVER_QUIT,*/
- NULL, /*PACKET_SERVER_ERROR_QUIT,*/
- NULL, /*PACKET_SERVER_SHUTDOWN,*/
- NULL, /*PACKET_SERVER_NEWGAME,*/
- NULL, /*PACKET_SERVER_RCON,*/
- RECEIVE_COMMAND(PACKET_CLIENT_RCON),
-};
-
-// If this fails, check the array above with network_data.h
-assert_compile(lengthof(_network_server_packet) == PACKET_END);
-
-// This update the company_info-stuff
-void NetworkPopulateCompanyInfo(void)
-{
- char password[NETWORK_PASSWORD_LENGTH];
- const Player *p;
- const Vehicle *v;
- const Station *s;
- const NetworkClientState *cs;
- const NetworkClientInfo *ci;
- uint i;
- uint16 months_empty;
-
- FOR_ALL_PLAYERS(p) {
- if (!p->is_active) {
- memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
- continue;
- }
-
- // Clean the info but not the password
- ttd_strlcpy(password, _network_player_info[p->index].password, sizeof(password));
- months_empty = _network_player_info[p->index].months_empty;
- memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
- _network_player_info[p->index].months_empty = months_empty;
- ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password));
-
- // Grap the company name
- SetDParam(0, p->name_1);
- SetDParam(1, p->name_2);
- GetString(_network_player_info[p->index].company_name, STR_JUST_STRING, lastof(_network_player_info[p->index].company_name));
-
- // Check the income
- if (_cur_year - 1 == p->inaugurated_year) {
- // The player is here just 1 year, so display [2], else display[1]
- for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) {
- _network_player_info[p->index].income -= p->yearly_expenses[2][i];
- }
- } else {
- for (i = 0; i < lengthof(p->yearly_expenses[1]); i++) {
- _network_player_info[p->index].income -= p->yearly_expenses[1][i];
- }
- }
-
- // Set some general stuff
- _network_player_info[p->index].inaugurated_year = p->inaugurated_year;
- _network_player_info[p->index].company_value = p->old_economy[0].company_value;
- _network_player_info[p->index].money = p->money64;
- _network_player_info[p->index].performance = p->old_economy[0].performance_history;
- }
-
- // Go through all vehicles and count the type of vehicles
- FOR_ALL_VEHICLES(v) {
- if (!IsValidPlayer(v->owner)) continue;
-
- switch (v->type) {
- case VEH_Train:
- if (IsFrontEngine(v)) _network_player_info[v->owner].num_vehicle[0]++;
- break;
-
- case VEH_Road:
- if (v->cargo_type != CT_PASSENGERS) {
- _network_player_info[v->owner].num_vehicle[1]++;
- } else {
- _network_player_info[v->owner].num_vehicle[2]++;
- }
- break;
-
- case VEH_Aircraft:
- if (v->subtype <= 2) _network_player_info[v->owner].num_vehicle[3]++;
- break;
-
- case VEH_Ship:
- _network_player_info[v->owner].num_vehicle[4]++;
- break;
-
- case VEH_Special:
- case VEH_Disaster:
- break;
- }
- }
-
- // Go through all stations and count the types of stations
- FOR_ALL_STATIONS(s) {
- if (IsValidPlayer(s->owner)) {
- NetworkPlayerInfo *npi = &_network_player_info[s->owner];
-
- if (s->facilities & FACIL_TRAIN) npi->num_station[0]++;
- if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[1]++;
- if (s->facilities & FACIL_BUS_STOP) npi->num_station[2]++;
- if (s->facilities & FACIL_AIRPORT) npi->num_station[3]++;
- if (s->facilities & FACIL_DOCK) npi->num_station[4]++;
- }
- }
-
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- // Register local player (if not dedicated)
- if (ci != NULL && IsValidPlayer(ci->client_playas))
- ttd_strlcpy(_network_player_info[ci->client_playas].players, ci->client_name, sizeof(_network_player_info[0].players));
-
- FOR_ALL_CLIENTS(cs) {
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- ci = DEREF_CLIENT_INFO(cs);
- if (ci != NULL && IsValidPlayer(ci->client_playas)) {
- if (strlen(_network_player_info[ci->client_playas].players) != 0)
- ttd_strlcat(_network_player_info[ci->client_playas].players, ", ", lengthof(_network_player_info[0].players));
-
- ttd_strlcat(_network_player_info[ci->client_playas].players, client_name, lengthof(_network_player_info[0].players));
- }
- }
-}
-
-// Send a packet to all clients with updated info about this client_index
-void NetworkUpdateClientInfo(uint16 client_index)
-{
- NetworkClientState *cs;
- NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
-
- if (ci == NULL) return;
-
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, ci);
- }
-}
-
-/* Check if we want to restart the map */
-static void NetworkCheckRestartMap(void)
-{
- if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
- DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
-
- StartNewGameWithoutGUI(GENERATE_NEW_SEED);
- }
-}
-
-/* Check if the server has autoclean_companies activated
- Two things happen:
- 1) If a company is not protected, it is closed after 1 year (for example)
- 2) If a company is protected, protection is disabled after 3 years (for example)
- (and item 1. happens a year later) */
-static void NetworkAutoCleanCompanies(void)
-{
- const NetworkClientState *cs;
- const NetworkClientInfo *ci;
- const Player *p;
- bool clients_in_company[MAX_PLAYERS];
-
- if (!_network_autoclean_companies) return;
-
- memset(clients_in_company, 0, sizeof(clients_in_company));
-
- /* Detect the active companies */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
- }
-
- if (!_network_dedicated) {
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
- }
-
- /* Go through all the comapnies */
- FOR_ALL_PLAYERS(p) {
- /* Skip the non-active once */
- if (!p->is_active || p->is_ai) continue;
-
- if (!clients_in_company[p->index]) {
- /* The company is empty for one month more */
- _network_player_info[p->index].months_empty++;
-
- /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
- if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
- /* Shut the company down */
- DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
- IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1);
- }
- /* Is the compnay empty for autoclean_protected-months, and there is a protection? */
- if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
- /* Unprotect the company */
- _network_player_info[p->index].password[0] = '\0';
- IConsolePrintF(_icolour_def, "Auto-removed protection from company #%d", p->index+1);
- _network_player_info[p->index].months_empty = 0;
- }
- } else {
- /* It is not empty, reset the date */
- _network_player_info[p->index].months_empty = 0;
- }
- }
-}
-
-// This function changes new_name to a name that is unique (by adding #1 ...)
-// and it returns true if that succeeded.
-bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
-{
- NetworkClientState *new_cs;
- bool found_name = false;
- byte number = 0;
- char original_name[NETWORK_CLIENT_NAME_LENGTH];
-
- // We use NETWORK_CLIENT_NAME_LENGTH in here, because new_name is really a pointer
- ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
-
- while (!found_name) {
- const NetworkClientInfo *ci;
-
- found_name = true;
- FOR_ALL_CLIENTS(new_cs) {
- ci = DEREF_CLIENT_INFO(new_cs);
- if (strcmp(ci->client_name, new_name) == 0) {
- // Name already in use
- found_name = false;
- break;
- }
- }
- // Check if it is the same as the server-name
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (ci != NULL) {
- if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
- }
-
- if (!found_name) {
- // Try a new name (<name> #1, <name> #2, and so on)
-
- // Stop if we tried for more than 50 times..
- if (number++ > 50) break;
- snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
- }
- }
-
- return found_name;
-}
-
-// Reads a packet from the stream
-bool NetworkServer_ReadPackets(NetworkClientState *cs)
-{
- Packet *p;
- NetworkRecvStatus res;
- while ((p = NetworkRecv_Packet(cs, &res)) != NULL) {
- byte type = NetworkRecv_uint8(cs, p);
- if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->has_quit) {
- _network_server_packet[type](cs, p);
- } else {
- DEBUG(net, 0, "[server] received invalid packet type %d", type);
- }
- free(p);
- }
-
- return true;
-}
-
-// Handle the local command-queue
-static void NetworkHandleCommandQueue(NetworkClientState* cs)
-{
- CommandPacket *cp;
-
- while ( (cp = cs->command_queue) != NULL) {
- SEND_COMMAND(PACKET_SERVER_COMMAND)(cs, cp);
-
- cs->command_queue = cp->next;
- free(cp);
- }
-}
-
-// This is called every tick if this is a _network_server
-void NetworkServer_Tick(bool send_frame)
-{
- NetworkClientState *cs;
-#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
- bool send_sync = false;
-#endif
-
-#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
- if (_frame_counter >= _last_sync_frame + _network_sync_freq) {
- _last_sync_frame = _frame_counter;
- send_sync = true;
- }
-#endif
-
- // Now we are done with the frame, inform the clients that they can
- // do their frame!
- FOR_ALL_CLIENTS(cs) {
- // Check if the speed of the client is what we can expect from a client
- if (cs->status == STATUS_ACTIVE) {
- // 1 lag-point per day
- int lag = NetworkCalculateLag(cs) / DAY_TICKS;
- if (lag > 0) {
- if (lag > 3) {
- // Client did still not report in after 4 game-day, drop him
- // (that is, the 3 of above, + 1 before any lag is counted)
- IConsolePrintF(_icolour_err,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
- NetworkCloseClient(cs);
- continue;
- }
-
- // Report once per time we detect the lag
- if (cs->lag_test == 0) {
- IConsolePrintF(_icolour_warn,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
- cs->lag_test = 1;
- }
- } else {
- cs->lag_test = 0;
- }
- } else if (cs->status == STATUS_PRE_ACTIVE) {
- int lag = NetworkCalculateLag(cs);
- if (lag > _network_max_join_time) {
- IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
- NetworkCloseClient(cs);
- }
- }
-
- if (cs->status >= STATUS_PRE_ACTIVE) {
- // Check if we can send command, and if we have anything in the queue
- NetworkHandleCommandQueue(cs);
-
- // Send an updated _frame_counter_max to the client
- if (send_frame) SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
-
-#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
- // Send a sync-check packet
- if (send_sync) SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
-#endif
- }
- }
-
- /* See if we need to advertise */
- NetworkUDPAdvertise();
-}
-
-void NetworkServerYearlyLoop(void)
-{
- NetworkCheckRestartMap();
-}
-
-void NetworkServerMonthlyLoop(void)
-{
- NetworkAutoCleanCompanies();
-}
-
-#endif /* ENABLE_NETWORK */
--- a/network_server.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_SERVER_H
-#define NETWORK_SERVER_H
-
-#ifdef ENABLE_NETWORK
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP);
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, uint16 client_index, NetworkErrorCode errorno);
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error);
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN);
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command);
-
-bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
-void NetworkServer_HandleChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
-
-bool NetworkServer_ReadPackets(NetworkClientState *cs);
-void NetworkServer_Tick(bool send_frame);
-void NetworkServerMonthlyLoop(void);
-void NetworkServerYearlyLoop(void);
-
-static inline const char* GetPlayerIP(const NetworkClientInfo* ci)
-{
- struct in_addr addr;
-
- addr.s_addr = ci->client_ip;
- return inet_ntoa(addr);
-}
-
-#else /* ENABLE_NETWORK */
-/* Network function stubs when networking is disabled */
-
-static inline void NetworkServerMonthlyLoop(void) {}
-static inline void NetworkServerYearlyLoop(void) {}
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_SERVER_H */
--- a/network_udp.c Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,892 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "stdafx.h"
-#include "debug.h"
-#include "string.h"
-#include "network_data.h"
-#include "date.h"
-#include "map.h"
-#include "network_gamelist.h"
-#include "network_udp.h"
-#include "variables.h"
-#include "newgrf_config.h"
-
-//
-// This file handles all the LAN-stuff
-// Stuff like:
-// - UDP search over the network
-//
-
-typedef enum {
- PACKET_UDP_CLIENT_FIND_SERVER,
- PACKET_UDP_SERVER_RESPONSE,
- PACKET_UDP_CLIENT_DETAIL_INFO,
- PACKET_UDP_SERVER_DETAIL_INFO, // Is not used in OpenTTD itself, only for external querying
- PACKET_UDP_SERVER_REGISTER, // Packet to register itself to the master server
- PACKET_UDP_MASTER_ACK_REGISTER, // Packet indicating registration has succedeed
- PACKET_UDP_CLIENT_GET_LIST, // Request for serverlist from master server
- PACKET_UDP_MASTER_RESPONSE_LIST, // Response from master server with server ip's + port's
- PACKET_UDP_SERVER_UNREGISTER, // Request to be removed from the server-list
- PACKET_UDP_CLIENT_GET_NEWGRFS, // Requests the name for a list of GRFs (GRF_ID and MD5)
- PACKET_UDP_SERVER_NEWGRFS, // Sends the list of NewGRF's requested.
- PACKET_UDP_END
-} PacketUDPType;
-
-enum {
- ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes)
- ADVERTISE_RETRY_INTERVAL = 300, // readvertise when no response after this many ticks (9 seconds)
- ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries
-};
-
-#define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, struct sockaddr_in *client_addr)
-static void NetworkSendUDP_Packet(SOCKET udp, Packet* p, struct sockaddr_in* recv);
-
-static NetworkClientState _udp_cs;
-
-/**
- * Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
- * @param p the packet to write the data to
- * @param c the configuration to write the GRF ID and MD5 checksum from
- */
-static void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c)
-{
- uint j;
- NetworkSend_uint32(p, c->grfid);
- for (j = 0; j < sizeof(c->md5sum); j++) {
- NetworkSend_uint8 (p, c->md5sum[j]);
- }
-}
-
-/**
- * Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
- * @param p the packet to read the data from
- * @param c the configuration to write the GRF ID and MD5 checksum to
- */
-static void NetworkRecv_GRFIdentifier(Packet *p, GRFConfig *c)
-{
- uint j;
- c->grfid = NetworkRecv_uint32(&_udp_cs, p);
- for (j = 0; j < sizeof(c->md5sum); j++) {
- c->md5sum[j] = NetworkRecv_uint8(&_udp_cs, p);
- }
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER)
-{
- Packet *packet;
- // Just a fail-safe.. should never happen
- if (!_network_udp_server)
- return;
-
- packet = NetworkSend_Init(PACKET_UDP_SERVER_RESPONSE);
-
- // Update some game_info
- _network_game_info.game_date = _date;
- _network_game_info.map_width = MapSizeX();
- _network_game_info.map_height = MapSizeY();
- _network_game_info.map_set = _opt.landscape;
-
- NetworkSend_uint8 (packet, NETWORK_GAME_INFO_VERSION);
-
- /* NETWORK_GAME_INFO_VERSION = 4 */
- {
- /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
- * the GRFs that are needed, i.e. the ones that the server has
- * selected in the NewGRF GUI and not the ones that are used due
- * to the fact that they are in [newgrf-static] in openttd.cfg */
- const GRFConfig *c;
- uint i = 0;
-
- /* Count number of GRFs to send information about */
- for (c = _grfconfig; c != NULL; c = c->next) {
- if (!HASBIT(c->flags, GCF_STATIC)) i++;
- }
- NetworkSend_uint8 (packet, i); // Send number of GRFs
-
- /* Send actual GRF Identifications */
- for (c = _grfconfig; c != NULL; c = c->next) {
- if (!HASBIT(c->flags, GCF_STATIC)) NetworkSend_GRFIdentifier(packet, c);
- }
- }
-
- /* NETWORK_GAME_INFO_VERSION = 3 */
- NetworkSend_uint32(packet, _network_game_info.game_date);
- NetworkSend_uint32(packet, _network_game_info.start_date);
-
- /* NETWORK_GAME_INFO_VERSION = 2 */
- NetworkSend_uint8 (packet, _network_game_info.companies_max);
- NetworkSend_uint8 (packet, ActivePlayerCount());
- NetworkSend_uint8 (packet, _network_game_info.spectators_max);
-
- /* NETWORK_GAME_INFO_VERSION = 1 */
- NetworkSend_string(packet, _network_game_info.server_name);
- NetworkSend_string(packet, _network_game_info.server_revision);
- NetworkSend_uint8 (packet, _network_game_info.server_lang);
- NetworkSend_uint8 (packet, _network_game_info.use_password);
- NetworkSend_uint8 (packet, _network_game_info.clients_max);
- NetworkSend_uint8 (packet, _network_game_info.clients_on);
- NetworkSend_uint8 (packet, NetworkSpectatorCount());
- NetworkSend_string(packet, _network_game_info.map_name);
- NetworkSend_uint16(packet, _network_game_info.map_width);
- NetworkSend_uint16(packet, _network_game_info.map_height);
- NetworkSend_uint8 (packet, _network_game_info.map_set);
- NetworkSend_uint8 (packet, _network_game_info.dedicated);
-
- // Let the client know that we are here
- NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
-
- free(packet);
-
- DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr));
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE)
-{
- extern const char _openttd_revision[];
- NetworkGameList *item;
- byte game_info_version;
-
- // Just a fail-safe.. should never happen
- if (_network_udp_server)
- return;
-
- game_info_version = NetworkRecv_uint8(&_udp_cs, p);
-
- if (_udp_cs.has_quit) return;
-
- DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
-
- // Find next item
- item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
-
- item->info.compatible = true;
- /* Please observer the order. In the order in which packets are sent
- * they are to be received */
- switch (game_info_version) {
- case 4: {
- GRFConfig *c, **dst = &item->info.grfconfig;
- const GRFConfig *f;
- uint i;
- uint num_grfs = NetworkRecv_uint8(&_udp_cs, p);
-
- for (i = 0; i < num_grfs; i++) {
- c = calloc(1, sizeof(*c));
- NetworkRecv_GRFIdentifier(p, c);
-
- /* Find the matching GRF file */
- f = FindGRFConfig(c->grfid, c->md5sum);
- if (f == NULL) {
- /* Don't know the GRF, so mark game incompatible and the (possibly)
- * already resolved name for this GRF (another server has sent the
- * name of the GRF already */
- item->info.compatible = false;
- c->name = FindUnknownGRFName(c->grfid, c->md5sum, true);
- SETBIT(c->flags, GCF_NOT_FOUND);
- } else {
- c->filename = f->filename;
- c->name = f->name;
- c->info = f->info;
- }
- SETBIT(c->flags, GCF_COPY);
-
- /* Append GRFConfig to the list */
- *dst = c;
- dst = &c->next;
- }
- } /* Fallthrough */
- case 3:
- item->info.game_date = NetworkRecv_uint32(&_udp_cs, p);
- item->info.start_date = NetworkRecv_uint32(&_udp_cs, p);
- /* Fallthrough */
- case 2:
- item->info.companies_max = NetworkRecv_uint8(&_udp_cs, p);
- item->info.companies_on = NetworkRecv_uint8(&_udp_cs, p);
- item->info.spectators_max = NetworkRecv_uint8(&_udp_cs, p);
- /* Fallthrough */
- case 1:
- NetworkRecv_string(&_udp_cs, p, item->info.server_name, sizeof(item->info.server_name));
- NetworkRecv_string(&_udp_cs, p, item->info.server_revision, sizeof(item->info.server_revision));
- item->info.server_lang = NetworkRecv_uint8(&_udp_cs, p);
- item->info.use_password = NetworkRecv_uint8(&_udp_cs, p);
- item->info.clients_max = NetworkRecv_uint8(&_udp_cs, p);
- item->info.clients_on = NetworkRecv_uint8(&_udp_cs, p);
- item->info.spectators_on = NetworkRecv_uint8(&_udp_cs, p);
- if (game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
- item->info.game_date = NetworkRecv_uint16(&_udp_cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
- item->info.start_date = NetworkRecv_uint16(&_udp_cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
- }
- NetworkRecv_string(&_udp_cs, p, item->info.map_name, sizeof(item->info.map_name));
- item->info.map_width = NetworkRecv_uint16(&_udp_cs, p);
- item->info.map_height = NetworkRecv_uint16(&_udp_cs, p);
- item->info.map_set = NetworkRecv_uint8(&_udp_cs, p);
- item->info.dedicated = NetworkRecv_uint8(&_udp_cs, p);
-
- if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
- if (item->info.map_set >= NUM_LANDSCAPE ) item->info.map_set = 0;
-
- if (item->info.hostname[0] == '\0')
- snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
-
- /* Check if we are allowed on this server based on the revision-match */
- item->info.version_compatible =
- strcmp(item->info.server_revision, _openttd_revision) == 0 ||
- strcmp(item->info.server_revision, NOREV_STRING) == 0;
- item->info.compatible &= item->info.version_compatible; // Already contains match for GRFs
- break;
- }
-
- {
- /* Checks whether there needs to be a request for names of GRFs and makes
- * the request if necessary. GRFs that need to be requested are the GRFs
- * that do not exist on the clients system and we do not have the name
- * resolved of, i.e. the name is still UNKNOWN_GRF_NAME_PLACEHOLDER.
- * The in_request array and in_request_count are used so there is no need
- * to do a second loop over the GRF list, which can be relatively expensive
- * due to the string comparisons. */
- const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT];
- const GRFConfig *c;
- uint in_request_count = 0;
- struct sockaddr_in out_addr;
-
- for (c = item->info.grfconfig; c != NULL; c = c->next) {
- if (!HASBIT(c->flags, GCF_NOT_FOUND) || strcmp(c->name, UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue;
- in_request[in_request_count] = c;
- in_request_count++;
- }
-
- if (in_request_count > 0) {
- /* There are 'unknown' GRFs, now send a request for them */
- uint i;
- Packet *packet = NetworkSend_Init(PACKET_UDP_CLIENT_GET_NEWGRFS);
-
- NetworkSend_uint8 (packet, in_request_count);
- for (i = 0; i < in_request_count; i++) {
- NetworkSend_GRFIdentifier(packet, in_request[i]);
- }
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(item->port);
- out_addr.sin_addr.s_addr = item->ip;
- NetworkSendUDP_Packet(_udp_client_socket, packet, &out_addr);
- free(packet);
- }
- }
-
- item->online = true;
-
- UpdateNetworkGameWindow(false);
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO)
-{
- NetworkClientState *cs;
- NetworkClientInfo *ci;
- Packet *packet;
- Player *player;
- byte current = 0;
- int i;
-
- // Just a fail-safe.. should never happen
- if (!_network_udp_server) return;
-
- packet = NetworkSend_Init(PACKET_UDP_SERVER_DETAIL_INFO);
-
- /* Send the amount of active companies */
- NetworkSend_uint8 (packet, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (packet, ActivePlayerCount());
-
- /* Fetch the latest version of everything */
- NetworkPopulateCompanyInfo();
-
- /* Go through all the players */
- FOR_ALL_PLAYERS(player) {
- /* Skip non-active players */
- if (!player->is_active) continue;
-
- current++;
-
- /* Send the information */
- NetworkSend_uint8(packet, current);
-
- NetworkSend_string(packet, _network_player_info[player->index].company_name);
- NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year);
- NetworkSend_uint64(packet, _network_player_info[player->index].company_value);
- NetworkSend_uint64(packet, _network_player_info[player->index].money);
- NetworkSend_uint64(packet, _network_player_info[player->index].income);
- NetworkSend_uint16(packet, _network_player_info[player->index].performance);
-
- /* Send 1 if there is a passord for the company else send 0 */
- if (_network_player_info[player->index].password[0] != '\0') {
- NetworkSend_uint8(packet, 1);
- } else {
- NetworkSend_uint8(packet, 0);
- }
-
- for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
- NetworkSend_uint16(packet, _network_player_info[player->index].num_vehicle[i]);
-
- for (i = 0; i < NETWORK_STATION_TYPES; i++)
- NetworkSend_uint16(packet, _network_player_info[player->index].num_station[i]);
-
- /* Find the clients that are connected to this player */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (ci->client_playas == player->index) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
- }
- /* Also check for the server itself */
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (ci->client_playas == player->index) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
-
- /* Indicates end of client list */
- NetworkSend_uint8(packet, 0);
- }
-
- /* And check if we have any spectators */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (!IsValidPlayer(ci->client_playas)) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
- }
-
- /* Also check for the server itself */
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (!IsValidPlayer(ci->client_playas)) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
-
- /* Indicates end of client list */
- NetworkSend_uint8(packet, 0);
-
- NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
-
- free(packet);
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST)
-{
- int i;
- struct in_addr ip;
- uint16 port;
- uint8 ver;
-
- /* packet begins with the protocol version (uint8)
- * then an uint16 which indicates how many
- * ip:port pairs are in this packet, after that
- * an uint32 (ip) and an uint16 (port) for each pair
- */
-
- ver = NetworkRecv_uint8(&_udp_cs, p);
-
- if (_udp_cs.has_quit) return;
-
- if (ver == 1) {
- for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) {
- ip.s_addr = TO_LE32(NetworkRecv_uint32(&_udp_cs, p));
- port = NetworkRecv_uint16(&_udp_cs, p);
- NetworkUDPQueryServer(inet_ntoa(ip), port);
- }
- }
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER)
-{
- _network_advertise_retries = 0;
- DEBUG(net, 2, "[udp] advertising on master server successfull");
-
- /* We are advertised, but we don't want to! */
- if (!_network_advertise) NetworkUDPRemoveAdvertise();
-}
-
-/**
- * A client has requested the names of some NewGRFs.
- *
- * Replying this can be tricky as we have a limit of SEND_MTU bytes
- * in the reply packet and we can send up to 100 bytes per NewGRF
- * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name).
- * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it
- * could be that a packet overflows. To stop this we only reply
- * with the first N NewGRFs so that if the first N + 1 NewGRFs
- * would be sent, the packet overflows.
- * in_reply and in_reply_count are used to keep a list of GRFs to
- * send in the reply.
- */
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS)
-{
- uint8 num_grfs;
- uint i;
-
- const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
- Packet *packet;
- uint8 in_reply_count = 0;
- uint packet_len = 0;
-
- /* Just a fail-safe.. should never happen */
- if (_udp_cs.has_quit) return;
-
- DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
-
- num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
- if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
-
- for (i = 0; i < num_grfs; i++) {
- GRFConfig c;
- const GRFConfig *f;
-
- NetworkRecv_GRFIdentifier(p, &c);
-
- /* Find the matching GRF file */
- f = FindGRFConfig(c.grfid, c.md5sum);
- if (f == NULL) continue; // The GRF is unknown to this server
-
- /* If the reply might exceed the size of the packet, only reply
- * the current list and do not send the other data.
- * The name could be an empty string, if so take the filename. */
- packet_len += sizeof(c.grfid) + sizeof(c.md5sum) +
- min(strlen((f->name != NULL && strlen(f->name) > 0) ? f->name : f->filename) + 1, NETWORK_GRF_NAME_LENGTH);
- if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply
- break;
- }
- in_reply[in_reply_count] = f;
- in_reply_count++;
- }
-
- if (in_reply_count == 0) return;
-
- packet = NetworkSend_Init(PACKET_UDP_SERVER_NEWGRFS);
- NetworkSend_uint8 (packet, in_reply_count);
- for (i = 0; i < in_reply_count; i++) {
- char name[NETWORK_GRF_NAME_LENGTH];
-
- /* The name could be an empty string, if so take the filename */
- ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ?
- in_reply[i]->name : in_reply[i]->filename, sizeof(name));
- NetworkSend_GRFIdentifier(packet, in_reply[i]);
- NetworkSend_string(packet, name);
- }
-
- NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
- free(packet);
-}
-
-/** The return of the client's request of the names of some NewGRFs */
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS)
-{
- uint8 num_grfs;
- uint i;
-
- /* Just a fail-safe.. should never happen */
- if (_udp_cs.has_quit) return;
-
- DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
-
- num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
- if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
-
- for (i = 0; i < num_grfs; i++) {
- char *unknown_name;
- char name[NETWORK_GRF_NAME_LENGTH];
- GRFConfig c;
-
- NetworkRecv_GRFIdentifier(p, &c);
- NetworkRecv_string(&_udp_cs, p, name, sizeof(name));
-
- /* An empty name is not possible under normal circumstances
- * and causes problems when showing the NewGRF list. */
- if (strlen(name) == 0) continue;
-
- /* Finds the fake GRFConfig for the just read GRF ID and MD5sum tuple.
- * If it exists and not resolved yet, then name of the fake GRF is
- * overwritten with the name from the reply. */
- unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
- if (unknown_name != NULL && strcmp(unknown_name, UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
- ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH);
- }
- }
-}
-
-
-// The layout for the receive-functions by UDP
-typedef void NetworkUDPPacket(Packet *p, struct sockaddr_in *client_addr);
-
-static NetworkUDPPacket* const _network_udp_packet[] = {
- RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER),
- RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE),
- RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO),
- NULL,
- NULL,
- RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER),
- NULL,
- RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST),
- NULL,
- RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS),
- RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS),
-};
-
-
-// If this fails, check the array above with network_data.h
-assert_compile(lengthof(_network_udp_packet) == PACKET_UDP_END);
-
-
-static void NetworkHandleUDPPacket(Packet* p, struct sockaddr_in* client_addr)
-{
- byte type;
-
- /* Fake a client, so we can see when there is an illegal packet */
- _udp_cs.socket = INVALID_SOCKET;
- _udp_cs.has_quit = false;
-
- type = NetworkRecv_uint8(&_udp_cs, p);
-
- if (type < PACKET_UDP_END && _network_udp_packet[type] != NULL && !_udp_cs.has_quit) {
- _network_udp_packet[type](p, client_addr);
- } else {
- if (!_udp_cs.has_quit) {
- DEBUG(net, 0, "[udp] received invalid packet type %d", type);
- } else {
- DEBUG(net, 0, "[udp] received illegal packet");
- }
- }
-}
-
-
-// Send a packet over UDP
-static void NetworkSendUDP_Packet(SOCKET udp, Packet* p, struct sockaddr_in* recv)
-{
- int res;
-
- // Put the length in the buffer
- p->buffer[0] = p->size & 0xFF;
- p->buffer[1] = p->size >> 8;
-
- // Send the buffer
- res = sendto(udp, p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv));
-
- // Check for any errors, but ignore it otherwise
- if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR());
-}
-
-// Start UDP listener
-bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast)
-{
- struct sockaddr_in sin;
-
- // Make sure socket is closed
- closesocket(*udp);
-
- *udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (*udp == INVALID_SOCKET) {
- DEBUG(net, 0, "[udp] failed to start UDP listener");
- return false;
- }
-
- // set nonblocking mode for socket
- {
- unsigned long blocking = 1;
-#ifndef BEOS_NET_SERVER
- ioctlsocket(*udp, FIONBIO, &blocking);
-#else
- setsockopt(*udp, SOL_SOCKET, SO_NONBLOCK, &blocking, NULL);
-#endif
- }
-
- sin.sin_family = AF_INET;
- // Listen on all IPs
- sin.sin_addr.s_addr = host;
- sin.sin_port = htons(port);
-
- if (bind(*udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
- DEBUG(net, 0, "[udp] bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port);
- return false;
- }
-
- if (broadcast) {
- /* Enable broadcast */
- unsigned long val = 1;
-#ifndef BEOS_NET_SERVER // will work around this, some day; maybe.
- setsockopt(*udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val));
-#endif
- }
-
- DEBUG(net, 1, "[udp] listening on port %s:%d", inet_ntoa(*(struct in_addr *)&host), port);
-
- return true;
-}
-
-// Close UDP connection
-void NetworkUDPClose(void)
-{
- DEBUG(net, 1, "[udp] closed listeners");
-
- if (_network_udp_server) {
- if (_udp_server_socket != INVALID_SOCKET) {
- closesocket(_udp_server_socket);
- _udp_server_socket = INVALID_SOCKET;
- }
-
- if (_udp_master_socket != INVALID_SOCKET) {
- closesocket(_udp_master_socket);
- _udp_master_socket = INVALID_SOCKET;
- }
-
- _network_udp_server = false;
- _network_udp_broadcast = 0;
- } else {
- if (_udp_client_socket != INVALID_SOCKET) {
- closesocket(_udp_client_socket);
- _udp_client_socket = INVALID_SOCKET;
- }
- _network_udp_broadcast = 0;
- }
-}
-
-// Receive something on UDP level
-void NetworkUDPReceive(SOCKET udp)
-{
- struct sockaddr_in client_addr;
- socklen_t client_len;
- int nbytes;
- static Packet *p = NULL;
- int packet_len;
-
- // If p is NULL, malloc him.. this prevents unneeded mallocs
- if (p == NULL) p = malloc(sizeof(*p));
-
- packet_len = sizeof(p->buffer);
- client_len = sizeof(client_addr);
-
- // Try to receive anything
- nbytes = recvfrom(udp, p->buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len);
-
- // We got some bytes.. just asume we receive the whole packet
- if (nbytes > 0) {
- // Get the size of the buffer
- p->size = (uint16)p->buffer[0];
- p->size += (uint16)p->buffer[1] << 8;
- // Put the position on the right place
- p->pos = 2;
- p->next = NULL;
-
- // Handle the packet
- NetworkHandleUDPPacket(p, &client_addr);
-
- // Free the packet
- free(p);
- p = NULL;
- }
-}
-
-// Broadcast to all ips
-static void NetworkUDPBroadCast(SOCKET udp)
-{
- Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
- uint i;
-
- for (i = 0; _broadcast_list[i] != 0; i++) {
- struct sockaddr_in out_addr;
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(_network_server_port);
- out_addr.sin_addr.s_addr = _broadcast_list[i];
-
- DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
-
- NetworkSendUDP_Packet(udp, p, &out_addr);
- }
-
- free(p);
-}
-
-
-// Request the the server-list from the master server
-void NetworkUDPQueryMasterServer(void)
-{
- struct sockaddr_in out_addr;
- Packet *p;
-
- if (_udp_client_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
- return;
-
- p = NetworkSend_Init(PACKET_UDP_CLIENT_GET_LIST);
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
- out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
-
- // packet only contains protocol version
- NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
-
- NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
-
- DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr),ntohs(out_addr.sin_port));
-
- free(p);
-}
-
-// Find all servers
-void NetworkUDPSearchGame(void)
-{
- // We are still searching..
- if (_network_udp_broadcast > 0) return;
-
- // No UDP-socket yet..
- if (_udp_client_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
- return;
-
- DEBUG(net, 0, "[udp] searching server");
-
- NetworkUDPBroadCast(_udp_client_socket);
- _network_udp_broadcast = 300; // Stay searching for 300 ticks
-}
-
-NetworkGameList *NetworkUDPQueryServer(const char* host, unsigned short port)
-{
- struct sockaddr_in out_addr;
- Packet *p;
- NetworkGameList *item;
-
- // No UDP-socket yet..
- if (_udp_client_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
- return NULL;
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(port);
- out_addr.sin_addr.s_addr = NetworkResolveHost(host);
-
- // Clear item in gamelist
- item = NetworkGameListAddItem(inet_addr(inet_ntoa(out_addr.sin_addr)), ntohs(out_addr.sin_port));
- memset(&item->info, 0, sizeof(item->info));
- ttd_strlcpy(item->info.server_name, host, lengthof(item->info.server_name));
- ttd_strlcpy(item->info.hostname, host, lengthof(item->info.hostname));
- item->online = false;
-
- // Init the packet
- p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
-
- NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
-
- free(p);
-
- UpdateNetworkGameWindow(false);
- return item;
-}
-
-/* Remove our advertise from the master-server */
-void NetworkUDPRemoveAdvertise(void)
-{
- struct sockaddr_in out_addr;
- Packet *p;
-
- /* Check if we are advertising */
- if (!_networking || !_network_server || !_network_udp_server) return;
-
- /* check for socket */
- if (_udp_master_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
- return;
-
- DEBUG(net, 1, "[udp] removing advertise from master server");
-
- /* Find somewhere to send */
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
- out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
-
- /* Send the packet */
- p = NetworkSend_Init(PACKET_UDP_SERVER_UNREGISTER);
- /* Packet is: Version, server_port */
- NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
- NetworkSend_uint16(p, _network_server_port);
- NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
-
- free(p);
-}
-
-/* Register us to the master server
- This function checks if it needs to send an advertise */
-void NetworkUDPAdvertise(void)
-{
- struct sockaddr_in out_addr;
- Packet *p;
-
- /* Check if we should send an advertise */
- if (!_networking || !_network_server || !_network_udp_server || !_network_advertise)
- return;
-
- /* check for socket */
- if (_udp_master_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
- return;
-
- if (_network_need_advertise) {
- _network_need_advertise = false;
- _network_advertise_retries = ADVERTISE_RETRY_TIMES;
- } else {
- /* Only send once every ADVERTISE_NORMAL_INTERVAL ticks */
- if (_network_advertise_retries == 0) {
- if ((_network_last_advertise_frame + ADVERTISE_NORMAL_INTERVAL) > _frame_counter)
- return;
- _network_advertise_retries = ADVERTISE_RETRY_TIMES;
- }
-
- if ((_network_last_advertise_frame + ADVERTISE_RETRY_INTERVAL) > _frame_counter)
- return;
- }
-
- _network_advertise_retries--;
- _network_last_advertise_frame = _frame_counter;
-
- /* Find somewhere to send */
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
- out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
-
- DEBUG(net, 1, "[udp] advertising to master server");
-
- /* Send the packet */
- p = NetworkSend_Init(PACKET_UDP_SERVER_REGISTER);
- /* Packet is: WELCOME_MESSAGE, Version, server_port */
- NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
- NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
- NetworkSend_uint16(p, _network_server_port);
- NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
-
- free(p);
-}
-
-void NetworkUDPInitialize(void)
-{
- _udp_client_socket = INVALID_SOCKET;
- _udp_server_socket = INVALID_SOCKET;
- _udp_master_socket = INVALID_SOCKET;
-
- _network_udp_server = false;
- _network_udp_broadcast = 0;
-}
-
-#endif /* ENABLE_NETWORK */
--- a/network_udp.h Tue Jan 02 18:40:37 2007 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_UDP_H
-#define NETWORK_UDP_H
-
-#ifdef ENABLE_NETWORK
-
-void NetworkUDPInitialize(void);
-bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast);
-void NetworkUDPReceive(SOCKET udp);
-void NetworkUDPSearchGame(void);
-void NetworkUDPQueryMasterServer(void);
-NetworkGameList *NetworkUDPQueryServer(const char* host, unsigned short port);
-void NetworkUDPAdvertise(void);
-void NetworkUDPRemoveAdvertise(void);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_UDP_H */
--- a/newgrf_config.c Tue Jan 02 18:40:37 2007 +0000
+++ b/newgrf_config.c Wed Jan 03 08:32:17 2007 +0000
@@ -9,7 +9,7 @@
#include "string.h"
#include "saveload.h"
#include "md5.h"
-#include "network_data.h"
+#include "network/network_data.h"
#include "newgrf.h"
#include "newgrf_config.h"
--- a/newgrf_spritegroup.c Tue Jan 02 18:40:37 2007 +0000
+++ b/newgrf_spritegroup.c Wed Jan 03 08:32:17 2007 +0000
@@ -11,7 +11,7 @@
static void SpriteGroupPoolCleanBlock(uint start_item, uint end_item);
static uint _spritegroup_count = 0;
-STATIC_OLD_POOL(SpriteGroup, SpriteGroup, 4, 8000, NULL, SpriteGroupPoolCleanBlock)
+STATIC_OLD_POOL(SpriteGroup, SpriteGroup, 9, 250, NULL, SpriteGroupPoolCleanBlock)
static void DestroySpriteGroup(SpriteGroup *group)
{
--- a/npf.c Tue Jan 02 18:40:37 2007 +0000
+++ b/npf.c Wed Jan 03 08:32:17 2007 +0000
@@ -14,7 +14,7 @@
#include "tile.h"
#include "depot.h"
#include "tunnel_map.h"
-#include "network.h"
+#include "network/network.h"
#include "water_map.h"
static AyStar _npf_aystar;
--- a/oldloader.c Tue Jan 02 18:40:37 2007 +0000
+++ b/oldloader.c Wed Jan 03 08:32:17 2007 +0000
@@ -16,7 +16,7 @@
#include "signs.h"
#include "debug.h"
#include "depot.h"
-#include "network.h"
+#include "network/network.h"
#include "ai/ai.h"
#include "date.h"
--- a/openttd.c Tue Jan 02 18:40:37 2007 +0000
+++ b/openttd.c Wed Jan 03 08:32:17 2007 +0000
@@ -41,7 +41,7 @@
#include "airport.h"
#include "console.h"
#include "screenshot.h"
-#include "network.h"
+#include "network/network.h"
#include "signs.h"
#include "depot.h"
#include "waypoint.h"
--- a/openttd.vcproj Tue Jan 02 18:40:37 2007 +0000
+++ b/openttd.vcproj Wed Jan 03 08:32:17 2007 +0000
@@ -292,22 +292,31 @@
RelativePath=".\namegen.c">
</File>
<File
- RelativePath=".\network.c">
- </File>
- <File
- RelativePath=".\network_client.c">
+ RelativePath=".\network\core\packet.c">
</File>
<File
- RelativePath=".\network_data.c">
+ RelativePath=".\network\core\tcp.c">
</File>
<File
- RelativePath=".\network_gamelist.c">
+ RelativePath=".\network\core\udp.c">
</File>
<File
- RelativePath=".\network_server.c">
+ RelativePath=".\network\network.c">
</File>
<File
- RelativePath=".\network_udp.c">
+ RelativePath=".\network\network_client.c">
+ </File>
+ <File
+ RelativePath=".\network\network_data.c">
+ </File>
+ <File
+ RelativePath=".\network\network_gamelist.c">
+ </File>
+ <File
+ RelativePath=".\network\network_server.c">
+ </File>
+ <File
+ RelativePath=".\network\network_udp.c">
</File>
<File
RelativePath=".\newgrf.c">
@@ -542,22 +551,37 @@
RelativePath=".\music.h">
</File>
<File
- RelativePath=".\network.h">
- </File>
- <File
- RelativePath=".\network_client.h">
+ RelativePath=".\network\core\config.h">
</File>
<File
- RelativePath=".\network_core.h">
+ RelativePath=".\network\core\game.h">
</File>
<File
- RelativePath=".\network_data.h">
+ RelativePath=".\network\core\os_abstraction.h">
</File>
<File
- RelativePath=".\network_gamelist.h">
+ RelativePath=".\network\core\packet.h">
</File>
<File
- RelativePath=".\network_gui.h">
+ RelativePath=".\network\core\tcp.h">
+ </File>
+ <File
+ RelativePath=".\network\core\udp.h">
+ </File>
+ <File
+ RelativePath=".\network\network.h">
+ </File>
+ <File
+ RelativePath=".\network\network_client.h">
+ </File>
+ <File
+ RelativePath=".\network\network_data.h">
+ </File>
+ <File
+ RelativePath=".\network\network_gamelist.h">
+ </File>
+ <File
+ RelativePath=".\network\network_gui.h">
</File>
<File
RelativePath=".\network_server.h">
--- a/openttd_vs80.vcproj Tue Jan 02 18:40:37 2007 +0000
+++ b/openttd_vs80.vcproj Wed Jan 03 08:32:17 2007 +0000
@@ -653,27 +653,39 @@
>
</File>
<File
- RelativePath=".\network.c"
- >
- </File>
- <File
- RelativePath=".\network_client.c"
+ RelativePath=".\network\core\packet.c"
>
</File>
<File
- RelativePath=".\network_data.c"
+ RelativePath=".\network\core\tcp.c"
>
</File>
<File
- RelativePath=".\network_gamelist.c"
+ RelativePath=".\network\core\udp.c"
>
</File>
<File
- RelativePath=".\network_server.c"
+ RelativePath=".\network\network.c"
>
</File>
<File
- RelativePath=".\network_udp.c"
+ RelativePath=".\network\network_client.c"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_data.c"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_gamelist.c"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_server.c"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_udp.c"
>
</File>
<File
@@ -1040,35 +1052,55 @@
>
</File>
<File
- RelativePath=".\network.h"
- >
- </File>
- <File
- RelativePath=".\network_client.h"
- >
- </File>
- <File
- RelativePath=".\network_core.h"
+ RelativePath=".\networe\core\config.h"
>
</File>
<File
- RelativePath=".\network_data.h"
- >
- </File>
- <File
- RelativePath=".\network_gamelist.h"
+ RelativePath=".\network\core\game.h"
>
</File>
<File
- RelativePath=".\network_gui.h"
+ RelativePath=".\network\core\os_abstraction.h"
>
</File>
<File
- RelativePath=".\network_server.h"
+ RelativePath=".\network\core\packet.h"
>
</File>
<File
- RelativePath=".\network_udp.h"
+ RelativePath=".\network\core\tcp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\core\udp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_client.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_data.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_gamelist.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_gui.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_server.h"
+ >
+ </File>
+ <File
+ RelativePath=".\network\network_udp.h"
>
</File>
<File
--- a/player_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/player_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -13,13 +13,13 @@
#include "command.h"
#include "vehicle.h"
#include "economy.h"
-#include "network.h"
+#include "network/network.h"
#include "variables.h"
#include "train.h"
#include "date.h"
#include "newgrf.h"
-#include "network_data.h"
-#include "network_client.h"
+#include "network/network_data.h"
+#include "network/network_client.h"
static void DoShowPlayerFinances(PlayerID player, bool show_small, bool show_stickied);
--- a/players.c Tue Jan 02 18:40:37 2007 +0000
+++ b/players.c Wed Jan 03 08:32:17 2007 +0000
@@ -21,7 +21,7 @@
#include "saveload.h"
#include "command.h"
#include "sound.h"
-#include "network.h"
+#include "network/network.h"
#include "variables.h"
#include "engine.h"
#include "ai/ai.h"
--- a/saveload.c Tue Jan 02 18:40:37 2007 +0000
+++ b/saveload.c Wed Jan 03 08:32:17 2007 +0000
@@ -26,7 +26,7 @@
#include "town.h"
#include "player.h"
#include "saveload.h"
-#include "network.h"
+#include "network/network.h"
#include "variables.h"
#include <setjmp.h>
@@ -1042,7 +1042,6 @@
//********** START OF MEMORY CODE (in ram)****
//********************************************
-#include "network.h"
#include "table/strings.h"
#include "table/sprites.h"
#include "gfx.h"
--- a/settings.c Tue Jan 02 18:40:37 2007 +0000
+++ b/settings.c Wed Jan 03 08:32:17 2007 +0000
@@ -28,7 +28,7 @@
#include "sound.h"
#include "string.h"
#include "variables.h"
-#include "network.h"
+#include "network/network.h"
#include "settings.h"
#include "command.h"
#include "console.h"
--- a/settings_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/settings_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -15,7 +15,7 @@
#include "engine.h"
#include "screenshot.h"
#include "newgrf.h"
-#include "network.h"
+#include "network/network.h"
#include "town.h"
#include "variables.h"
#include "settings.h"
--- a/table/sprites.h Tue Jan 02 18:40:37 2007 +0000
+++ b/table/sprites.h Wed Jan 03 08:32:17 2007 +0000
@@ -1314,9 +1314,9 @@
* @see SpriteSetup */
enum SpriteMasks {
///Maximum number of sprites that can be loaded at a given time.
- MAX_SPRITES = (1 << SPRITE_WIDTH) - 1,
+ MAX_SPRITES = 1 << SPRITE_WIDTH,
///The mask to for the main sprite
- SPRITE_MASK = MAX_SPRITES,
+ SPRITE_MASK = MAX_SPRITES - 1,
///The mask for the auxiliary sprite (the one that takes care of recoloring)
PALETTE_SPRITE_MASK = ((1 << PALETTE_SPRITE_WIDTH) - 1) << PALETTE_SPRITE_START,
///Mask for the auxiliary sprites if it is locate in the LSBs
--- a/town_gui.c Tue Jan 02 18:40:37 2007 +0000
+++ b/town_gui.c Wed Jan 03 08:32:17 2007 +0000
@@ -14,7 +14,7 @@
#include "gui.h"
#include "command.h"
#include "player.h"
-#include "network.h"
+#include "network/network.h"
#include "variables.h"
static const Widget _town_authority_widgets[] = {
--- a/vehicle.c Tue Jan 02 18:40:37 2007 +0000
+++ b/vehicle.c Wed Jan 03 08:32:17 2007 +0000
@@ -30,7 +30,7 @@
#include "industry_map.h"
#include "station_map.h"
#include "water_map.h"
-#include "network.h"
+#include "network/network.h"
#include "yapf/yapf.h"
#include "date.h"
#include "newgrf_engine.h"
--- a/video/cocoa_v.m Tue Jan 02 18:40:37 2007 +0000
+++ b/video/cocoa_v.m Wed Jan 03 08:32:17 2007 +0000
@@ -54,7 +54,7 @@
#include "../macros.h"
#include "../sdl.h"
#include "../window.h"
-#include "../network.h"
+#include "../network/network.h"
#include "../variables.h"
#include "../os/macosx/splash.h"
--- a/video/dedicated_v.c Tue Jan 02 18:40:37 2007 +0000
+++ b/video/dedicated_v.c Wed Jan 03 08:32:17 2007 +0000
@@ -8,7 +8,7 @@
#include "../debug.h"
#include "../functions.h"
#include "../gfx.h"
-#include "../network.h"
+#include "../network/network.h"
#include "../window.h"
#include "../console.h"
#include "../variables.h"
--- a/video/sdl_v.c Tue Jan 02 18:40:37 2007 +0000
+++ b/video/sdl_v.c Wed Jan 03 08:32:17 2007 +0000
@@ -11,7 +11,7 @@
#include "../macros.h"
#include "../sdl.h"
#include "../window.h"
-#include "../network.h"
+#include "../network/network.h"
#include "../variables.h"
#include "sdl_v.h"
#include <SDL.h>
@@ -440,7 +440,9 @@
#if defined(_DEBUG)
if (_shift_pressed)
#else
- if (keys[SDLK_TAB])
+ /* Speedup when pressing tab, except when using ALT+TAB
+ * to switch to another application */
+ if (keys[SDLK_TAB] && (mod & KMOD_ALT) == 0)
#endif
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
--- a/video/win32_v.c Tue Jan 02 18:40:37 2007 +0000
+++ b/video/win32_v.c Wed Jan 03 08:32:17 2007 +0000
@@ -5,7 +5,7 @@
#include "../functions.h"
#include "../gfx.h"
#include "../macros.h"
-#include "../network.h"
+#include "../network/network.h"
#include "../variables.h"
#include "../win32.h"
#include "../window.h"