Update to 1.11.2

This commit is contained in:
dP
2021-05-03 22:10:57 +03:00
parent 5881c752f5
commit ac7d3eba75
103 changed files with 1631 additions and 942 deletions

View File

@@ -1,32 +1,23 @@
1.11.1 (2021-04-18) 1.11.2 (2021-05-03)
------------------------------------------------------------------------ ------------------------------------------------------------------------
Feature: Toggle to enable/disable vsync (#8997) Change: [Win32] Limit hardware accelerated video driver to OpenGL 3.2 or higher (#9077)
Feature: Volume controls in the Game Options window, and better defaults (#8943) Change: More improvements to the GUI at different scales (#9075, #9102, #9107, #9133, #9174, #9183)
Add: Hotkey to focus object and rail filters (#8908) Fix: Query windows could be partially drawn (#9184)
Add: Better plural support for Romanian (#8936) Fix #9113: Crash when removing an airport that exists in an aircraft's orders (#9182)
Change: Improve layout and spacing of several windows at different GUI scales (#9041, #9042, #9044, #9050) Fix #9117: [Fluidsynth] Hang when changing song (#9181)
Change: [Win32] Use user UI language setting for initial language selection (#8974) Fix: String validation could leave invalid UTF-8 encoded strings (#9096)
Change: Make effect volume scale more intuitively (#8945, #8950) Fix: [Network] Out-of-bounds memory access with modified servers sending too short password salts (#9176)
Change: Improve padding of Object & Rail station windows (#8929) Fix: Crash when extra viewport with zero height has sign in view (#9175)
Fix #6322: [Script] Crash when script allocates too much memory, now kills script instead (#9047) Fix #9147: Crash when taking screenshots (#9169)
Fix #7513: [Script] Crash on garbage collection with misbehaving script (#9040) Fix #6598: [Network] Prevent crashes when (re)joining network game by falling back to main menu first (#9163)
Fix #9028: [OpenGL] Crash when changing max sprite zoom level (#9032) Fix #9152: Screenshot success popup window was treated as an error (#9159)
Fix #8874: show a warning when a NewGRF scan is requested multiple times (#9022) Fix: Fast-forward stuttering when vsync is enabled (#9140)
Fix: Desync when GS unlocks railtype with wagon unlock (#9021) Fix: [Network, Win32] Network errors were handled badly (#9116)
Fix #9015: [Win32] Crash on running "pwd" command in the console (#9016) Fix: [Network] Savegame transfer could stall in rare cases (#9106)
Fix #9008: Validate starting year given on the command line (-t) (#9014) Fix #9097: [NewGRF] Cargo initial payment variable was being truncated (#9098)
Fix #8878: [Network] Slow DNS queries could block the server and disconnect clients (#9013) Fix: [NewGRF] Industry variable 66 and object variable 46 erroneously truncated the distance (#9088)
Fix: Improve validation of OpenGL video driver to avoid crashes (#9007) Fix: [NewGRF] Industry variables 65 and 66 ignored the parameter, and always used the north tile (#9088)
Fix: Credits scrolled too slowly with larger font sizes (#8994) Fix: Do not include regression test AI in bundle (#9068, #9164)
Fix #8977: Crash when altering max sprite resolution (#8993) Fix #9062: [Win32] Version in executable was not set to current release version (#9066, #9154)
Fix #8956: Industry disaster news messages showed the wrong location (#8992)
Fix: [Win32] Font glyphs of certain widths had broken rendering (#8990)
Fix #8930: [Win32] Duplicate text input issue for systems using IME (#8976)
Fix: [Network] Potential stale client entries in client list (#8959)
Fix: Graphical issues when dragging measurement tooltips (#8951)
Fix: [Fluidsynth] Use provided default soundfont if available (#8948, #8953)
Fix #8935: [macOS] Crash on save (#8944)
Fix #8922: Crash when selling shared vehicles with shared vehicle window open (#8926)
Fix: Compiling on armhf (Raspberry Pi) (#8924)

View File

@@ -143,7 +143,7 @@ jobs:
- name: Test - name: Test
run: | run: |
cd build cd build
ctest -j $(nproc) ctest -j $(nproc) --timeout 120
macos: macos:
name: Mac OS name: Mac OS
@@ -224,7 +224,7 @@ jobs:
- name: Test - name: Test
run: | run: |
cd build cd build
ctest -j $(sysctl -n hw.logicalcpu) ctest -j $(sysctl -n hw.logicalcpu) --timeout 120
windows: windows:
name: Windows name: Windows
@@ -314,4 +314,4 @@ jobs:
shell: bash shell: bash
run: | run: |
cd ${GITHUB_WORKSPACE}/build cd ${GITHUB_WORKSPACE}/build
ctest ctest --timeout 120

View File

@@ -1 +1 @@
1.11.1 20210418 0 0be22efffc3c14db08baf5e58c448b5d074f4427 1 1 2021 1.11.2 20210503 0 672f285218c6817784d86f737987b75db4bc78fc 1 1 2021

View File

@@ -1 +1 @@
2021-04-18 21:11 UTC 2021-05-03 18:41 UTC

View File

@@ -1 +1 @@
1.11.1 1.11.2

View File

@@ -4,7 +4,9 @@ if(NOT BINARY_NAME)
set(BINARY_NAME openttd) set(BINARY_NAME openttd)
endif() endif()
project(${BINARY_NAME}) project(${BINARY_NAME}
VERSION 1.11.2
)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-source builds not allowed. Please run \"cmake ..\" from the build directory. You may need to delete \"${CMAKE_SOURCE_DIR}/CMakeCache.txt\" first.") message(FATAL_ERROR "In-source builds not allowed. Please run \"cmake ..\" from the build directory. You may need to delete \"${CMAKE_SOURCE_DIR}/CMakeCache.txt\" first.")
@@ -72,6 +74,9 @@ add_custom_target(find_version
${CMAKE_COMMAND} ${CMAKE_COMMAND}
-DFIND_VERSION_BINARY_DIR=${CMAKE_BINARY_DIR}/generated -DFIND_VERSION_BINARY_DIR=${CMAKE_BINARY_DIR}/generated
-DCPACK_BINARY_DIR=${CMAKE_BINARY_DIR} -DCPACK_BINARY_DIR=${CMAKE_BINARY_DIR}
-DREV_MAJOR=${PROJECT_VERSION_MAJOR}
-DREV_MINOR=${PROJECT_VERSION_MINOR}
-DREV_BUILD=${PROJECT_VERSION_PATCH}
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake" -P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
BYPRODUCTS ${GENERATED_SOURCE_FILES} BYPRODUCTS ${GENERATED_SOURCE_FILES}

View File

@@ -2,26 +2,27 @@
## Required/optional libraries ## Required/optional libraries
The following libraries are used by OpenTTD for: OpenTTD makes use of the following external libraries:
- zlib: (de)compressing of old (0.3.0-1.0.5) savegames, content downloads, - (encouraged) zlib: (de)compressing of old (0.3.0-1.0.5) savegames, content downloads,
heightmaps heightmaps
- liblzo2: (de)compressing of old (pre 0.3.0) savegames - (encouraged) liblzma: (de)compressing of savegames (1.1.0 and later)
- liblzma: (de)compressing of savegames (1.1.0 and later) - (encouraged) libpng: making screenshots and loading heightmaps
- libpng: making screenshots and loading heightmaps - (optional) liblzo2: (de)compressing of old (pre 0.3.0) savegames
For Linux, the following additional libraries are used (for non-dedicated only):
- libSDL2: hardware access (video, sound, mouse)
- libfreetype: loading generic fonts and rendering them - libfreetype: loading generic fonts and rendering them
- libfontconfig: searching for fonts, resolving font names to actual fonts - libfontconfig: searching for fonts, resolving font names to actual fonts
- libicu: handling of right-to-left scripts (e.g. Arabic and Persian) and - libicu: handling of right-to-left scripts (e.g. Arabic and Persian) and
natural sorting of strings (Linux only) natural sorting of strings
- libSDL2: hardware access (video, sound, mouse) (not required for Windows or macOS)
OpenTTD does not require any of the libraries to be present, but without OpenTTD does not require any of the libraries to be present, but without
liblzma you cannot open most recent savegames and without zlib you cannot liblzma you cannot open most recent savegames and without zlib you cannot
open most older savegames or use the content downloading system. open most older savegames or use the content downloading system.
Without libSDL/liballegro on non-Windows and non-macOS machines you have
no graphical user interface; you would be building a dedicated server.
## Windows: ## Windows
You need Microsoft Visual Studio 2017 or more recent. You need Microsoft Visual Studio 2017 or more recent.
@@ -77,6 +78,8 @@ files himself via the `ZERO_CHECK` project.
## All other platforms ## All other platforms
Minimum required version of CMake is 3.9. Minimum required version of CMake is 3.9.
By default this produces a Debug build with assertations enabled.
This is a far slower build than release builds.
```bash ```bash
mkdir build mkdir build
@@ -88,6 +91,25 @@ make
For more information on how to use CMake (including how to make Release builds), For more information on how to use CMake (including how to make Release builds),
we urge you to read [their excellent manual](https://cmake.org/cmake/help/latest/guide/user-interaction/index.html). we urge you to read [their excellent manual](https://cmake.org/cmake/help/latest/guide/user-interaction/index.html).
## CMake Options
Via CMake, several options can be influenced to get different types of
builds.
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`: build a release build. This is
significant faster than a debug build, but has far less useful information
in case of a crash.
- `-DOPTION_DEDICATED=ON`: build OpenTTD without a GUI. Useful if you are
running a headless server, as it requires less libraries to operate.
- `-DOPTION_USE_ASSERTS=OFF`: disable asserts. Use with care, as assert
statements capture early signs of trouble. Release builds have them
disabled by default.
- `-DOPTION_USE_THREADS=OFF`: disable the use of threads. This will block
the interface in many places, and in general gives a worse experience of
the game. Use with care.
- `-DOPTION_TOOLS_ONLY=ON`: only build tools like `strgen`. Does not build
the game itself. Useful for cross-compiling.
## Supported compilers ## Supported compilers
Every compiler that is supported by CMake and supports C++17, should be Every compiler that is supported by CMake and supports C++17, should be

View File

@@ -46,15 +46,13 @@ OpenTTD has a [community-maintained wiki](https://wiki.openttd.org/), including
OpenTTD has been ported to several platforms and operating systems. OpenTTD has been ported to several platforms and operating systems.
The currently working platforms are: The currently supported platforms are:
- FreeBSD (SDL) - Linux (SDL (OpenGL and non-OpenGL))
- Haiku (SDL) - macOS (universal) (Cocoa)
- Linux (SDL) - Windows (Win32 GDI / OpenGL)
- macOS (universal) (Cocoa video and sound drivers)
- OpenBSD (SDL) Other platforms may also work (in particular various BSD systems), but we don't actively test or maintain these.
- OS/2 (SDL)
- Windows (Win32 GDI (faster) or SDL)
### 1.3.1) Legacy support ### 1.3.1) Legacy support
Platforms, languages and compilers change. Platforms, languages and compilers change.
@@ -79,9 +77,9 @@ For some platforms, you will need to refer to [the installation guide](https://w
The free data files, split into OpenGFX for graphics, OpenSFX for sounds and The free data files, split into OpenGFX for graphics, OpenSFX for sounds and
OpenMSX for music can be found at: OpenMSX for music can be found at:
- https://www.openttd.org/download-opengfx for OpenGFX - https://www.openttd.org/downloads/opengfx-releases/ for OpenGFX
- https://www.openttd.org/download-opensfx for OpenSFX - https://www.openttd.org/downloads/opensfx-releases/ for OpenSFX
- https://www.openttd.org/download-openmsx for OpenMSX - https://www.openttd.org/downloads/openmsx-releases/ for OpenMSX
Please follow the readme of these packages about the installation procedure. Please follow the readme of these packages about the installation procedure.
The Windows installer can optionally download and install these packages. The Windows installer can optionally download and install these packages.

View File

@@ -1,3 +1,26 @@
1.11.2 (2021-05-03)
------------------------------------------------------------------------
Change: [Win32] Limit hardware accelerated video driver to OpenGL 3.2 or higher (#9077)
Change: More improvements to the GUI at different scales (#9075, #9102, #9107, #9133, #9174, #9183)
Fix: Query windows could be partially drawn (#9184)
Fix #9113: Crash when removing an airport that exists in an aircraft's orders (#9182)
Fix #9117: [Fluidsynth] Hang when changing song (#9181)
Fix: String validation could leave invalid UTF-8 encoded strings (#9096)
Fix: [Network] Out-of-bounds memory access with modified servers sending too short password salts (#9176)
Fix: Crash when extra viewport with zero height has sign in view (#9175)
Fix #9147: Crash when taking screenshots (#9169)
Fix #6598: [Network] Prevent crashes when (re)joining network game by falling back to main menu first (#9163)
Fix #9152: Screenshot success popup window was treated as an error (#9159)
Fix: Fast-forward stuttering when vsync is enabled (#9140)
Fix: [Network, Win32] Network errors were handled badly (#9116)
Fix: [Network] Savegame transfer could stall in rare cases (#9106)
Fix #9097: [NewGRF] Cargo initial payment variable was being truncated (#9098)
Fix: [NewGRF] Industry variable 66 and object variable 46 erroneously truncated the distance (#9088)
Fix: [NewGRF] Industry variables 65 and 66 ignored the parameter, and always used the north tile (#9088)
Fix: Do not include regression test AI in bundle (#9068, #9164)
Fix #9062: [Win32] Version in executable was not set to current release version (#9066, #9154)
1.11.1 (2021-04-18) 1.11.1 (2021-04-18)
------------------------------------------------------------------------ ------------------------------------------------------------------------
Feature: Toggle to enable/disable vsync (#8997) Feature: Toggle to enable/disable vsync (#8997)

View File

@@ -35,9 +35,9 @@ function(create_grf_command)
-DNFORENUM_EXECUTABLE=${NFORENUM_EXECUTABLE} -DNFORENUM_EXECUTABLE=${NFORENUM_EXECUTABLE}
-DGRFCODEC_EXECUTABLE=${GRFCODEC_EXECUTABLE} -DGRFCODEC_EXECUTABLE=${GRFCODEC_EXECUTABLE}
-P ${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake -P ${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake
MAIN_DEPENDENCY ${GRF_NFO_SOURCE_FILES} MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake
DEPENDS ${GRF_PNG_BINARY_FILES} DEPENDS ${GRF_PNG_BINARY_FILES}
${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake ${GRF_NFO_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating ${GRF_SOURCE_FOLDER_NAME}.grf" COMMENT "Generating ${GRF_SOURCE_FOLDER_NAME}.grf"
) )

View File

@@ -30,7 +30,9 @@ install(DIRECTORY
${CMAKE_BINARY_DIR}/game ${CMAKE_BINARY_DIR}/game
${CMAKE_SOURCE_DIR}/bin/scripts ${CMAKE_SOURCE_DIR}/bin/scripts
DESTINATION ${DATA_DESTINATION_DIR} DESTINATION ${DATA_DESTINATION_DIR}
COMPONENT language_files) COMPONENT language_files
REGEX "ai/[^\.]+$" EXCLUDE # Ignore subdirs in ai dir
)
install(FILES install(FILES
${CMAKE_SOURCE_DIR}/COPYING.md ${CMAKE_SOURCE_DIR}/COPYING.md

View File

@@ -39,6 +39,20 @@ foreach(NFO_LINE IN LISTS NFO_LINES)
endif() endif()
endforeach() endforeach()
execute_process(COMMAND ${NFORENUM_EXECUTABLE} -s sprites/${GRF_SOURCE_FOLDER_NAME}.nfo) execute_process(COMMAND ${NFORENUM_EXECUTABLE} -s sprites/${GRF_SOURCE_FOLDER_NAME}.nfo RESULT_VARIABLE RESULT)
execute_process(COMMAND ${GRFCODEC_EXECUTABLE} -n -s -e -p1 ${GRF_SOURCE_FOLDER_NAME}.grf) if(RESULT)
if(NOT RESULT MATCHES "^[0-9]*$")
message(FATAL_ERROR "Failed to run NFORenum (${RESULT}), please check NFORENUM_EXECUTABLE variable")
endif()
message(FATAL_ERROR "NFORenum failed")
endif()
execute_process(COMMAND ${GRFCODEC_EXECUTABLE} -n -s -e -p1 ${GRF_SOURCE_FOLDER_NAME}.grf RESULT_VARIABLE RESULT)
if(RESULT)
if(NOT RESULT MATCHES "^[0-9]*$")
message(FATAL_ERROR "Failed to run GRFCodec (${RESULT}), please check GRFCODEC_EXECUTABLE variable")
endif()
message(FATAL_ERROR "GRFCodec failed")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${GRF_SOURCE_FOLDER_NAME}.grf ${GRF_BINARY_FILE}) execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${GRF_SOURCE_FOLDER_NAME}.grf ${GRF_BINARY_FILE})

View File

@@ -1,5 +1,15 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
if(NOT REV_MAJOR)
set(REV_MAJOR 0)
endif()
if(NOT REV_MINOR)
set(REV_MINOR 0)
endif()
if(NOT REV_BUILD)
set(REV_BUILD 0)
endif()
# #
# Finds the current version of the current folder. # Finds the current version of the current folder.
# #

View File

@@ -7,6 +7,7 @@ class Regression extends AIInfo {
function GetAPIVersion() { return "1.11"; } function GetAPIVersion() { return "1.11"; }
function GetDate() { return "2007-03-18"; } function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "Regression"; } function CreateInstance() { return "Regression"; }
function UseAsRandomAI() { return false; }
} }
RegisterAI(Regression()); RegisterAI(Regression());

View File

@@ -7,6 +7,7 @@ class StationList extends AIInfo {
function GetAPIVersion() { return "1.11"; } function GetAPIVersion() { return "1.11"; }
function GetDate() { return "2007-03-18"; } function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "StationList"; } function CreateInstance() { return "StationList"; }
function UseAsRandomAI() { return false; }
} }
RegisterAI(StationList()); RegisterAI(StationList());

View File

@@ -81,7 +81,7 @@ class ReplaceVehicleWindow : public Window {
bool replace_engines; ///< If \c true, engines are replaced, if \c false, wagons are replaced (only for trains). bool replace_engines; ///< If \c true, engines are replaced, if \c false, wagons are replaced (only for trains).
bool reset_sel_engine; ///< Also reset #sel_engine while updating left and/or right and no valid engine selected. bool reset_sel_engine; ///< Also reset #sel_engine while updating left and/or right and no valid engine selected.
GroupID sel_group; ///< Group selected to replace. GroupID sel_group; ///< Group selected to replace.
int details_height; ///< Minimal needed height of the details panels (found so far). int details_height; ///< Minimal needed height of the details panels, in text lines (found so far).
byte sort_criteria; ///< Criteria of sorting vehicles. byte sort_criteria; ///< Criteria of sorting vehicles.
bool descending_sort_order; ///< Order of sorting vehicles. bool descending_sort_order; ///< Order of sorting vehicles.
bool show_hidden_engines; ///< Whether to show the hidden engines. bool show_hidden_engines; ///< Whether to show the hidden engines.
@@ -229,7 +229,7 @@ public:
this->engines[0].ForceRebuild(); this->engines[0].ForceRebuild();
this->engines[1].ForceRebuild(); this->engines[1].ForceRebuild();
this->reset_sel_engine = true; this->reset_sel_engine = true;
this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9);
this->sel_engine[0] = INVALID_ENGINE; this->sel_engine[0] = INVALID_ENGINE;
this->sel_engine[1] = INVALID_ENGINE; this->sel_engine[1] = INVALID_ENGINE;
this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype]; this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype];
@@ -274,7 +274,7 @@ public:
case WID_RV_LEFT_DETAILS: case WID_RV_LEFT_DETAILS:
case WID_RV_RIGHT_DETAILS: case WID_RV_RIGHT_DETAILS:
size->height = this->details_height; size->height = FONT_HEIGHT_NORMAL * this->details_height + padding.height;
break; break;
case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: { case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: {
@@ -475,7 +475,7 @@ public:
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS); NWidgetBase *nwi = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS);
int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT, int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT,
nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine[side], ted); nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine[side], ted);
needed_height = std::max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM); needed_height = std::max(needed_height, (text_end - (int)nwi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL);
} }
} }
if (needed_height != this->details_height) { // Details window are not high enough, enlarge them. if (needed_height != this->details_height) { // Details window are not high enough, enlarge them.

View File

@@ -274,7 +274,7 @@ template <class Tbase_set>
return p; return p;
} }
#include "network/network_content.h" #include "network/core/tcp_content_type.h"
template <class Tbase_set> const char *TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const Tbase_set *s) template <class Tbase_set> const char *TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const Tbase_set *s)
{ {

View File

@@ -1055,7 +1055,7 @@ struct BuildVehicleWindow : Window {
CargoID cargo_filter[NUM_CARGO + 3]; ///< Available cargo filters; CargoID or CF_ANY or CF_NONE or CF_ENGINES CargoID cargo_filter[NUM_CARGO + 3]; ///< Available cargo filters; CargoID or CF_ANY or CF_NONE or CF_ENGINES
StringID cargo_filter_texts[NUM_CARGO + 4]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID StringID cargo_filter_texts[NUM_CARGO + 4]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID
byte cargo_filter_criteria; ///< Selected cargo filter byte cargo_filter_criteria; ///< Selected cargo filter
int details_height; ///< Minimal needed height of the details panels (found so far). int details_height; ///< Minimal needed height of the details panels, in text lines (found so far).
Scrollbar *vscroll; Scrollbar *vscroll;
TestedEngineDetails te; ///< Tested cost and capacity after refit. TestedEngineDetails te; ///< Tested cost and capacity after refit.
@@ -1115,7 +1115,7 @@ struct BuildVehicleWindow : Window {
widget->tool_tip = STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP + type; widget->tool_tip = STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP + type;
widget->SetLowered(this->show_hidden_engines); widget->SetLowered(this->show_hidden_engines);
this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9);
this->FinishInitNested(tile == INVALID_TILE ? (int)type : tile); this->FinishInitNested(tile == INVALID_TILE ? (int)type : tile);
@@ -1553,7 +1553,7 @@ struct BuildVehicleWindow : Window {
break; break;
case WID_BV_PANEL: case WID_BV_PANEL:
size->height = this->details_height; size->height = FONT_HEIGHT_NORMAL * this->details_height + padding.height;
break; break;
case WID_BV_SORT_ASCENDING_DESCENDING: { case WID_BV_SORT_ASCENDING_DESCENDING: {
@@ -1620,12 +1620,12 @@ struct BuildVehicleWindow : Window {
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_BV_PANEL); NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_BV_PANEL);
int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT, int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT,
nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine, this->te); nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine, this->te);
needed_height = std::max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM); needed_height = std::max(needed_height, (text_end - (int)nwi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL);
} }
if (needed_height != this->details_height) { // Details window are not high enough, enlarge them. if (needed_height != this->details_height) { // Details window are not high enough, enlarge them.
int resize = needed_height - this->details_height; int resize = needed_height - this->details_height;
this->details_height = needed_height; this->details_height = needed_height;
this->ReInit(0, resize); this->ReInit(0, resize * FONT_HEIGHT_NORMAL);
return; return;
} }
} }

View File

@@ -59,7 +59,7 @@ struct CargoSpec {
uint8 rating_colour; uint8 rating_colour;
uint8 weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg). uint8 weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
uint16 multiplier; ///< Capacity multiplier for vehicles. (8 fractional bits) uint16 multiplier; ///< Capacity multiplier for vehicles. (8 fractional bits)
uint16 initial_payment; uint32 initial_payment; ///< Initial payment rate before inflation is applied.
uint8 transit_days[2]; uint8 transit_days[2];
bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier). bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier).

View File

@@ -13,6 +13,7 @@
#include "engine_func.h" #include "engine_func.h"
#include "landscape.h" #include "landscape.h"
#include "saveload/saveload.h" #include "saveload/saveload.h"
#include "network/core/game_info.h"
#include "network/network.h" #include "network/network.h"
#include "network/network_func.h" #include "network/network_func.h"
#include "network/network_base.h" #include "network/network_base.h"
@@ -893,7 +894,7 @@ DEF_CONSOLE_CMD(ConNetworkReconnect)
/* Don't resolve the address first, just print it directly as it comes from the config file. */ /* Don't resolve the address first, just print it directly as it comes from the config file. */
IConsolePrintF(CC_DEFAULT, "Reconnecting to %s:%d...", _settings_client.network.last_host, _settings_client.network.last_port); IConsolePrintF(CC_DEFAULT, "Reconnecting to %s:%d...", _settings_client.network.last_host, _settings_client.network.last_port);
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), playas); NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, playas);
return true; return true;
} }
@@ -907,7 +908,6 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
} }
if (argc < 2) return false; if (argc < 2) return false;
if (_networking) NetworkDisconnect(); // we are in network-mode, first close it!
const char *port = nullptr; const char *port = nullptr;
const char *company = nullptr; const char *company = nullptr;
@@ -935,7 +935,7 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
IConsolePrintF(CC_DEFAULT, " port: %s", port); IConsolePrintF(CC_DEFAULT, " port: %s", port);
} }
NetworkClientConnectGame(NetworkAddress(ip, rport), join_as); NetworkClientConnectGame(ip, rport, join_as);
return true; return true;
} }
@@ -1439,7 +1439,7 @@ DEF_CONSOLE_CMD(ConScreenShot)
ScreenshotType type = SC_VIEWPORT; ScreenshotType type = SC_VIEWPORT;
uint32 width = 0; uint32 width = 0;
uint32 height = 0; uint32 height = 0;
const char *name = nullptr; std::string name{};
uint32 arg_index = 1; uint32 arg_index = 1;
if (argc > arg_index) { if (argc > arg_index) {

View File

@@ -13,7 +13,7 @@
#include "gfx_type.h" #include "gfx_type.h"
#include "company_base.h" #include "company_base.h"
#include "newgrf_config.h" #include "newgrf_config.h"
#include "network/core/tcp_content.h" #include "network/core/tcp_content_type.h"
/** Special values for save-load window for the data parameter of #InvalidateWindowData. */ /** Special values for save-load window for the data parameter of #InvalidateWindowData. */

View File

@@ -244,6 +244,28 @@ static void LoadSpriteTables()
} }
static void RealChangeBlitter(const char *repl_blitter)
{
const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName();
if (strcmp(cur_blitter, repl_blitter) == 0) return;
DEBUG(driver, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter);
Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter);
if (new_blitter == nullptr) NOT_REACHED();
DEBUG(driver, 1, "Successfully switched to %s.", repl_blitter);
if (!VideoDriver::GetInstance()->AfterBlitterChange()) {
/* Failed to switch blitter, let's hope we can return to the old one. */
if (BlitterFactory::SelectBlitter(cur_blitter) == nullptr || !VideoDriver::GetInstance()->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config");
}
/* Clear caches that might have sprites for another blitter. */
VideoDriver::GetInstance()->ClearSystemSprites();
ClearFontCache();
GfxClearSpriteCache();
ReInitAllWindows();
}
/** /**
* Check blitter needed by NewGRF config and switch if needed. * Check blitter needed by NewGRF config and switch if needed.
* @return False when nothing changed, true otherwise. * @return False when nothing changed, true otherwise.
@@ -309,7 +331,7 @@ static bool SwitchNewGRFBlitter()
if (BlitterFactory::GetBlitterFactory(repl_blitter) == nullptr) continue; if (BlitterFactory::GetBlitterFactory(repl_blitter) == nullptr) continue;
/* Inform the video driver we want to switch blitter as soon as possible. */ /* Inform the video driver we want to switch blitter as soon as possible. */
VideoDriver::GetInstance()->ChangeBlitter(repl_blitter); VideoDriver::GetInstance()->QueueOnMainThread(std::bind(&RealChangeBlitter, repl_blitter));
break; break;
} }

View File

@@ -1006,6 +1006,8 @@ STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Hardware
STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Selecteer dit vakje om OpenTTD hardwareversnelling te laten gebruiken. De gewijzigde instelling wordt pas van kracht nadat het spel opnieuw is gestart. STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Selecteer dit vakje om OpenTTD hardwareversnelling te laten gebruiken. De gewijzigde instelling wordt pas van kracht nadat het spel opnieuw is gestart.
STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}De instelling wordt pas van kracht als het spel opnieuw is gestart STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}De instelling wordt pas van kracht als het spel opnieuw is gestart
STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}VSync
STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Selecteer dit vakje om het scherm verticaal te synchroniseren. De wijziging gaat pas in nadat je het spel opnieuw hebt opgestart. Werkt alleen als hardwareversnelling is ingeschakeld
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Menupuntgrootte STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Menupuntgrootte
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Kiest de grootte van bedieningselementen STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Kiest de grootte van bedieningselementen
@@ -2040,10 +2042,10 @@ STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Vul je n
STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Voer het IP-adres van de server in STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Voer het IP-adres van de server in
# Start new multiplayer server # Start new multiplayer server
STR_NETWORK_START_SERVER_CAPTION :{WHITE}Start nieuw multiplayerspel STR_NETWORK_START_SERVER_CAPTION :{WHITE}Nieuw spel met meerdere spelers starten
STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}Spelnaam: STR_NETWORK_START_SERVER_NEW_GAME_NAME :{BLACK}Spelnaam:
STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}De spelnaam wordt weergegeven aan andere spelers in het multiplayerspelselectiemenu STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}De spelnaam wordt weergegeven aan andere spelers in het spelselectiemenu voor meerdere spelers
STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Wachtwoord instellen STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Wachtwoord instellen
STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beveilig je spel met een wachtwoord als je niet wilt dat dit algemeen toegankelijk is STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Beveilig je spel met een wachtwoord als je niet wilt dat dit algemeen toegankelijk is

View File

@@ -4467,7 +4467,7 @@ STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Ei voi r
STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Satamaa ei voi rakentaa tähän... STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Satamaa ei voi rakentaa tähän...
STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Lentokenttää ei voi rakentaa... STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Lentokenttää ei voi rakentaa...
STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Liitä yhteen useampi asema/lastausalue. STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Vieressä on useampi kuin yksi olemassaoleva asema tai kuormausalue.
STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... asema liian levittäytynyt STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... asema liian levittäytynyt
STR_ERROR_TOO_MANY_STATIONS_LOADING :{WHITE}Liian monta asemaa ja lastausaluetta. STR_ERROR_TOO_MANY_STATIONS_LOADING :{WHITE}Liian monta asemaa ja lastausaluetta.
STR_ERROR_TOO_MANY_STATION_SPECS :{WHITE}Rautatieasema on jakautunut liian moneen osaan STR_ERROR_TOO_MANY_STATION_SPECS :{WHITE}Rautatieasema on jakautunut liian moneen osaan
@@ -4500,7 +4500,7 @@ STR_ERROR_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Satama p
STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Lentokenttä pitää tuhota ensin. STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Lentokenttä pitää tuhota ensin.
# Waypoint related errors # Waypoint related errors
STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Liittää useamman kuin yhden reittipisteen STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Vieressä on useampi kuin yksi olemassaoleva reittipiste.
STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Liian lähellä toista reittipistettä STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Liian lähellä toista reittipistettä
STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Junien reittipistettä ei voi rakentaa tähän... STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Junien reittipistettä ei voi rakentaa tähän...

View File

@@ -32,7 +32,7 @@ STR_CARGO_PLURAL_OIL :石油
STR_CARGO_PLURAL_LIVESTOCK :家畜 STR_CARGO_PLURAL_LIVESTOCK :家畜
STR_CARGO_PLURAL_GOODS :商品 STR_CARGO_PLURAL_GOODS :商品
STR_CARGO_PLURAL_GRAIN :穀物 STR_CARGO_PLURAL_GRAIN :穀物
STR_CARGO_PLURAL_WOOD :木 STR_CARGO_PLURAL_WOOD :
STR_CARGO_PLURAL_IRON_ORE :鉄鉱石 STR_CARGO_PLURAL_IRON_ORE :鉄鉱石
STR_CARGO_PLURAL_STEEL :鋼鉄 STR_CARGO_PLURAL_STEEL :鋼鉄
STR_CARGO_PLURAL_VALUABLES :貴重品 STR_CARGO_PLURAL_VALUABLES :貴重品
@@ -66,7 +66,7 @@ STR_CARGO_SINGULAR_OIL :石油
STR_CARGO_SINGULAR_LIVESTOCK :家畜 STR_CARGO_SINGULAR_LIVESTOCK :家畜
STR_CARGO_SINGULAR_GOODS :商品 STR_CARGO_SINGULAR_GOODS :商品
STR_CARGO_SINGULAR_GRAIN :穀物 STR_CARGO_SINGULAR_GRAIN :穀物
STR_CARGO_SINGULAR_WOOD :木 STR_CARGO_SINGULAR_WOOD :
STR_CARGO_SINGULAR_IRON_ORE :鉄鉱石 STR_CARGO_SINGULAR_IRON_ORE :鉄鉱石
STR_CARGO_SINGULAR_STEEL :鋼鉄 STR_CARGO_SINGULAR_STEEL :鋼鉄
STR_CARGO_SINGULAR_VALUABLES :貴重品 STR_CARGO_SINGULAR_VALUABLES :貴重品
@@ -100,7 +100,7 @@ STR_QUANTITY_OIL :石油{VOLUME_L
STR_QUANTITY_LIVESTOCK :家畜{COMMA}頭 STR_QUANTITY_LIVESTOCK :家畜{COMMA}頭
STR_QUANTITY_GOODS :商品{COMMA}箱 STR_QUANTITY_GOODS :商品{COMMA}箱
STR_QUANTITY_GRAIN :穀物{WEIGHT_LONG} STR_QUANTITY_GRAIN :穀物{WEIGHT_LONG}
STR_QUANTITY_WOOD :木{WEIGHT_LONG} STR_QUANTITY_WOOD :木{WEIGHT_LONG}
STR_QUANTITY_IRON_ORE :鉄鉱石{WEIGHT_LONG} STR_QUANTITY_IRON_ORE :鉄鉱石{WEIGHT_LONG}
STR_QUANTITY_STEEL :鋼鉄{WEIGHT_LONG} STR_QUANTITY_STEEL :鋼鉄{WEIGHT_LONG}
STR_QUANTITY_VALUABLES :貴重品{COMMA}袋 STR_QUANTITY_VALUABLES :貴重品{COMMA}袋
@@ -187,6 +187,7 @@ STR_COLOUR_ORANGE :橙
STR_COLOUR_BROWN :茶 STR_COLOUR_BROWN :茶
STR_COLOUR_GREY :灰 STR_COLOUR_GREY :灰
STR_COLOUR_WHITE :白 STR_COLOUR_WHITE :白
STR_COLOUR_RANDOM :ランダム
# Units used in OpenTTD # Units used in OpenTTD
STR_UNITS_VELOCITY_IMPERIAL :{COMMA}mph STR_UNITS_VELOCITY_IMPERIAL :{COMMA}mph
@@ -312,6 +313,7 @@ STR_SORT_BY_RATING :レーティン
STR_SORT_BY_NUM_VEHICLES :車両数 STR_SORT_BY_NUM_VEHICLES :車両数
STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :昨年の総利益 STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :昨年の総利益
STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :今年の総利益 STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :今年の総利益
STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :前年度の平均利益
# Group by options for vehicle list # Group by options for vehicle list
STR_GROUP_BY_SHARED_ORDERS :共有注文 STR_GROUP_BY_SHARED_ORDERS :共有注文
@@ -360,6 +362,7 @@ STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION :{BLACK}地形
STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}町を生成します STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}町を生成します
STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}産業を生成します STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}産業を生成します
STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}道路を建設します STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}道路を建設します
STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}路面電車建設
STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}木を植えます。Shiftキーを押しながら決定すると費用を見積もります STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}木を植えます。Shiftキーを押しながら決定すると費用を見積もります
STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}標識を設置します STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}標識を設置します
STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}オブジェクトを設置します。Shiftを押しながら決定すると費用を見積もります STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}オブジェクトを設置します。Shiftを押しながら決定すると費用を見積もります
@@ -648,6 +651,7 @@ STR_MUSIC_EFFECTS_VOLUME :{TINY_FONT}{BLA
STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}--
STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM}
STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------
STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}音楽がありません
STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}"
STR_MUSIC_TRACK :{TINY_FONT}{BLACK}トラック STR_MUSIC_TRACK :{TINY_FONT}{BLACK}トラック
STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}タイトル STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}タイトル
@@ -673,7 +677,9 @@ STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTB
STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}楽曲索引 STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}楽曲索引
STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}プレイリスト - '{STRING}' STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}プレイリスト - '{STRING}'
STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}消去 STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}消去
STR_PLAYLIST_CHANGE_SET :{BLACK}セットの変更
STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}選択したプレイリストの内容を消去します。カスタム1/2 のみ) STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}選択したプレイリストの内容を消去します。カスタム1/2 のみ)
STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}音楽の選択を別のインストール済みセットに変更する
STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストに追加します。(カスタム1/2 のみ) STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストに追加します。(カスタム1/2 のみ)
STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストから削除します。(カスタム1/2 のみ) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}クリックすると、その曲を選択したプレイリストから削除します。(カスタム1/2 のみ)
@@ -733,6 +739,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA
STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}荒地 STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}荒地
STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}草地 STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}草地
STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}露地 STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}露地
STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT} {BLACK}熱帯雨林
STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}耕作地 STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}耕作地
STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}樹林 STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}樹林
STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}岩石 STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}岩石
@@ -764,6 +771,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}全貨
STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}最新のメッセージ/ニュースを表示します STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}最新のメッセージ/ニュースを表示します
STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - -
STR_STATUSBAR_PAUSED :{YELLOW}* * ポーズ中 * * STR_STATUSBAR_PAUSED :{YELLOW}* * ポーズ中 * *
STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * 一時停止中 (リンクグラフの更新を待っています) * *
STR_STATUSBAR_AUTOSAVE :{RED}オートセーブ STR_STATUSBAR_AUTOSAVE :{RED}オートセーブ
STR_STATUSBAR_SAVING_GAME :{RED}* * ゲームセーブ中 * * STR_STATUSBAR_SAVING_GAME :{RED}* * ゲームセーブ中 * *
@@ -923,8 +931,12 @@ STR_GAME_OPTIONS_CURRENCY_ZAR :南アフリカ
STR_GAME_OPTIONS_CURRENCY_CUSTOM :カスタム… STR_GAME_OPTIONS_CURRENCY_CUSTOM :カスタム…
STR_GAME_OPTIONS_CURRENCY_GEL :グルジア ラリー(GEL) STR_GAME_OPTIONS_CURRENCY_GEL :グルジア ラリー(GEL)
STR_GAME_OPTIONS_CURRENCY_IRR :イラン リアル(IRR) STR_GAME_OPTIONS_CURRENCY_IRR :イラン リアル(IRR)
STR_GAME_OPTIONS_CURRENCY_RUB :新ロシアルーブルRUB
STR_GAME_OPTIONS_CURRENCY_MXN :メキシコペソMXN STR_GAME_OPTIONS_CURRENCY_MXN :メキシコペソMXN
STR_GAME_OPTIONS_CURRENCY_NTD :新台湾ドル(ntd) STR_GAME_OPTIONS_CURRENCY_NTD :新台湾ドル(ntd)
STR_GAME_OPTIONS_CURRENCY_CNY :人民元(CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :香港ドルHKD
STR_GAME_OPTIONS_CURRENCY_INR :インドルピーINR
STR_GAME_OPTIONS_CURRENCY_IDR :インドネシアルピアIDR STR_GAME_OPTIONS_CURRENCY_IDR :インドネシアルピアIDR
############ end of currency region ############ end of currency region
@@ -982,6 +994,7 @@ STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM}
STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}ハードウェアアクセラレーション STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}ハードウェアアクセラレーション
STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK} 垂直同期
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}インターフェイスのサイズ STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}インターフェイスのサイズ
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}インターフェイス上の単位サイズを指定します STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}インターフェイス上の単位サイズを指定します
@@ -992,15 +1005,19 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :2倍
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :4倍 STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :4倍
STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}フォントサイズ STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}フォントサイズ
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}使用するインターフェースのフォントサイズを選択します
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(自動検出) STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(自動検出)
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :ノーマル STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :ノーマル
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :ダブルサイズ
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :4倍
STR_GAME_OPTIONS_GRAPHICS :{BLACK}グラフィクス STR_GAME_OPTIONS_GRAPHICS :{BLACK}グラフィクス
STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}画面リフレッシュレート STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}画面リフレッシュレート
STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}使用する画面のリフレッシュレートを選択します STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}使用する画面のリフレッシュレートを選択します
STR_GAME_OPTIONS_REFRESH_RATE_OTHER :その他 STR_GAME_OPTIONS_REFRESH_RATE_OTHER :その他
STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}60Hzを超えるリフレッシュレートはパフォーマンスに影響を与える可能性があります。
STR_GAME_OPTIONS_BASE_GRF :{BLACK}基本グラフィックセット STR_GAME_OPTIONS_BASE_GRF :{BLACK}基本グラフィックセット
STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}使用するグラフィックセットを選択します STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}使用するグラフィックセットを選択します
@@ -1096,6 +1113,8 @@ STR_TERRAIN_TYPE_FLAT :平地
STR_TERRAIN_TYPE_HILLY :丘陵地 STR_TERRAIN_TYPE_HILLY :丘陵地
STR_TERRAIN_TYPE_MOUNTAINOUS :山岳地 STR_TERRAIN_TYPE_MOUNTAINOUS :山岳地
STR_TERRAIN_TYPE_ALPINIST :山脈地帯 STR_TERRAIN_TYPE_ALPINIST :山脈地帯
STR_TERRAIN_TYPE_CUSTOM :カスタム高度
STR_TERRAIN_TYPE_CUSTOM_VALUE :カスタム高度 ({NUM})
STR_CITY_APPROVAL_PERMISSIVE :寛大 STR_CITY_APPROVAL_PERMISSIVE :寛大
STR_CITY_APPROVAL_TOLERANT :寛容 STR_CITY_APPROVAL_TOLERANT :寛容
@@ -1177,11 +1196,14 @@ STR_CONFIG_SETTING_DISASTERS_HELPTEXT :設定を有効
STR_CONFIG_SETTING_CITY_APPROVAL :地域の再編に対する町の姿勢: {STRING} STR_CONFIG_SETTING_CITY_APPROVAL :地域の再編に対する町の姿勢: {STRING}
STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :会社が街域で引き起こした騒音(主に空港)や環境破壊がどの程度、街での評価や同じ地域での更なる建設行為に影響するかを設定します STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :会社が街域で引き起こした騒音(主に空港)や環境破壊がどの程度、街での評価や同じ地域での更なる建設行為に影響するかを設定します
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :マップ高さ限界: {STRING}
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(自動)
STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}マップの最高高さをこの値には設定出来ません。少なくとも1箇所以上この値より高い山があります。 STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}マップの最高高さをこの値には設定出来ません。少なくとも1箇所以上この値より高い山があります。
STR_CONFIG_SETTING_AUTOSLOPE :建物/路線の自動地形追従: {STRING} STR_CONFIG_SETTING_AUTOSLOPE :建物/路線の自動地形追従: {STRING}
STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :撤去を行わないで建物や路線がある土地の地形を変更することを可能にします。建物/路線は変更された地形に自動で追従します。 STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :撤去を行わないで建物や路線がある土地の地形を変更することを可能にします。建物/路線は変更された地形に自動で追従します。
STR_CONFIG_SETTING_CATCHMENT :現実的な受入範囲: {STRING} STR_CONFIG_SETTING_CATCHMENT :現実的な受入範囲: {STRING}
STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :駅や空港の種類の違いによって受入範囲が変動するようになります STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :駅や空港の種類の違いによって受入範囲が変動するようになります
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :有効にすると、駅が接続されている産業(石油掘削装置など)にも、近くに建設された会社が所有している駅がサービスを提供する場合があります。無効になっている場合、これらの産業は、接続されているステーションによってのみサービスを受けることができます。近くの会社のステーションはそれらにサービスを提供できず、接続されたステーションは業界以外のものにサービスを提供しません
STR_CONFIG_SETTING_EXTRADYNAMITE :街有道路・橋・トンネルの撤去容認: {STRING} STR_CONFIG_SETTING_EXTRADYNAMITE :街有道路・橋・トンネルの撤去容認: {STRING}
STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :街有の交通インフラや建物の撤去をより容易にします STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :街有の交通インフラや建物の撤去をより容易にします
STR_CONFIG_SETTING_TRAIN_LENGTH :列車の最大長: {STRING} STR_CONFIG_SETTING_TRAIN_LENGTH :列車の最大長: {STRING}
@@ -1319,6 +1341,8 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :石油精製所
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :石油精製所はマップの外周付近にのみ建設されます。つまり、外周が海のマップでは海岸沿いに建設されるということです STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :石油精製所はマップの外周付近にのみ建設されます。つまり、外周が海のマップでは海岸沿いに建設されるということです
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪線の位置: {STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪線の位置: {STRING}
STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :亜寒帯気候での雪線の高さを設定します。雪は産業と街の成長に影響があります STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :亜寒帯気候での雪線の高さを設定します。雪は産業と街の成長に影響があります
STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :亜寒帯の風景のおおよその雪の量を制御します。雪はまた、産業の生成と町の成長要件にも影響を及ぼします。マップの生成中にのみ使用されます。海抜のすぐ上の土地は常に雪がありません
STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}%
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :地形の起伏: {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :地形の起伏: {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesisのみ) 地形の起伏度を設定します。なだらかな地形では丘陵の数は減り、裾野が長くなります。起伏が多い地形では丘陵が多くなりますが、似たり寄ったりな地形の繰り返しに見えることがあります STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesisのみ) 地形の起伏度を設定します。なだらかな地形では丘陵の数は減り、裾野が長くなります。起伏が多い地形では丘陵が多くなりますが、似たり寄ったりな地形の繰り返しに見えることがあります
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :特になだらか STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :特になだらか
@@ -1357,6 +1381,7 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :青紫
STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :スクロール時の動き STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :スクロール時の動き
STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :右クリックでビューポートを移動し、マウスの位置をロックします STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :右クリックでビューポートを移動し、マウスの位置をロックします
STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :右クリックで地図を移動し、マウスの位置をロックします STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :右クリックで地図を移動し、マウスの位置をロックします
STR_CONFIG_SETTING_SCROLLMODE_RMB :マップを右マウスボタンで動かす
STR_CONFIG_SETTING_SMOOTH_SCROLLING :画面のスムーズスクロール: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING :画面のスムーズスクロール: {STRING}
STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :ミニマップでの移動や「現在位置に移動」などのコマンドを使用した際にメイン画面がどのように移動するかを設定します。有効にした場合はスムーズにスクロールして移動します。無効の場合は目的地に直接ジャンプします STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :ミニマップでの移動や「現在位置に移動」などのコマンドを使用した際にメイン画面がどのように移動するかを設定します。有効にした場合はスムーズにスクロールして移動します。無効の場合は目的地に直接ジャンプします
STR_CONFIG_SETTING_MEASURE_TOOLTIP :測定ツールチップ表示: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP :測定ツールチップ表示: {STRING}
@@ -1427,7 +1452,9 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :建設ツール
STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :橋やトンネルなどを建設した後もツールバーを開いたままにします STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :橋やトンネルなどを建設した後もツールバーを開いたままにします
STR_CONFIG_SETTING_EXPENSES_LAYOUT :財政ウィンドウのグループ分け: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT :財政ウィンドウのグループ分け: {STRING}
STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :財政ウィンドウのレイアウトを収入部門・支出部門でグループ分けするかどうかを設定します STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :財政ウィンドウのレイアウトを収入部門・支出部門でグループ分けするかどうかを設定します
STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :早送りが有効になっている場合のゲームの進行速度を制限します。0 =制限なしコンピューターが許す限り高速。100未満の値は、ゲームの速度を低下させます。上限はコンピュータの仕様によって異なり、ゲームによって異なる場合があります。
STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}%通常のゲーム速度 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}%通常のゲーム速度
STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :制限なし(コンピューターが許す限り高速)
STR_CONFIG_SETTING_SOUND_TICKER :ニュース表示: {STRING} STR_CONFIG_SETTING_SOUND_TICKER :ニュース表示: {STRING}
STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :ステータスバーにニュースが流れたとき効果音を鳴らすかどうかを設定します STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :ステータスバーにニュースが流れたとき効果音を鳴らすかどうかを設定します
@@ -1476,6 +1503,8 @@ STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :マルチプレ
STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :マルチプレイヤーゲームでもAIのライバル企業が登場するかを設定します STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :マルチプレイヤーゲームでもAIのライバル企業が登場するかを設定します
STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :命令コード処理上限: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :命令コード処理上限: {STRING}
STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :AIやゲームスクリプトが一つの「詰め込み指令」を処理する際に、一度に演算できる命令コード数を設定します。一般に値を小さくした場合、ゲームへの負荷が軽減されます STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :AIやゲームスクリプトが一つの「詰め込み指令」を処理する際に、一度に演算できる命令コード数を設定します。一般に値を小さくした場合、ゲームへの負荷が軽減されます
STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY :スクリプトあたりの最大メモリ使用量:{STRING}
STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_VALUE :{COMMA} MiB
STR_CONFIG_SETTING_SERVINT_ISPERCENT :最大信頼度を点検要件化: {STRING} STR_CONFIG_SETTING_SERVINT_ISPERCENT :最大信頼度を点検要件化: {STRING}
STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT :次の点検が必要と判断される条件を設定します。無効の場合は、前の点検から指定の期間が経過した際に点検が必要と判断されます。有効にすると、輸送機器の最大信頼度が指定の値より落ち込んだ場合に次の点検が必要と判断されます STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT :次の点検が必要と判断される条件を設定します。無効の場合は、前の点検から指定の期間が経過した際に点検が必要と判断されます。有効にすると、輸送機器の最大信頼度が指定の値より落ち込んだ場合に次の点検が必要と判断されます
@@ -1535,7 +1564,9 @@ STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :カラー新聞
STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :新聞がカラー版になる境目の年を設定します STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :新聞がカラー版になる境目の年を設定します
STR_CONFIG_SETTING_STARTING_YEAR :開始年: {STRING} STR_CONFIG_SETTING_STARTING_YEAR :開始年: {STRING}
STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :スコアリングの目的でゲームが終了する年。 今年の終わりには、会社のスコアが記録され、ハイスコア画面が表示されますが、プレーヤーはその後もプレイを続けることができます。{}これが開始年より前の場合、ハイスコア画面は表示されません。 STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :スコアリングの目的でゲームが終了する年。 今年の終わりには、会社のスコアが記録され、ハイスコア画面が表示されますが、プレーヤーはその後もプレイを続けることができます。{}これが開始年より前の場合、ハイスコア画面は表示されません。
STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM}
STR_CONFIG_SETTING_ECONOMY_TYPE :エコノミータイプ:{STRING} STR_CONFIG_SETTING_ECONOMY_TYPE :エコノミータイプ:{STRING}
STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :オリジナル
STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :なだらか STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :なだらか
STR_CONFIG_SETTING_ALLOW_SHARES :他社株の取引許容: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES :他社株の取引許容: {STRING}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :有効にすると、ライバル会社の株式を取引できるようになります。この設定を有効にしても、目的の社が設立から丸5年経過していない場合は取引できません STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :有効にすると、ライバル会社の株式を取引できるようになります。この設定を有効にしても、目的の社が設立から丸5年経過していない場合は取引できません
@@ -1586,6 +1617,7 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :町の総人口
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :樹木の自然成長: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :樹木の自然成長: {STRING}
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :ゲーム中、ランダムに生えてくる樹種を設定します。設定によっては樹木の生育に依存する産業に悪影響が生じる可能性があります(「不可」にした場合、亜熱帯地域の伐採所を機能させ続けるためには手動で植林し続ける必要があります) STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :ゲーム中、ランダムに生えてくる樹種を設定します。設定によっては樹木の生育に依存する産業に悪影響が生じる可能性があります(「不可」にした場合、亜熱帯地域の伐採所を機能させ続けるためには手動で植林し続ける必要があります)
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :成長するが、熱帯雨林にのみ広がる STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :成長するが、熱帯雨林にのみ広がる
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :成長し、どこにでも広がる
STR_CONFIG_SETTING_TOOLBAR_POS :メインツールバーの位置: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS :メインツールバーの位置: {STRING}
STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :画面上のメインツールバーの位置を決めます STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :画面上のメインツールバーの位置を決めます
@@ -1603,6 +1635,7 @@ STR_CONFIG_SETTING_ZOOM_MIN :最大ズーム
STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :ズームインの最大倍率を設定します。倍率を高くすればするほどメモリー使用量が増えます STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :ズームインの最大倍率を設定します。倍率を高くすればするほどメモリー使用量が増えます
STR_CONFIG_SETTING_ZOOM_MAX :最大ズームアウトレベル:{STRING} STR_CONFIG_SETTING_ZOOM_MAX :最大ズームアウトレベル:{STRING}
STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :ズームアウトの最大倍率を設定します。ズームアウトの倍率が大きいと、処理遅延が発生する可能性があります STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :ズームアウトの最大倍率を設定します。ズームアウトの倍率が大きいと、処理遅延が発生する可能性があります
STR_CONFIG_SETTING_SPRITE_ZOOM_MIN :使用する最高解像度のスプライト:{STRING}
STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :スプライトに使用する最大解像度を制限します。 スプライトの解像度を制限すると、使用可能な場合でも高解像度のグラフィックを使用できなくなります。 これにより、高解像度のグラフィックを使用する場合と使用しない場合のGRFファイルを組み合わせて使用する場合に、ゲームの外観を統一することができます。 STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :スプライトに使用する最大解像度を制限します。 スプライトの解像度を制限すると、使用可能な場合でも高解像度のグラフィックを使用できなくなります。 これにより、高解像度のグラフィックを使用する場合と使用しない場合のGRFファイルを組み合わせて使用する場合に、ゲームの外観を統一することができます。
STR_CONFIG_SETTING_ZOOM_LVL_MIN :4倍 STR_CONFIG_SETTING_ZOOM_LVL_MIN :4倍
STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2倍 STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2倍
@@ -1746,6 +1779,7 @@ STR_CONFIG_ERROR_OUT_OF_MEMORY :{WHITE}メモ
STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}スプライトキャッシュ中、{BYTES}の割り当てに失敗しました。スプライトキャッシュは{BYTES}に減ったため、OpenTTDの処理速度が低下する恐れがあります。必要メモリ量を減らすには32bitグラフィックを無効にするか、最大ズームイン・ズームアウトのレベルを下げてください STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}スプライトキャッシュ中、{BYTES}の割り当てに失敗しました。スプライトキャッシュは{BYTES}に減ったため、OpenTTDの処理速度が低下する恐れがあります。必要メモリ量を減らすには32bitグラフィックを無効にするか、最大ズームイン・ズームアウトのレベルを下げてください
# Video initalization errors # Video initalization errors
STR_VIDEO_DRIVER_ERROR :{WHITE}ビデオ設定にエラーがあります...
# Intro window # Intro window
STR_INTRO_CAPTION :{WHITE}OpenTTD {REV} STR_INTRO_CAPTION :{WHITE}OpenTTD {REV}
@@ -1953,6 +1987,7 @@ STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}サー
STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}サーバー情報を更新します STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}サーバー情報を更新します
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}インターネットを検索 STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}インターネットを検索
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}インターネットで公開されているサーバーを探す
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}LANで探す STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}LANで探す
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}ローカルエリアネットワークでサーバーを検索する STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}ローカルエリアネットワークでサーバーを検索する
STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}サーバーを追加 STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}サーバーを追加
@@ -2137,6 +2172,7 @@ STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}不正
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}サーバが満員です STR_NETWORK_ERROR_SERVER_FULL :{WHITE}サーバが満員です
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}サーバー側であなたの参加が禁止されています STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}サーバー側であなたの参加が禁止されています
STR_NETWORK_ERROR_KICKED :{WHITE}ゲームから追放されました STR_NETWORK_ERROR_KICKED :{WHITE}ゲームから追放されました
STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}理由:{STRING}
STR_NETWORK_ERROR_CHEATER :{WHITE}このサーバーではチート行為は許可されていません STR_NETWORK_ERROR_CHEATER :{WHITE}このサーバーではチート行為は許可されていません
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}サーバーに送ったコマンド数が過剰です STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}サーバーに送ったコマンド数が過剰です
STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}パスワード入力時間切れです STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}パスワード入力時間切れです
@@ -2178,6 +2214,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :ゲームはま
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :ゲームはまだポーズされています。({STRING}、{STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :ゲームはまだポーズされています。({STRING}、{STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :ゲームはまだポーズされています。 ({STRING}、{STRING}、{STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :ゲームはまだポーズされています。 ({STRING}、{STRING}、{STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :ゲームはまだポーズされています。 ({STRING}、{STRING}、{STRING}、{STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :ゲームはまだポーズされています。 ({STRING}、{STRING}、{STRING}、{STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :ゲームはまだポーズされています。 ({STRING}, {STRING}, {STRING}, {STRING}, {STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :ゲームのポーズが解除されました。({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :ゲームのポーズが解除されました。({STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :プレーヤー数不足 STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :プレーヤー数不足
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :クライアントに接続中 STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :クライアントに接続中
@@ -2195,6 +2232,7 @@ STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING}
STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} は名前を {STRING} に変更しました STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} は名前を {STRING} に変更しました
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}サーバがセッションを終了しました STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}サーバがセッションを終了しました
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}このサーバーは再起動中です…{}しばらくお待ちください… STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}このサーバーは再起動中です…{}しばらくお待ちください…
STR_NETWORK_MESSAGE_KICKED :*** {STRING}がキックされました。理由: ({STRING})
# Content downloading window # Content downloading window
STR_CONTENT_TITLE :{WHITE}コンテンツをダウンロード中 STR_CONTENT_TITLE :{WHITE}コンテンツをダウンロード中
@@ -2270,6 +2308,8 @@ STR_MISSING_GRAPHICS_YES_DOWNLOAD :{BLACK}はい
STR_MISSING_GRAPHICS_NO_QUIT :{BLACK}いいえ、OpenTTDを終了します STR_MISSING_GRAPHICS_NO_QUIT :{BLACK}いいえ、OpenTTDを終了します
STR_MISSING_GRAPHICS_ERROR_TITLE :{WHITE}ダウンロードに失敗しました STR_MISSING_GRAPHICS_ERROR_TITLE :{WHITE}ダウンロードに失敗しました
STR_MISSING_GRAPHICS_ERROR :{BLACK}グラフィックのダウンロードに失敗しました。{}手動でダウンロードしてください。
STR_MISSING_GRAPHICS_ERROR_QUIT :{BLACK}OpenTTDをやめる
# Transparency settings window # Transparency settings window
STR_TRANSPARENCY_CAPTION :{WHITE}透過表示設定 STR_TRANSPARENCY_CAPTION :{WHITE}透過表示設定
@@ -2289,6 +2329,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}貨物
STR_LINKGRAPH_LEGEND_ALL :{BLACK}全て STR_LINKGRAPH_LEGEND_ALL :{BLACK}全て
STR_LINKGRAPH_LEGEND_NONE :{BLACK}なし STR_LINKGRAPH_LEGEND_NONE :{BLACK}なし
STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}表示する会社を選択 STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}表示する会社を選択
STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY}
# Linkgraph legend window and linkgraph legend in smallmap # Linkgraph legend window and linkgraph legend in smallmap
STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}未使用(運送過多) STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}未使用(運送過多)
@@ -2415,7 +2456,9 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}道路
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}軌道用トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}軌道用トンネルを建設します。Shiftを押しながら決定すると費用の見積が出ます
STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}道路の建設/撤去を切り替えます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}道路の建設/撤去を切り替えます
STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}軌道の建設/撤去を切り替えます STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}軌道の建設/撤去を切り替えます
STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}道路の種類を変更/アップグレードします.Shiftは、コスト見積もりの作成/表示を切り替えます
STR_ROAD_NAME_ROAD :道路
STR_ROAD_NAME_TRAM :トラムウェイ STR_ROAD_NAME_TRAM :トラムウェイ
# Road depot construction window # Road depot construction window
@@ -2504,7 +2547,9 @@ STR_TREES_RANDOM_TYPE :{BLACK}ラン
STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}ランダムな樹類で植林します。Shift+クリックで費用を見積もります STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}ランダムな樹類で植林します。Shift+クリックで費用を見積もります
STR_TREES_RANDOM_TREES_BUTTON :{BLACK}ランダムに広域植林 STR_TREES_RANDOM_TREES_BUTTON :{BLACK}ランダムに広域植林
STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}地表全体にランダムに植林します STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}地表全体にランダムに植林します
STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}風景の上をドラッグして、単一の木を植えます。
STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}グローブ STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}グローブ
STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}風景をドラッグして小さな森を植えます
STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}風景の上をドラッグして、大きな森を植えます。 STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}風景の上をドラッグして、大きな森を植えます。
# Land generation window (SE) # Land generation window (SE)
@@ -2564,6 +2609,7 @@ STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}費用:
STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}調査/探鉱 STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}調査/探鉱
STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}建設 STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}建設
STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}出資 STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}出資
STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}すべての産業を削除してもよろしいですか?
# Industry cargoes window # Industry cargoes window
STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}産業:{STRING}に関わる産業チェーン STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}産業:{STRING}に関わる産業チェーン
@@ -2710,22 +2756,39 @@ STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD
# Framerate display window # Framerate display window
STR_FRAMERATE_CAPTION :{WHITE}フレームレート STR_FRAMERATE_CAPTION :{WHITE}フレームレート
STR_FRAMERATE_RATE_BLITTER :{BLACK}グラフィックフレームレート:{STRING} STR_FRAMERATE_RATE_BLITTER :{BLACK}グラフィックフレームレート:{STRING}
STR_FRAMERATE_SPEED_FACTOR :{BLACK}現在のゲーム速度:{DECIMAL} x
STR_FRAMERATE_CURRENT :{WHITE}現在
STR_FRAMERATE_AVERAGE :{WHITE}平均
STR_FRAMERATE_MEMORYUSE :{WHITE}メモリ
STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL} ms STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL} ms
STR_FRAMERATE_MS_WARN :{YELLOW} {DECIMAL} ms STR_FRAMERATE_MS_WARN :{YELLOW} {DECIMAL} ms
STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL} フレーム/秒 STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL} フレーム/秒
STR_FRAMERATE_FPS_WARN :{YELLOW} {DECIMAL}フレーム/秒 STR_FRAMERATE_FPS_WARN :{YELLOW} {DECIMAL}フレーム/秒
STR_FRAMERATE_FPS_BAD :{RED} {DECIMAL}FPS
STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES} STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES}
STR_FRAMERATE_BYTES_WARN :{YELLOW} {BYTES}
############ Leave those lines in this order!! ############ Leave those lines in this order!!
STR_FRAMERATE_GAMELOOP :{BLACK}ゲームループの合計: STR_FRAMERATE_GAMELOOP :{BLACK}ゲームループの合計:
STR_FRAMERATE_GL_ECONOMY :{BLACK}貨物の取り扱い: STR_FRAMERATE_GL_ECONOMY :{BLACK}貨物の取り扱い:
STR_FRAMERATE_GL_TRAINS :{BLACK} 鉄道車両のティック:
STR_FRAMERATE_GL_ROADVEHS :{BLACK} 自動車ティック:
STR_FRAMERATE_GL_AIRCRAFT :{BLACK}航空機ティック:
STR_FRAMERATE_DRAWING :{BLACK}グラフィックレンダリング:
STR_FRAMERATE_VIDEO :{BLACK}ビデオ出力: STR_FRAMERATE_VIDEO :{BLACK}ビデオ出力:
STR_FRAMERATE_SOUND :{BLACK}サウンドミキサー:
############ End of leave-in-this-order ############ End of leave-in-this-order
############ Leave those lines in this order!! ############ Leave those lines in this order!!
STR_FRAMETIME_CAPTION_GAMELOOP :ゲームループ STR_FRAMETIME_CAPTION_GAMELOOP :ゲームループ
STR_FRAMETIME_CAPTION_GL_ECONOMY :貨物の取り扱い STR_FRAMETIME_CAPTION_GL_ECONOMY :貨物の取り扱い
STR_FRAMETIME_CAPTION_GL_TRAINS :切符 STR_FRAMETIME_CAPTION_GL_TRAINS :切符
STR_FRAMETIME_CAPTION_GL_SHIPS :船のティック
STR_FRAMETIME_CAPTION_GL_AIRCRAFT :航空機ティック
STR_FRAMETIME_CAPTION_GL_LANDSCAPE :ワールドティック
STR_FRAMETIME_CAPTION_GL_LINKGRAPH :リンクグラフの遅延 STR_FRAMETIME_CAPTION_GL_LINKGRAPH :リンクグラフの遅延
STR_FRAMETIME_CAPTION_DRAWING :グラフィックレンダリング
STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :ワールドビューポートレンダリング STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :ワールドビューポートレンダリング
STR_FRAMETIME_CAPTION_VIDEO :ビデオ出力
STR_FRAMETIME_CAPTION_AI :AI {NUM} {STRING}
############ End of leave-in-this-order ############ End of leave-in-this-order
@@ -2751,8 +2814,10 @@ STR_SAVELOAD_DETAIL_CAPTION :{BLACK}ゲー
STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}― 情報なし ― STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}― 情報なし ―
STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING}
STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING} STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING}
STR_SAVELOAD_FILTER_TITLE :{BLACK}フィルター:
STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}ファイルを上書きする STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}ファイルを上書きする
STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}既存のファイルを上書きしてもよろしいですか? STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}既存のファイルを上書きしてもよろしいですか?
STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Parent directory)
STR_SAVELOAD_OSKTITLE :{BLACK}保存名を入力 STR_SAVELOAD_OSKTITLE :{BLACK}保存名を入力
@@ -2764,6 +2829,14 @@ STR_MAPGEN_BY :{BLACK}×
STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}街数: STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}街数:
STR_MAPGEN_DATE :{BLACK}日付: STR_MAPGEN_DATE :{BLACK}日付:
STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}産業数: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}産業数:
STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}最高峰:
STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}マップの最高峰の最大の高さを1減らします。
STR_MAPGEN_SNOW_COVERAGE :{BLACK}降雪量:
STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}積雪量を10減らします
STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK} {NUM}
STR_MAPGEN_DESERT_COVERAGE :{BLACK}砂漠の範囲:
STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}砂漠の割合を10増やします
STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}砂漠の範囲を10減らします
STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}%
STR_MAPGEN_LAND_GENERATOR :{BLACK}地形作成: STR_MAPGEN_LAND_GENERATOR :{BLACK}地形作成:
STR_MAPGEN_TERRAIN_TYPE :{BLACK}地形種類: STR_MAPGEN_TERRAIN_TYPE :{BLACK}地形種類:
@@ -2790,6 +2863,9 @@ STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}ハイ
STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}サイズ: STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}サイズ:
STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM} STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM}
STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}ターゲットの最高の高さ
STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}積雪量(%)
STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}砂漠領域(%)
STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}開始年の変更 STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}開始年の変更
# SE Map generation # SE Map generation
@@ -2864,6 +2940,7 @@ STR_NEWGRF_SETTINGS_MD5SUM :{BLACK}MD5sum:
STR_NEWGRF_SETTINGS_PALETTE :{BLACK}パレット: {SILVER}{STRING} STR_NEWGRF_SETTINGS_PALETTE :{BLACK}パレット: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PALETTE_DEFAULT :デフォルトD STR_NEWGRF_SETTINGS_PALETTE_DEFAULT :デフォルトD
STR_NEWGRF_SETTINGS_PALETTE_DEFAULT_32BPP :デフォルトD/ 32 bpp STR_NEWGRF_SETTINGS_PALETTE_DEFAULT_32BPP :デフォルトD/ 32 bpp
STR_NEWGRF_SETTINGS_PALETTE_LEGACY :レガシーW
STR_NEWGRF_SETTINGS_PALETTE_LEGACY_32BPP :レガシーW/ 32 bpp STR_NEWGRF_SETTINGS_PALETTE_LEGACY_32BPP :レガシーW/ 32 bpp
STR_NEWGRF_SETTINGS_PARAMETER :{BLACK}設定: {SILVER}{STRING} STR_NEWGRF_SETTINGS_PARAMETER :{BLACK}設定: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PARAMETER_NONE :なし STR_NEWGRF_SETTINGS_PARAMETER_NONE :なし
@@ -3044,6 +3121,7 @@ STR_TOWN_VIEW_RENAME_TOWN_BUTTON :街名を変更
# Town local authority window # Town local authority window
STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} 地方自治体 STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} 地方自治体
STR_LOCAL_AUTHORITY_ZONE :ゾーン STR_LOCAL_AUTHORITY_ZONE :ゾーン
STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}地方自治体の境界を見る
STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}社の評判: STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}社の評判:
STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING} STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING}
STR_LOCAL_AUTHORITY_ACTIONS_TITLE :{BLACK}可能な活動: STR_LOCAL_AUTHORITY_ACTIONS_TITLE :{BLACK}可能な活動:
@@ -3072,6 +3150,7 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}買収
# Goal window # Goal window
STR_GOALS_CAPTION :{WHITE}{COMPANY} 目標 STR_GOALS_CAPTION :{WHITE}{COMPANY} 目標
STR_GOALS_SPECTATOR_CAPTION :{WHITE}大目標 STR_GOALS_SPECTATOR_CAPTION :{WHITE}大目標
STR_GOALS_GLOBAL_BUTTON_HELPTEXT :{BLACK}グローバルな目標を表示する
STR_GOALS_COMPANY_BUTTON :{BLACK}会社 STR_GOALS_COMPANY_BUTTON :{BLACK}会社
STR_GOALS_COMPANY_BUTTON_HELPTEXT :{BLACK}会社の目標を見る STR_GOALS_COMPANY_BUTTON_HELPTEXT :{BLACK}会社の目標を見る
STR_GOALS_TEXT :{ORANGE}{STRING} STR_GOALS_TEXT :{ORANGE}{STRING}
@@ -3274,6 +3353,7 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}本社
STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}本社ビルを移転します(費用は社の総資産の1%になります)。Shift+クリックで費用を見積もります STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}本社ビルを移転します(費用は社の総資産の1%になります)。Shift+クリックで費用を見積もります
STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}詳細 STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}詳細
STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}インフラ設備の詳細な個数・タイル数を表示します STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}インフラ設備の詳細な個数・タイル数を表示します
STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}この会社にお金を渡す
STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}顔の変更 STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}顔の変更
STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}社長の顔を変更します STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}社長の顔を変更します
@@ -3291,6 +3371,7 @@ STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}この
STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :会社名 STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :会社名
STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :社長名 STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :社長名
STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION :寄付したい金額を入力してください
STR_BUY_COMPANY_MESSAGE :{WHITE}現在、当{COMPANY}は業績悪化に伴い、債務の肩代わりを条件に社の全資産をお譲り致そうと考えております。{}{}債務{CURRENCY_LONG}を一括代済し、この会社を吸収合併しますか? STR_BUY_COMPANY_MESSAGE :{WHITE}現在、当{COMPANY}は業績悪化に伴い、債務の肩代わりを条件に社の全資産をお譲り致そうと考えております。{}{}債務{CURRENCY_LONG}を一括代済し、この会社を吸収合併しますか?
@@ -3299,6 +3380,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION :{WHITE}{COMPANY
STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT :{GOLD}線路長: STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT :{GOLD}線路長:
STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS :{WHITE}信号 STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS :{WHITE}信号
STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT :{GOLD}道路長(含軌道): STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT :{GOLD}道路長(含軌道):
STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT :{GOLD}路面電車軌道:
STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT :{GOLD}水運長: STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT :{GOLD}水運長:
STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}運河 STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}運河
STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}停留施設数: STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}停留施設数:
@@ -3309,8 +3391,11 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENC
# Industry directory # Industry directory
STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}産業 STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}産業
STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- なし - STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- なし -
STR_INDUSTRY_DIRECTORY_ITEM_INFO :{BLACK}{CARGO_LONG}{STRING}{YELLOW} ({COMMA}% 輸送済み){BLACK}
STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY}
STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}産業の名前です - 名前をクリックするとこの産業拠点の場所にメイン画面を移動します。Ctrl+クリックでこの産業拠点の場所を新たなビューポートに表示します STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}産業の名前です - 名前をクリックするとこの産業拠点の場所にメイン画面を移動します。Ctrl+クリックでこの産業拠点の場所を新たなビューポートに表示します
STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}受け取った貨物: {SILVER}{STRING}
STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}生産された貨物:{SILVER} {STRING}
STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :すべての貨物タイプ STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :すべての貨物タイプ
STR_INDUSTRY_DIRECTORY_FILTER_NONE :なし STR_INDUSTRY_DIRECTORY_FILTER_NONE :なし
@@ -3323,6 +3408,7 @@ STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}生産
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}この産業拠点は間もなく閉鎖されます! STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}この産業拠点は間もなく閉鎖されます!
STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}必要条件:{YELLOW} {STRING} {STRING} STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}必要条件:{YELLOW} {STRING} {STRING}
STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :、{STRING} {STRING}
STR_INDUSTRY_VIEW_REQUIRES : {BLACK}必要物資: STR_INDUSTRY_VIEW_REQUIRES : {BLACK}必要物資:
STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW} {STRING} {BLACK}{CARGO_SHORT}待機中{STRING} STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW} {STRING} {BLACK}{CARGO_SHORT}待機中{STRING}
@@ -3393,6 +3479,7 @@ STR_GROUP_RENAME_CAPTION :{BLACK}グル
STR_GROUP_PROFIT_THIS_YEAR :今年の利益: STR_GROUP_PROFIT_THIS_YEAR :今年の利益:
STR_GROUP_PROFIT_LAST_YEAR :昨年の利益: STR_GROUP_PROFIT_LAST_YEAR :昨年の利益:
STR_GROUP_OCCUPANCY :選択中:
# Build vehicle window # Build vehicle window
STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION :新規機関車(非電化) STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION :新規機関車(非電化)
@@ -3401,6 +3488,7 @@ STR_BUY_VEHICLE_TRAIN_MONORAIL_CAPTION :新規モノレ
STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :新規リニア車両 STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :新規リニア車両
STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :新規車両 STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :新規車両
STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :新しい路面電車車両
############ range for vehicle availability starts ############ range for vehicle availability starts
STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :新規列車 STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :新規列車
@@ -3409,6 +3497,7 @@ STR_BUY_VEHICLE_AIRCRAFT_CAPTION :新規航空機
############ range for vehicle availability ends ############ range for vehicle availability ends
STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}価格: {GOLD}{CURRENCY_LONG}{BLACK} 重量: {GOLD}{WEIGHT_SHORT} STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}価格: {GOLD}{CURRENCY_LONG}{BLACK} 重量: {GOLD}{WEIGHT_SHORT}
STR_PURCHASE_INFO_COST_REFIT_WEIGHT :{BLACK}コスト:{GOLD} {CURRENCY_LONG} {BLACK}(修理コスト:{GOLD} {CURRENCY_LONG} {BLACK})重量:{GOLD} {WEIGHT_SHORT}
STR_PURCHASE_INFO_SPEED_POWER :{BLACK}最高速度: {GOLD}{VELOCITY}{BLACK} 出力: {GOLD}{POWER} STR_PURCHASE_INFO_SPEED_POWER :{BLACK}最高速度: {GOLD}{VELOCITY}{BLACK} 出力: {GOLD}{POWER}
STR_PURCHASE_INFO_SPEED :{BLACK}最高速度: {GOLD}{VELOCITY} STR_PURCHASE_INFO_SPEED :{BLACK}最高速度: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}外洋/湖での航行速度: {GOLD}{VELOCITY} STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}外洋/湖での航行速度: {GOLD}{VELOCITY}
@@ -3432,6 +3521,7 @@ STR_PURCHASE_INFO_ENGINES_ONLY :エンジンの
STR_PURCHASE_INFO_ALL_BUT :{CARGO_LIST}を除いてすべて STR_PURCHASE_INFO_ALL_BUT :{CARGO_LIST}を除いてすべて
STR_PURCHASE_INFO_MAX_TE :{BLACK}最大牽引力: {GOLD}{FORCE} STR_PURCHASE_INFO_MAX_TE :{BLACK}最大牽引力: {GOLD}{FORCE}
STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}航続距離: {GOLD}{COMMA} タイル STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}航続距離: {GOLD}{COMMA} タイル
STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}航空機の機種: {GOLD}{STRING}
STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}列車リスト - 個々の情報を見るには列車をクリックします。Ctrl+クリックでその列車種の表示/非表示を切り替えます STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}列車リスト - 個々の情報を見るには列車をクリックします。Ctrl+クリックでその列車種の表示/非表示を切り替えます
STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}車両リスト - 個々の情報を見るには車両をクリックします。Ctrl+クリックでその車両種の表示/非表示を切り替えます STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}車両リスト - 個々の情報を見るには車両をクリックします。Ctrl+クリックでその車両種の表示/非表示を切り替えます
@@ -3443,12 +3533,15 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_BUTTON :{BLACK}車両
STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}船舶を購入 STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}船舶を購入
STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}航空機を購入 STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}航空機を購入
STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}購入し改造する
STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}船の購入と修理
STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}選択した列車を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}選択した列車を購入します。Shift+クリックで購入費を見積もります
STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}選択した車両を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}選択した車両を購入します。Shift+クリックで購入費を見積もります
STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}選択した船舶を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}選択した船舶を購入します。Shift+クリックで購入費を見積もります
STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}選択した航空機を購入します。Shift+クリックで購入費を見積もります STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}選択した航空機を購入します。Shift+クリックで購入費を見積もります
STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}ハイライトされた船を購入して修理します。Shift +クリックすると、購入なしの推定コストが表示されます
STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}名称を変更 STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}名称を変更
STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}名称を変更 STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}名称を変更
@@ -3564,6 +3657,7 @@ STR_ENGINE_PREVIEW_MONORAIL_LOCOMOTIVE :モノレール
STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :リニア列車 STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :リニア列車
STR_ENGINE_PREVIEW_ROAD_VEHICLE :車両 STR_ENGINE_PREVIEW_ROAD_VEHICLE :車両
STR_ENGINE_PREVIEW_TRAM_VEHICLE :路面電車車両
STR_ENGINE_PREVIEW_AIRCRAFT :航空機 STR_ENGINE_PREVIEW_AIRCRAFT :航空機
STR_ENGINE_PREVIEW_SHIP :船舶 STR_ENGINE_PREVIEW_SHIP :船舶
@@ -3611,6 +3705,7 @@ STR_REPLACE_ELRAIL_VEHICLES :機関車(電
STR_REPLACE_MONORAIL_VEHICLES :モノレール車両 STR_REPLACE_MONORAIL_VEHICLES :モノレール車両
STR_REPLACE_MAGLEV_VEHICLES :リニア車両 STR_REPLACE_MAGLEV_VEHICLES :リニア車両
STR_REPLACE_ROAD_VEHICLES :道路車両
STR_REPLACE_TRAM_VEHICLES :路面電車の車両 STR_REPLACE_TRAM_VEHICLES :路面電車の車両
STR_REPLACE_REMOVE_WAGON :{BLACK}列車の短縮: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON :{BLACK}列車の短縮: {ORANGE}{STRING}
@@ -3620,6 +3715,7 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}機関
STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE}
STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}メイン画面を列車に中心します。ダブルクリックで列車をメイン画面で追従します。Ctrl+クリックで列車の場所で新しいビューポートでを開きます。 STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}メイン画面を列車に中心します。ダブルクリックで列車をメイン画面で追従します。Ctrl+クリックで列車の場所で新しいビューポートでを開きます。
STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}航空機の位置に関する中央のメインビュー。ダブルクリックすると、メインビューで航空機が表示されます。Ctrl +クリックすると、航空機の位置に新しいビューポートが開きます
STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}列車を列車庫へ回送します。Ctrl+クリックすると点検後、再出庫します STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}列車を列車庫へ回送します。Ctrl+クリックすると点検後、再出庫します
STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}車両を車庫へ回送します。Ctrl+クリックすると点検後、再出庫します STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}車両を車庫へ回送します。Ctrl+クリックすると点検後、再出庫します
@@ -3651,6 +3747,8 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}車両
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}船舶の情報を表示 STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}船舶の情報を表示
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}航空機の情報を表示します STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}航空機の情報を表示します
STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}現在の列車の動作-クリックして列車を停止/開始します
STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}現在の車両の動作-クリックして車両を停止/開始します
STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}現在の船のアクション-クリックして船を停止/開始します STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}現在の船のアクション-クリックして船を停止/開始します
STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}現在の航空機のアクション-クリックして航空機を停止/開始します STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}現在の航空機のアクション-クリックして航空機を停止/開始します
@@ -3693,6 +3791,8 @@ STR_VEHICLE_INFO_AGE :{COMMA}年({COM
STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA}年({COMMA}年) STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA}年({COMMA}年)
STR_VEHICLE_INFO_MAX_SPEED :{BLACK}最高速度: {LTBLUE}{VELOCITY} STR_VEHICLE_INFO_MAX_SPEED :{BLACK}最高速度: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}最高速度: {LTBLUE}{VELOCITY} {BLACK}航空機のタイプ: {LTBLUE}{STRING}
STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :{BLACK}最高速度: {LTBLUE}{VELOCITY} {BLACK}航空機のタイプ: {LTBLUE}{STRING} {BLACK}範囲: {LTBLUE}{COMMA}タイル
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}重量: {LTBLUE}{WEIGHT_SHORT} {BLACK}出力: {LTBLUE}{POWER}{BLACK} 最高速度: {LTBLUE}{VELOCITY} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}重量: {LTBLUE}{WEIGHT_SHORT} {BLACK}出力: {LTBLUE}{POWER}{BLACK} 最高速度: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}重量: {LTBLUE}{WEIGHT_SHORT} {BLACK}出力: {LTBLUE}{POWER}{BLACK} 最高速度: {LTBLUE}{VELOCITY} {BLACK}最大牽引力: {LTBLUE}{FORCE} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}重量: {LTBLUE}{WEIGHT_SHORT} {BLACK}出力: {LTBLUE}{POWER}{BLACK} 最高速度: {LTBLUE}{VELOCITY} {BLACK}最大牽引力: {LTBLUE}{FORCE}
@@ -3878,6 +3978,7 @@ STR_ORDER_REFIT_STOP_ORDER :({STRING}に改
STR_ORDER_STOP_ORDER :(運用停止) STR_ORDER_STOP_ORDER :(運用停止)
STR_ORDER_GO_TO_STATION :{1:STATION}へ{0:STRING} {2:STRING} STR_ORDER_GO_TO_STATION :{1:STATION}へ{0:STRING} {2:STRING}
STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(駅を使用できません){POP_COLOUR} {STRING} {STATION} {STRING}
STR_ORDER_IMPLICIT :(自動) STR_ORDER_IMPLICIT :(自動)
@@ -4056,7 +4157,11 @@ STR_AI_LIST_ACCEPT_TOOLTIP :{BLACK}選択
STR_AI_LIST_CANCEL :{BLACK}キャンセル STR_AI_LIST_CANCEL :{BLACK}キャンセル
STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}スクリプトを変更しません STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}スクリプトを変更しません
STR_SCREENSHOT_CAPTION :{WHITE}スクリーンショットを撮る
STR_SCREENSHOT_ZOOMIN_SCREENSHOT :{BLACK}スクリーンショットを完全に拡大
STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}地図全体のスクリーンショット STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}地図全体のスクリーンショット
STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}ハイトマップスクリーンショット
STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}ミニマップのスクリーンショット
# AI Parameters # AI Parameters
STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} パラメータ STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} パラメータ
@@ -4116,6 +4221,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :このファイ
STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :ファイルを読み込むことができません STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :ファイルを読み込むことができません
STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :ファイルに書き込むことができません STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :ファイルに書き込むことができません
STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :データ保全性チェック失敗 STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :データ保全性チェック失敗
STR_GAME_SAVELOAD_ERROR_PATCHPACK :安定版のセーブデータです。
STR_GAME_SAVELOAD_NOT_AVAILABLE :<使用不能> STR_GAME_SAVELOAD_NOT_AVAILABLE :<使用不能>
STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}このゲームは路面電車に対応していないバージョンで保存されましたので、すべての路面電車が削除されました。 STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}このゲームは路面電車に対応していないバージョンで保存されましたので、すべての路面電車が削除されました。
@@ -4196,6 +4302,7 @@ STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}全額
STR_ERROR_CURRENCY_REQUIRED :{WHITE}{CURRENCY_LONG}が必要です STR_ERROR_CURRENCY_REQUIRED :{WHITE}{CURRENCY_LONG}が必要です
STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}借入金を返済できません STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}借入金を返済できません
STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}借入金を送金することはできません STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}借入金を送金することはできません
STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}この会社にお金を渡すことはできません...
STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}会社を買収できません STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}会社を買収できません
STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}会社の本社ビルを建設できません STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}会社の本社ビルを建設できません
STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}この会社の株を25%購入できません STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}この会社の株を25%購入できません
@@ -4323,6 +4430,7 @@ STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE
STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}この輸送機器の自動置換/更新は行われませんでした STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}この輸送機器の自動置換/更新は行われませんでした
STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(最低資金が確保できていません) STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(最低資金が確保できていません)
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}新しい車両は{STRING}を運ぶことができません STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}新しい車両は{STRING}を運ぶことができません
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}新しい車両は順番に修理できません{NUM}
# Rail construction errors # Rail construction errors
STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}不可能な線路の組み合わせです STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}不可能な線路の組み合わせです
@@ -4331,6 +4439,7 @@ STR_ERROR_NO_SUITABLE_RAILROAD_TRACK :{WHITE}適当
STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}先に線路を撤去しなければなりません STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}先に線路を撤去しなければなりません
STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}道路は一方通行または進入禁止です STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}道路は一方通行または進入禁止です
STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}このレール種別との平面交差はできません STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}このレール種別との平面交差はできません
STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}この道路では踏切は作れません
STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}ここには信号を設置できません STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}ここには信号を設置できません
STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}ここには線路を建設できません STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}ここには線路を建設できません
STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}ここから線路を撤去できません STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}ここから線路を撤去できません
@@ -4351,6 +4460,9 @@ STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}ここ
STR_ERROR_THERE_IS_NO_ROAD :{WHITE}道路がありません STR_ERROR_THERE_IS_NO_ROAD :{WHITE}道路がありません
STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}軌道がありません STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}軌道がありません
STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}この道路のタイプは変更できません STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}この道路のタイプは変更できません
STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}ここで路面電車の種類を変更できません...
STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}有効な路面電車がありません
STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}軌道に互換性がありません
# Waterway construction errors # Waterway construction errors
STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}ここには運河を建設できません STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}ここには運河を建設できません
@@ -4902,6 +5014,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} ブイ
STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} 第{COMMA}ブイ STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} 第{COMMA}ブイ
STR_FORMAT_COMPANY_NUM :(会社{COMMA}) STR_FORMAT_COMPANY_NUM :(会社{COMMA})
STR_FORMAT_GROUP_NAME :グループ {COMMA} STR_FORMAT_GROUP_NAME :グループ {COMMA}
STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA}
STR_FORMAT_INDUSTRY_NAME :{TOWN}{STRING} STR_FORMAT_INDUSTRY_NAME :{TOWN}{STRING}
STR_FORMAT_WAYPOINT_NAME :{TOWN}中継駅 STR_FORMAT_WAYPOINT_NAME :{TOWN}中継駅
STR_FORMAT_WAYPOINT_NAME_SERIAL :第{1:COMMA} {0:TOWN}中継駅 STR_FORMAT_WAYPOINT_NAME_SERIAL :第{1:COMMA} {0:TOWN}中継駅

View File

@@ -1262,7 +1262,7 @@ STR_CONFIG_SETTING_MULTIPINDTOWN_HELPTEXT :일반적으로
STR_CONFIG_SETTING_SIGNALSIDE :신호기 보이기: {STRING} STR_CONFIG_SETTING_SIGNALSIDE :신호기 보이기: {STRING}
STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT :선로의 어느 쪽에 신호기를 설치할 지 선택합니다. STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT :선로의 어느 쪽에 신호기를 설치할 지 선택합니다.
STR_CONFIG_SETTING_SIGNALSIDE_LEFT :왼쪽에 STR_CONFIG_SETTING_SIGNALSIDE_LEFT :왼쪽에
STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :행 방향에 STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :자동차 통행 방향에
STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :오른쪽에 STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :오른쪽에
STR_CONFIG_SETTING_SHOWFINANCES :연말에 자동으로 재정 창을 띄우기: {STRING} STR_CONFIG_SETTING_SHOWFINANCES :연말에 자동으로 재정 창을 띄우기: {STRING}
STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :이 설정을 켜면. 회사의 재정 상태를 확인하기 쉽도록 매년 말에 재정 창이 자동으로 뜹니다. STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :이 설정을 켜면. 회사의 재정 상태를 확인하기 쉽도록 매년 말에 재정 창이 자동으로 뜹니다.
@@ -1804,8 +1804,8 @@ STR_CONFIG_ERROR :{WHITE}설정
STR_CONFIG_ERROR_ARRAY :{WHITE}... 배열 '{STRING}'에서 오류 발생 STR_CONFIG_ERROR_ARRAY :{WHITE}... 배열 '{STRING}'에서 오류 발생
STR_CONFIG_ERROR_INVALID_VALUE :{WHITE}... '{1:STRING}'에 잘못된 값('{0:STRING}')이 지정되었습니다. STR_CONFIG_ERROR_INVALID_VALUE :{WHITE}... '{1:STRING}'에 잘못된 값('{0:STRING}')이 지정되었습니다.
STR_CONFIG_ERROR_TRAILING_CHARACTERS :{WHITE}... '{STRING}' 설정의 끝에 후행 문자가 있습니다. STR_CONFIG_ERROR_TRAILING_CHARACTERS :{WHITE}... '{STRING}' 설정의 끝에 후행 문자가 있습니다.
STR_CONFIG_ERROR_DUPLICATE_GRFID :{WHITE}... NewGRF '{STRING}' 무시중: '{STRING}'{G 1 "과" "와"} GRF ID가 겹침 STR_CONFIG_ERROR_DUPLICATE_GRFID :{WHITE}... '{STRING}' NewGRF를 무시합니다: '{STRING}'{G 1 "과" "와"} GRF ID가 겹침
STR_CONFIG_ERROR_INVALID_GRF :{WHITE}... 유효하지 않은 NewGRF '{STRING}' 무시중: {STRING} STR_CONFIG_ERROR_INVALID_GRF :{WHITE}... 유효하지 않은 '{STRING}' NewGRF를 무시합니다: {STRING}
STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND :찾을 수 없음 STR_CONFIG_ERROR_INVALID_GRF_NOT_FOUND :찾을 수 없음
STR_CONFIG_ERROR_INVALID_GRF_UNSAFE :사용하기에 불안함 STR_CONFIG_ERROR_INVALID_GRF_UNSAFE :사용하기에 불안함
STR_CONFIG_ERROR_INVALID_GRF_SYSTEM :NewGRF 시스템 STR_CONFIG_ERROR_INVALID_GRF_SYSTEM :NewGRF 시스템
@@ -2112,7 +2112,7 @@ STR_NETWORK_LANG_LATVIAN :라트비아어
STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}멀티플레이 게임 대기실 STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}멀티플레이 게임 대기실
STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}참가 준비중: {ORANGE}{STRING} STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}참가 준비중: {ORANGE}{STRING}
STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}이 게임에 있는 회사의 목록입니다. 다른 회사에 같이 참하거나, 빈 자리가 있을 경우 새로운 회사 시작할 수 있습니다 STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}이 게임에 있는 회사의 목록입니다. 다른 회사에 같이 참하거나, 빈 자리가 있을 경우 새로운 회사를 세워서 시작할 수 있습니다
STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}회사 정보 STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}회사 정보
STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}회사 이름: {WHITE}{STRING} STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}회사 이름: {WHITE}{STRING}
@@ -2178,11 +2178,11 @@ STR_COMPANY_PASSWORD_CANCEL :{BLACK}입력
STR_COMPANY_PASSWORD_OK :{BLACK}이 회사에 새 비밀번호 부여 STR_COMPANY_PASSWORD_OK :{BLACK}이 회사에 새 비밀번호 부여
STR_COMPANY_PASSWORD_CAPTION :{WHITE}회사 비밀번호 STR_COMPANY_PASSWORD_CAPTION :{WHITE}회사 비밀번호
STR_COMPANY_PASSWORD_MAKE_DEFAULT :{BLACK}회사 비밀번호 기본값으로 설정 STR_COMPANY_PASSWORD_MAKE_DEFAULT :{BLACK}회사 비밀번호 기본값으로 설정
STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP :{BLACK}이 회사 비밀번호를 새 회사의 비밀번호 기본값으로 사용 STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP :{BLACK}이 비밀번호를 새 회사의 비밀번호 기본값으로 사용합니다
# Network company info join/password # Network company info join/password
STR_COMPANY_VIEW_JOIN :{BLACK}참여 STR_COMPANY_VIEW_JOIN :{BLACK}참여
STR_COMPANY_VIEW_JOIN_TOOLTIP :{BLACK}이 회사해서 플레이합니다 STR_COMPANY_VIEW_JOIN_TOOLTIP :{BLACK}이 회사해서 플레이합니다
STR_COMPANY_VIEW_PASSWORD :{BLACK}비밀번호 STR_COMPANY_VIEW_PASSWORD :{BLACK}비밀번호
STR_COMPANY_VIEW_PASSWORD_TOOLTIP :{BLACK}다른 참가자가 이 회사에 참여하여 플레이하지 못 하도록 암호로 보호합니다 STR_COMPANY_VIEW_PASSWORD_TOOLTIP :{BLACK}다른 참가자가 이 회사에 참여하여 플레이하지 못 하도록 암호로 보호합니다
STR_COMPANY_VIEW_SET_PASSWORD :{BLACK}회사 비밀번호 설정 STR_COMPANY_VIEW_SET_PASSWORD :{BLACK}회사 비밀번호 설정
@@ -2274,7 +2274,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING}
STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} 님이 관전을 시작하셨습니다 STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} 님이 관전을 시작하셨습니다
STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} 님이 새로운 회사({2:NUM}번)를 창설하셨습니다 STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} 님이 새로운 회사({2:NUM}번)를 창설하셨습니다
STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} 님이 퇴장하셨습니다 (사유: {2:STRING}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} 님이 퇴장하셨습니다 (사유: {2:STRING})
STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} 님 이름 {STRING}(으)로 바었습니다 STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} 님 이름 {STRING}(으)로 바었습니다
STR_NETWORK_MESSAGE_GIVE_MONEY :*** {0:STRING} 님이 {1:STRING}에게 {2:CURRENCY_LONG}만큼의 돈을 보내셨습니다 STR_NETWORK_MESSAGE_GIVE_MONEY :*** {0:STRING} 님이 {1:STRING}에게 {2:CURRENCY_LONG}만큼의 돈을 보내셨습니다
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}서버가 게임을 종료하였습니다 STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}서버가 게임을 종료하였습니다
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}서버가 재시작되고 있습니다...{}기다려주세요... STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}서버가 재시작되고 있습니다...{}기다려주세요...
@@ -3128,7 +3128,7 @@ STR_NEWGRF_LIST_MISSING :{RED}파일 없
# NewGRF 'it's broken' warnings # NewGRF 'it's broken' warnings
STR_NEWGRF_BROKEN :{WHITE}'{0:STRING}' NewGRF가 적용되는 과정에서 비동기화나 충돌이 일어날 수 있습니다 STR_NEWGRF_BROKEN :{WHITE}'{0:STRING}' NewGRF가 적용되는 과정에서 비동기화나 충돌이 일어날 수 있습니다
STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}차고지 안에 있지 않은 '{1:ENGINE}'에 대한 동력 차량 상태가 바뀌었습니다 STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}차고지 안에 있지 않은 '{1:ENGINE}' 동력 차량 상태가 바뀌었습니다
STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}'{1:ENGINE}'{G 1 "이" "가"} 차고지 안에 있지 않으면 차량 길이가 바뀝니다 STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}'{1:ENGINE}'{G 1 "이" "가"} 차고지 안에 있지 않으면 차량 길이가 바뀝니다
STR_NEWGRF_BROKEN_CAPACITY :{WHITE}차량이 기지 안에 있지 않거나 개조가 불가능한 상태에서 '{1:ENGINE}'의 수송량이 변경되었습니다 STR_NEWGRF_BROKEN_CAPACITY :{WHITE}차량이 기지 안에 있지 않거나 개조가 불가능한 상태에서 '{1:ENGINE}'의 수송량이 변경되었습니다
STR_BROKEN_VEHICLE_LENGTH :{WHITE}'{1:COMPANY}'에 속한 열차 '{0:VEHICLE}'의 길이가 잘못된 값을 가지고 있습니다. NewGRF에 의한 문제로 보입니다. 게임이 비동기화 또는 충돌을 일으킬 수 있습니다. STR_BROKEN_VEHICLE_LENGTH :{WHITE}'{1:COMPANY}'에 속한 열차 '{0:VEHICLE}'의 길이가 잘못된 값을 가지고 있습니다. NewGRF에 의한 문제로 보입니다. 게임이 비동기화 또는 충돌을 일으킬 수 있습니다.

View File

@@ -2039,7 +2039,7 @@ STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Adiciona
STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Iniciar servidor STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Iniciar servidor
STR_NETWORK_SERVER_LIST_START_SERVER_TOOLTIP :{BLACK}Iniciar um servidor próprio STR_NETWORK_SERVER_LIST_START_SERVER_TOOLTIP :{BLACK}Iniciar um servidor próprio
STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Digite teu nome STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE :{BLACK}Introduza o seu nome
STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Introduza o endereço IP do servidor STR_NETWORK_SERVER_LIST_ENTER_IP :{BLACK}Introduza o endereço IP do servidor
# Start new multiplayer server # Start new multiplayer server

View File

@@ -390,7 +390,7 @@ STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}Если
STR_BUTTON_DEFAULT :{BLACK}По умолчанию STR_BUTTON_DEFAULT :{BLACK}По умолчанию
STR_BUTTON_CANCEL :{BLACK}Отмена STR_BUTTON_CANCEL :{BLACK}Отмена
STR_BUTTON_OK :{BLACK}OK STR_BUTTON_OK :{BLACK}OK
STR_WARNING_PASSWORD_SECURITY :{YELLOW}Внимание: администраторы сервера могут увидеть ваш пароль. STR_WARNING_PASSWORD_SECURITY :{YELLOW}Внимание: администраторы сервера могут увидеть текст, введённый в это поле.
# On screen keyboard window # On screen keyboard window
STR_OSK_KEYBOARD_LAYOUT :`1234567890-=\qwertyuiop[]asdfghjkl;' zxcvbnm,./ . STR_OSK_KEYBOARD_LAYOUT :`1234567890-=\qwertyuiop[]asdfghjkl;' zxcvbnm,./ .
@@ -924,7 +924,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Отоб
STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Показать последнее сообщение или новость STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Показать последнее сообщение или новость
STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - -
STR_STATUSBAR_PAUSED :{YELLOW}* * ПАУЗА * * STR_STATUSBAR_PAUSED :{YELLOW}* * ПАУЗА * *
STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * ПАУЗА (ожидает обновления графы ссылок) * * STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * ПАУЗА (ожидает обновления графа распределения) * *
STR_STATUSBAR_AUTOSAVE :{RED}АВТОСОХРАНЕНИЕ STR_STATUSBAR_AUTOSAVE :{RED}АВТОСОХРАНЕНИЕ
STR_STATUSBAR_SAVING_GAME :{RED}* * СОХРАНЕНИЕ ИГРЫ * * STR_STATUSBAR_SAVING_GAME :{RED}* * СОХРАНЕНИЕ ИГРЫ * *
@@ -1148,11 +1148,11 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER :Другое
STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM} STR_GAME_OPTIONS_RESOLUTION_ITEM :{NUM}x{NUM}
STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Аппаратное ускорение STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Аппаратное ускорение
STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Нажмите здесь, чтобы включить/выключить аппаратное ускорение в OpenTTD. После этого игру потребуется перезапустить. STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Включить/выключить аппаратное ускорение. После этого игру потребуется перезапустить.
STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Эта настройка будет применена только после перезапуска игры STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Эта настройка будет применена только после перезапуска игры
STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}Вертикальная синхронизация STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}Вертикальная синхронизация
STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Нажмите здесь, чтобы включить/выключить вертикальную синхронизацию. После этого игру потребуется перезапустить. Работает только при включённом аппаратном ускорении. STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Включить/выключить вертикальную синхронизацию. После этого игру потребуется перезапустить. Работает только при включённом аппаратном ускорении.
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Размер элементов интерфейса STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Размер элементов интерфейса
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Выберите размер элементов интерфейса STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Выберите размер элементов интерфейса
@@ -2155,7 +2155,7 @@ STR_NETWORK_SERVER_LIST_DATE_CAPTION :{BLACK}Дата
STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP :{BLACK}Текущая дата STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP :{BLACK}Текущая дата
STR_NETWORK_SERVER_LIST_YEARS_CAPTION :{BLACK}Года STR_NETWORK_SERVER_LIST_YEARS_CAPTION :{BLACK}Года
STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP :{BLACK}Количество лет{}в игре STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP :{BLACK}Количество лет{}в игре
STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP :{BLACK}Язык, версия сервера и т.п. STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP :{BLACK}Язык, версия сервера и{NBSP}т.{NBSP}п.
STR_NETWORK_SERVER_LIST_CLICK_GAME_TO_SELECT :{BLACK}Выберите игру из списка STR_NETWORK_SERVER_LIST_CLICK_GAME_TO_SELECT :{BLACK}Выберите игру из списка
STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER :{BLACK}Последний сервер, к которому вы подключались: STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER :{BLACK}Последний сервер, к которому вы подключались:
@@ -2170,19 +2170,19 @@ STR_NETWORK_SERVER_LIST_SERVER_VERSION :{SILVER}Вер
STR_NETWORK_SERVER_LIST_SERVER_ADDRESS :{SILVER}Адрес сервера: {WHITE}{STRING} STR_NETWORK_SERVER_LIST_SERVER_ADDRESS :{SILVER}Адрес сервера: {WHITE}{STRING}
STR_NETWORK_SERVER_LIST_START_DATE :{SILVER}Дата начала: {WHITE}{DATE_SHORT} STR_NETWORK_SERVER_LIST_START_DATE :{SILVER}Дата начала: {WHITE}{DATE_SHORT}
STR_NETWORK_SERVER_LIST_CURRENT_DATE :{SILVER}Текущая дата: {WHITE}{DATE_SHORT} STR_NETWORK_SERVER_LIST_CURRENT_DATE :{SILVER}Текущая дата: {WHITE}{DATE_SHORT}
STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Защищено паролем! STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Защищён паролем!
STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}СЕРВЕР ОТКЛЮЧЕН STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}СЕРВЕР ОТКЛЮЧЁН
STR_NETWORK_SERVER_LIST_SERVER_FULL :{SILVER}СЕРВЕР ЗАПОЛНЕН STR_NETWORK_SERVER_LIST_SERVER_FULL :{SILVER}СЕРВЕР ЗАПОЛНЕН
STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}ВЕРСИЯ НЕ ПОДХОДИТ STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}ВЕРСИЯ НЕ ПОДХОДИТ
STR_NETWORK_SERVER_LIST_GRF_MISMATCH :{SILVER}НЕ СОВПАДАЕТ НАБОР NEWGRF STR_NETWORK_SERVER_LIST_GRF_MISMATCH :{SILVER}НЕ СОВПАДАЕТ НАБОР NEWGRF
STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Присоединиться STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Присоединиться
STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Обновить сервер STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Обновить информацию
STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Обновить информацию о сервере STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Обновить информацию о сервере
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Искать в интернете STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Искать в интернете
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK} Искать в Интернете общедоступные серверы STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}Поиск общедоступных серверов в интернете
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Искать LAN STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Искать в ЛВС
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Поиск серверов в локальной сети STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Поиск серверов в локальной сети
STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Добавить сервер STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Добавить сервер
STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Добавить сервер в список, который будет автоматически проверяться на идущие игры STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Добавить сервер в список, который будет автоматически проверяться на идущие игры
@@ -2206,13 +2206,13 @@ STR_NETWORK_START_SERVER_UNADVERTISED :Нет
STR_NETWORK_START_SERVER_ADVERTISED :Да STR_NETWORK_START_SERVER_ADVERTISED :Да
STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клиент{P "" а ов} STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} клиент{P "" а ов}
STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. количество клиентов: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Макс. количество клиентов:
STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбор максимального числа клиентов. Не все места должны быть заняты STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Выбор максимального числа клиентов. Не все места обязательно должны быть заняты.
STR_NETWORK_START_SERVER_COMPANIES_SELECT :{BLACK}{NUM} компани{P я и й} STR_NETWORK_START_SERVER_COMPANIES_SELECT :{BLACK}{NUM} компани{P я и й}
STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Макс. количество компаний: STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Макс. количество компаний:
STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Ограничить максимальное количество компаний на сервере STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Ограничить максимальное количество компаний на сервере
STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} наблюдател{P ь я ей} STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} зрител{P ь я ей}
STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Макс. количество наблюдателей: STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Макс. количество зрителей:
STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Ограничить максимальное количество наблюдателей на сервере STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Ограничить максимальное количество зрителей на сервере
STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN :{BLACK}Язык общения: STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN :{BLACK}Язык общения:
STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP :{BLACK}Другие игроки будут знать, на каком языке общаются на сервере STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP :{BLACK}Другие игроки будут знать, на каком языке общаются на сервере
@@ -2262,7 +2262,7 @@ STR_NETWORK_LANG_LATVIAN :Латвийс
STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}Состояние сетевой игры STR_NETWORK_GAME_LOBBY_CAPTION :{WHITE}Состояние сетевой игры
STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}Подготовка соединения: {ORANGE}{STRING} STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN :{BLACK}Подготовка соединения: {ORANGE}{STRING}
STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}Список компаний в игре. Вы можете присоединиться к существующей или основать новую, если есть свободный слот STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP :{BLACK}Список компаний в игре. Вы можете присоединиться к одной из существующих или основать новую, если есть свободная позиция.
STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}ИНФОРМАЦИЯ О КОМПАНИИ STR_NETWORK_GAME_LOBBY_COMPANY_INFO :{SILVER}ИНФОРМАЦИЯ О КОМПАНИИ
STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}Название компании: {WHITE}{STRING} STR_NETWORK_GAME_LOBBY_COMPANY_NAME :{SILVER}Название компании: {WHITE}{STRING}
@@ -2321,7 +2321,7 @@ STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT :Личное с
STR_NETWORK_SERVER :Сервер STR_NETWORK_SERVER :Сервер
STR_NETWORK_CLIENT :Клиент STR_NETWORK_CLIENT :Клиент
STR_NETWORK_SPECTATORS :Наблюдатели STR_NETWORK_SPECTATORS :Зрители
# Network set password # Network set password
STR_COMPANY_PASSWORD_CANCEL :{BLACK}Не сохранять пароль STR_COMPANY_PASSWORD_CANCEL :{BLACK}Не сохранять пароль
@@ -2365,8 +2365,8 @@ STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Прои
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Версия этого клиента не совместима с версией сервера STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Версия этого клиента не совместима с версией сервера
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Неверный пароль STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Неверный пароль
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас забанили на этом сервере STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас заблокировали на этом сервере
STR_NETWORK_ERROR_KICKED :{WHITE}Вас выкинули из игры STR_NETWORK_ERROR_KICKED :{WHITE}Вас отключили от игры
STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Причина: {STRING} STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Причина: {STRING}
STR_NETWORK_ERROR_CHEATER :{WHITE}Чит-коды не разрешены на этом сервере STR_NETWORK_ERROR_CHEATER :{WHITE}Чит-коды не разрешены на этом сервере
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}Вы посылали на сервер слишком много команд STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}Вы посылали на сервер слишком много команд
@@ -2415,13 +2415,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :количес
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :подключение клиентов STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :подключение клиентов
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :вручную STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :вручную
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :игровой скрипт STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :игровой скрипт
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :ожидает обновления графы ссылок STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :ожидает обновления графа распределения
############ End of leave-in-this-order ############ End of leave-in-this-order
STR_NETWORK_MESSAGE_CLIENT_LEAVING :покинул STR_NETWORK_MESSAGE_CLIENT_LEAVING :отключение
STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} подключился к игре STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} подключился к игре
STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} подключился к игре (клиент #{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} подключился к игре (клиент #{2:NUM})
STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} подключился к компании #{2:NUM} STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} подключился к компании #{2:NUM}
STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} подключился наблюдателем STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} подключился в качестве зрителя
STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} основал новую компанию (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} основал новую компанию (#{2:NUM})
STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} покинул игру ({2:STRING}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} покинул игру ({2:STRING})
STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} изменил имя на {STRING} STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} изменил имя на {STRING}
@@ -3305,7 +3305,7 @@ STR_NEWGRF_BROKEN :{WHITE}Файл
STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}Меняется состояние локомотива «{1:ENGINE}», находящегося вне депо STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}Меняется состояние локомотива «{1:ENGINE}», находящегося вне депо
STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}Меняется длина транспорта «{1:ENGINE}», находящегося вне депо STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}Меняется длина транспорта «{1:ENGINE}», находящегося вне депо
STR_NEWGRF_BROKEN_CAPACITY :{WHITE}Он изменил ёмкость ТС «{1:ENGINE}» за пределами депо или без задания на переоборудование STR_NEWGRF_BROKEN_CAPACITY :{WHITE}Он изменил ёмкость ТС «{1:ENGINE}» за пределами депо или без задания на переоборудование
STR_BROKEN_VEHICLE_LENGTH :{WHITE}Поезд «{VEHICLE}», принадлежащий «{COMPANY}», имеет неправильную длину. Вероятно, это вызвано проблемами в файле новой графики (NewGRF). Игра может рассинхронизироваться или вылететь. STR_BROKEN_VEHICLE_LENGTH :{WHITE}Поезд «{VEHICLE}», принадлежащий «{COMPANY}», имеет неправильную длину. Вероятно, это вызвано ошибками в одном из модулей NewGRF. Игра может рассинхронизироваться или вылететь.
STR_NEWGRF_BUGGY :{WHITE}NewGRF «{0:STRING}» предоставляет неверную информацию. STR_NEWGRF_BUGGY :{WHITE}NewGRF «{0:STRING}» предоставляет неверную информацию.
STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Информация о вместимости/переоборудовании для локомотива «{1:ENGINE}» после постройки отличается от сведений в списке покупки, что может помешать функции автообновления/автозамены корректно произвести переоборудование. STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Информация о вместимости/переоборудовании для локомотива «{1:ENGINE}» после постройки отличается от сведений в списке покупки, что может помешать функции автообновления/автозамены корректно произвести переоборудование.
@@ -5372,7 +5372,7 @@ STR_DEFAULT_SIGN_NAME :Табличк
STR_COMPANY_SOMEONE :кто-то STR_COMPANY_SOMEONE :кто-то
STR_SAVEGAME_NAME_DEFAULT :{COMPANY}, {STRING} STR_SAVEGAME_NAME_DEFAULT :{COMPANY}, {STRING}
STR_SAVEGAME_NAME_SPECTATOR :Наблюдатель, {1:STRING} STR_SAVEGAME_NAME_SPECTATOR :Зритель, {1:STRING}
# Viewport strings # Viewport strings
STR_VIEWPORT_TOWN_POP :{WHITE}{TOWN} ({COMMA}) STR_VIEWPORT_TOWN_POP :{WHITE}{TOWN} ({COMMA})

View File

@@ -946,6 +946,7 @@ STR_GAME_OPTIONS_CURRENCY_NTD :新台币 (NTD)
STR_GAME_OPTIONS_CURRENCY_CNY :中国人民币 (CNY) STR_GAME_OPTIONS_CURRENCY_CNY :中国人民币 (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :港币 (HKD) STR_GAME_OPTIONS_CURRENCY_HKD :港币 (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :印度卢布INR STR_GAME_OPTIONS_CURRENCY_INR :印度卢布INR
STR_GAME_OPTIONS_CURRENCY_IDR :印尼盾 (IDR)
STR_GAME_OPTIONS_CURRENCY_MYR :马来西亚林吉特 (MYR) STR_GAME_OPTIONS_CURRENCY_MYR :马来西亚林吉特 (MYR)
############ end of currency region ############ end of currency region
@@ -1005,6 +1006,8 @@ STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}硬件
STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}点击该复选框,让 OpenTTD 尝试使用硬件加速。修改后的设置将在游戏重启后生效 STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}点击该复选框,让 OpenTTD 尝试使用硬件加速。修改后的设置将在游戏重启后生效
STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}修改后的设置将在游戏重启后生效 STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}修改后的设置将在游戏重启后生效
STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}垂直同步
STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}点击该复选框开启垂直同步(V-sync)。修改后的设置将在游戏重启后生效。仅开启硬件加速时有效
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}界面大小 STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}界面大小
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}选择使用的界面元素大小 STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}选择使用的界面元素大小
@@ -1026,6 +1029,8 @@ STR_GAME_OPTIONS_GRAPHICS :{BLACK}图像
STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}显示刷新率 STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}显示刷新率
STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}选择需要的屏幕刷新率 STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}选择需要的屏幕刷新率
STR_GAME_OPTIONS_REFRESH_RATE_OTHER :其他
STR_GAME_OPTIONS_REFRESH_RATE_ITEM :{NUM}Hz
STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}高于 60Hz 的刷新率可能会影响性能。 STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}高于 60Hz 的刷新率可能会影响性能。
STR_GAME_OPTIONS_BASE_GRF :{BLACK}基础图形组 STR_GAME_OPTIONS_BASE_GRF :{BLACK}基础图形组
@@ -1206,8 +1211,10 @@ STR_CONFIG_SETTING_CITY_APPROVAL :地区政府对
STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :设置相关参数以决定各公司造成的噪音及环境破坏时,各城镇对该公司的评价及未来区域建设的影响。 STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :设置相关参数以决定各公司造成的噪音及环境破坏时,各城镇对该公司的评价及未来区域建设的影响。
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :地图高度限制:{STRING} STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :地图高度限制:{STRING}
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :设置高原的最大高度。选择 "(自动)" 则在地形生成后自动选取合适的值
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM}
STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}您不能把最高地面高度设为这个值,因为地图上至少有一座山丘的高度比这个值还大 STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(自动)
STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}您不能把最高地面高度限制设为这个值,因为地图上至少有一座山的高度大于该值
STR_CONFIG_SETTING_AUTOSLOPE :允许在建筑、轨道等下方改变地形(自动斜坡): {STRING} STR_CONFIG_SETTING_AUTOSLOPE :允许在建筑、轨道等下方改变地形(自动斜坡): {STRING}
STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :允许在建筑和轨道下方改变地形而不需要拆除他们 STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :允许在建筑和轨道下方改变地形而不需要拆除他们
STR_CONFIG_SETTING_CATCHMENT :允许更真实的客源范围:{STRING} STR_CONFIG_SETTING_CATCHMENT :允许更真实的客源范围:{STRING}
@@ -1352,6 +1359,7 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :石油工业距
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :限制炼油厂和油井到地图边缘或海岛海岸的最大距离。对于大于 256 格的地图,该值将按比例放大。 STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :限制炼油厂和油井到地图边缘或海岛海岸的最大距离。对于大于 256 格的地图,该值将按比例放大。
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪线高度:{STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪线高度:{STRING}
STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :控制在寒带气候中雪线高度。大雪会影响工业和城镇发展需求。只能在场景编辑器中更改或由“积雪覆盖率”计算得到。 STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :控制在寒带气候中雪线高度。大雪会影响工业和城镇发展需求。只能在场景编辑器中更改或由“积雪覆盖率”计算得到。
STR_CONFIG_SETTING_SNOW_COVERAGE :积雪覆盖率:{STRING}
STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :控制寒带气候中大致的雪量。雪会影响工业和城镇发展需求。只在地图生成时使用。海平面以上一格的土地永远没有积雪 STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :控制寒带气候中大致的雪量。雪会影响工业和城镇发展需求。只在地图生成时使用。海平面以上一格的土地永远没有积雪
STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}%
STR_CONFIG_SETTING_DESERT_COVERAGE :沙漠覆盖率:{STRING} STR_CONFIG_SETTING_DESERT_COVERAGE :沙漠覆盖率:{STRING}
@@ -1471,9 +1479,11 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :“打开”时
STR_CONFIG_SETTING_EXPENSES_LAYOUT :企业财政窗口中的组群支出:{STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT :企业财政窗口中的组群支出:{STRING}
STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :“打开”时公司财务报表将分组显示 STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :“打开”时公司财务报表将分组显示
STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :建造铁路时自动移除信号灯:{STRING} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :建造铁路时自动移除信号灯:{STRING}
STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :建造铁路时自动移除路过的信号灯。注意,这可能导致火车事故。
STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :快进速度上限:{STRING} STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :快进速度上限:{STRING}
STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :限制快进时的最大速度。0 = 无限制(在您计算机允许的范围内)。低于 100% 的值将使游戏变慢。上限取决于您计算机的配置,并随着游戏情况浮动。
STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}% 正常游戏速度 STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}% 正常游戏速度
STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :无限制(在您计算机允许的范围内) STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :无限制(在您计算机允许的范围内)
STR_CONFIG_SETTING_SOUND_TICKER :产业新闻: {STRING} STR_CONFIG_SETTING_SOUND_TICKER :产业新闻: {STRING}
STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :每月初产业新闻音效 STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :每月初产业新闻音效
@@ -1643,7 +1653,10 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :线性
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :树木自动生长: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :树木自动生长: {STRING}
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :控制游戏中数目的随机生长,这将影响依赖树木的工业,比如木材厂 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :控制游戏中数目的随机生长,这将影响依赖树木的工业,比如木材厂
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :生长但不扩散 {RED}(损坏伐木场)
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :只生长在雨林 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :只生长在雨林
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :生长并四处扩散
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :不生长,不扩散 {RED}(损坏伐木场)
STR_CONFIG_SETTING_TOOLBAR_POS :主工具栏位置:{STRING} STR_CONFIG_SETTING_TOOLBAR_POS :主工具栏位置:{STRING}
STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :主工具栏在屏幕上方的位置 STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :主工具栏在屏幕上方的位置
@@ -1661,6 +1674,8 @@ STR_CONFIG_SETTING_ZOOM_MIN :最大放大倍
STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :画面的最大放大倍数,注意:提高放大倍数增加内存需求 STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :画面的最大放大倍数,注意:提高放大倍数增加内存需求
STR_CONFIG_SETTING_ZOOM_MAX :最大视角缩小倍数: {STRING} STR_CONFIG_SETTING_ZOOM_MAX :最大视角缩小倍数: {STRING}
STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :画面的最大缩小倍数,过大的缩放级别在使用时会引起延迟 STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :画面的最大缩小倍数,过大的缩放级别在使用时会引起延迟
STR_CONFIG_SETTING_SPRITE_ZOOM_MIN :贴图的最高分辨率:{STRING}
STR_CONFIG_SETTING_SPRITE_ZOOM_MIN_HELPTEXT :限制贴图的最高分辨率。限制贴图分辨率将避免使用高分辨率贴图,即使它们可用。有助于在混用有/无高分辨率图形的 GRF 文件时保持游戏外观的统一。
STR_CONFIG_SETTING_ZOOM_LVL_MIN :4倍 STR_CONFIG_SETTING_ZOOM_LVL_MIN :4倍
STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2倍 STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2倍
STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :普通 STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :普通
@@ -1713,6 +1728,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :在界面上以
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :英制(英里/小时) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :英制(英里/小时)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :公制(千米/小时) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :公制(千米/小时)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :国际单位制(米/秒) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :国际单位制(米/秒)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :游戏单位 (格/日)
STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :运输工具功率单位:{STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :运输工具功率单位:{STRING}
STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :在界面上以所选择的单位表示运输工具的功率 STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :在界面上以所选择的单位表示运输工具的功率
@@ -2578,8 +2594,12 @@ STR_TREES_RANDOM_TYPE :{BLACK}随机
STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}种植随机类型的树木,按住 Shift 键可以显示所需资金 STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}种植随机类型的树木,按住 Shift 键可以显示所需资金
STR_TREES_RANDOM_TREES_BUTTON :{BLACK}随机树木 STR_TREES_RANDOM_TREES_BUTTON :{BLACK}随机树木
STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}随机地种植一些树木 STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}随机地种植一些树木
STR_TREES_MODE_NORMAL_BUTTON :{BLACK}正常
STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}在地面上拖动以种植单个树木
STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}树丛 STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}树丛
STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}在地面上拖动以种植一些树木
STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}森林 STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}森林
STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}在地面上拖动以种植大量树木
# Land generation window (SE) # Land generation window (SE)
STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}生成土地 STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}生成土地
@@ -2630,7 +2650,7 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}随机
# Fund new industry window # Fund new industry window
STR_FUND_INDUSTRY_CAPTION :{WHITE}建设新的工业设施 STR_FUND_INDUSTRY_CAPTION :{WHITE}建设新的工业设施
STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}请选择工业设施 STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}请选择工业设施
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :大量随机工业 STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}生成随机工业
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}在地图上创建大量随机的工业设施 STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}在地图上创建大量随机的工业设施
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}生成随机工业 STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}生成随机工业
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}你确定要生成大量随机工业吗? STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}你确定要生成大量随机工业吗?
@@ -2662,6 +2682,7 @@ STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP :{BLACK}选择
# Land area window # Land area window
STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}地块信息 STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}地块信息
STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}将屏幕中心移动到地块所在的位置。单击的同时按住Ctrl会在新视点中显示地块位置
STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}清除费用:{LTBLUE}N/A 不能清除 STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}清除费用:{LTBLUE}N/A 不能清除
STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}清除费用:{RED}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}清除费用:{RED}{CURRENCY_LONG}
STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}清除收入: {LTBLUE}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}清除收入: {LTBLUE}{CURRENCY_LONG}
@@ -2886,8 +2907,11 @@ STR_MAPGEN_DATE :{BLACK}日期:
STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}工业数量: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}工业数量:
STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}最高峰: STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}最高峰:
STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}提高最高峰的最大高度一格 STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}提高最高峰的最大高度一格
STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}降低最高峰的最大高度一格
STR_MAPGEN_SNOW_COVERAGE :{BLACK}积雪覆盖率:
STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}增加 10% 积雪覆盖率 STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}增加 10% 积雪覆盖率
STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}减少 10% 积雪覆盖率 STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}减少 10% 积雪覆盖率
STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK}{NUM}%
STR_MAPGEN_DESERT_COVERAGE :{BLACK}沙漠覆盖率: STR_MAPGEN_DESERT_COVERAGE :{BLACK}沙漠覆盖率:
STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}增加 10% 沙漠覆盖率 STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}增加 10% 沙漠覆盖率
STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}减少 10% 沙漠覆盖率 STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}减少 10% 沙漠覆盖率
@@ -2918,6 +2942,7 @@ STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}地图
STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM} STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM}
STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}最高峰目标高度 STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}最高峰目标高度
STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}最高峰
STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}积雪覆盖率 (百分比) STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}积雪覆盖率 (百分比)
STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}沙漠覆盖率 (百分比) STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}沙漠覆盖率 (百分比)
STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}改变游戏开始的日期 STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}改变游戏开始的日期
@@ -3136,6 +3161,7 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}显示
# Sign window # Sign window
STR_EDIT_SIGN_CAPTION :{WHITE}标记标志文字 STR_EDIT_SIGN_CAPTION :{WHITE}标记标志文字
STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}将屏幕中心移动到标志的位置. 单击的同时按住Ctrl会在新视点中显示标志位置
STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}前往下个标记 STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}前往下个标记
STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}前往上个标记 STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}前往上个标记
@@ -3196,13 +3222,13 @@ STR_LOCAL_AUTHORITY_ACTION_NEW_BUILDINGS :资助新房屋
STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :购买运输专营权 STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :购买运输专营权
STR_LOCAL_AUTHORITY_ACTION_BRIBE :贿赂地方政府 STR_LOCAL_AUTHORITY_ACTION_BRIBE :贿赂地方政府
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}进行小型的广告宣传,以吸引更多的旅客和货物选择贵公司的服务.{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}进行小型的广告宣传以吸引更多的旅客和货物选择贵公司的服务。{}为位于该城镇中心较近距离内的车站提供暂时的评分增益。{}费用:{CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}进行中型的广告宣传,以吸引更多的旅客和货物选择贵公司的服务.{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}进行中型的广告宣传以吸引更多的旅客和货物选择贵公司的服务。{}为位于该城镇中心中等距离内的车站提供暂时的评分增益。{}费用:{CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}进行大型的广告宣传,以吸引更多的旅客和货物选择贵公司的服务.{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}进行大型的广告宣传以吸引更多的旅客和货物选择贵公司的服务。{}为位于该城镇中心较远距离内的车站提供暂时的评分增益。{}费用:{CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}资助市政道路进行重建将造成市内交通阻断 6 个月。{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}资助市政道路进行重建。{}将造成市内交通阻断 6 个月。{}费用:{CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}以公司的名义设立一尊塑像。{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}以公司的名义设立一尊塑像。{}为位于该城镇的车站提供永久的评分增益。{}费用:{CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}资助市内建设新的商业设施。{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}资助市内建设新的商业设施。{}为城镇提供暂时的成长速度增益。{}费用:{CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}购买该市一年的运输专营权, 其间该市的乘客及货物只允许选用贵公司的运输服务。{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}购买该市一年的运输专营权。{}其间该市的乘客及货物只允许选用贵公司的运输服务。{}费用:{CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}贿赂地方政府以提高评价,但有被发现后严厉惩罚的风险。{}费用:{CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}贿赂地方政府以提高评价,但有被发现后严厉惩罚的风险。{}费用:{CURRENCY_LONG}
# Goal window # Goal window
@@ -3220,10 +3246,10 @@ STR_GOALS_PROGRESS_COMPLETE :{GREEN}{STRING}
STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}点击使得视图移动到该工业/城镇/地块. Ctrl+左键 在该处创建一个视点. STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}点击使得视图移动到该工业/城镇/地块. Ctrl+左键 在该处创建一个视点.
# Goal question window # Goal question window
STR_GOAL_QUESTION_CAPTION_QUESTION :帮助索引 STR_GOAL_QUESTION_CAPTION_QUESTION :{BLACK}帮助索引
STR_GOAL_QUESTION_CAPTION_INFORMATION :信息 STR_GOAL_QUESTION_CAPTION_INFORMATION :{BLACK}信息
STR_GOAL_QUESTION_CAPTION_WARNING :警告 STR_GOAL_QUESTION_CAPTION_WARNING :{BLACK}警告
STR_GOAL_QUESTION_CAPTION_ERROR :错误 STR_GOAL_QUESTION_CAPTION_ERROR :{YELLOW}错误
############ Start of Goal Question button list ############ Start of Goal Question button list
STR_GOAL_QUESTION_BUTTON_CANCEL :取消 STR_GOAL_QUESTION_BUTTON_CANCEL :取消
@@ -3432,6 +3458,7 @@ STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}出售
STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :公司名称 STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :公司名称
STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :总裁姓名 STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :总裁姓名
STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION :输入你要给予的金额
STR_BUY_COMPANY_MESSAGE :{WHITE}我们正在寻找一家愿意收购我们的公司。{}{}您愿意收购 {COMPANY} ({CURRENCY_LONG}) 吗? STR_BUY_COMPANY_MESSAGE :{WHITE}我们正在寻找一家愿意收购我们的公司。{}{}您愿意收购 {COMPANY} ({CURRENCY_LONG}) 吗?
@@ -3831,7 +3858,9 @@ STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}显示
STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}当前列车动作 - 点击以 停止/启动 列车 STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}当前列车动作 - 点击以 停止/启动 列车
STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}当前车辆动作 - 点击以 停止/启动 车辆 STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}当前车辆动作 - 点击以 停止/启动 车辆
STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}当前船只动作 - 点击以 停止/启动 船只 STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}当前船只动作 - 点击以 停止/启动 船只
STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}当前飞机动作 - 点击以 停止/启动 飞机
STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}将屏幕中心移动到当前指令的目的地。单击的同时按住Ctrl会在新视点中显示指令目的地的位置
# Messages in the start stop button in the vehicle view # Messages in the start stop button in the vehicle view
STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}装载/卸货 STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}装载/卸货
@@ -4059,6 +4088,7 @@ STR_ORDER_REFIT_STOP_ORDER :(改装为{STRI
STR_ORDER_STOP_ORDER :(停留) STR_ORDER_STOP_ORDER :(停留)
STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING} STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING}
STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(不能使用车站){POP_COLOUR} {STRING} {STATION} {STRING}
STR_ORDER_IMPLICIT :(自动) STR_ORDER_IMPLICIT :(自动)
@@ -4303,6 +4333,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :该存档是新
STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :文件无法读取 STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :文件无法读取
STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :文件无法写入 STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :文件无法写入
STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :数据完整性检查失败 STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :数据完整性检查失败
STR_GAME_SAVELOAD_ERROR_PATCHPACK :该存档是来自修改版的游戏
STR_GAME_SAVELOAD_NOT_AVAILABLE :<不可用> STR_GAME_SAVELOAD_NOT_AVAILABLE :<不可用>
STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}游戏已保存为无电车版。所有电车已被去除。 STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}游戏已保存为无电车版。所有电车已被去除。
@@ -4330,6 +4361,7 @@ STR_WARNING_FALLBACK_SOUNDSET :{WHITE}只找
STR_WARNING_SCREENSHOT_SIZE_CAPTION :{WHITE}超大截图 STR_WARNING_SCREENSHOT_SIZE_CAPTION :{WHITE}超大截图
STR_WARNING_SCREENSHOT_SIZE_MESSAGE :{YELLOW}屏幕截图需要 {COMMA} x {COMMA} 像素。 截图将需要一段时间。确认继续截图? STR_WARNING_SCREENSHOT_SIZE_MESSAGE :{YELLOW}屏幕截图需要 {COMMA} x {COMMA} 像素。 截图将需要一段时间。确认继续截图?
STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY :{WHITE}高度图已经被成功保存为 '{STRING}'。最高峰高度是 {NUM}
STR_MESSAGE_SCREENSHOT_SUCCESSFULLY :{WHITE}屏幕截图已经被成功保存为{} '{STRING}' STR_MESSAGE_SCREENSHOT_SUCCESSFULLY :{WHITE}屏幕截图已经被成功保存为{} '{STRING}'
STR_ERROR_SCREENSHOT_FAILED :{WHITE}屏幕截图失败! STR_ERROR_SCREENSHOT_FAILED :{WHITE}屏幕截图失败!
@@ -4510,6 +4542,8 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :车库类型错
STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE}在更新后总长会过长 STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE}在更新后总长会过长
STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}当前没有进行中的车辆更新计划. STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}当前没有进行中的车辆更新计划.
STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(现金不够) STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(现金不够)
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}新车辆不能装载 {STRING}
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}新车辆无法在调度计划 {NUM} 时改装
# Rail construction errors # Rail construction errors
STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}不可能的轨道组合 STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}不可能的轨道组合

View File

@@ -4476,14 +4476,14 @@ STR_ERROR_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Názov s
STR_ERROR_CAN_T_CHANGE_PRESIDENT :{WHITE}Meno prezidenta sa nedá zmeniť... STR_ERROR_CAN_T_CHANGE_PRESIDENT :{WHITE}Meno prezidenta sa nedá zmeniť...
STR_ERROR_MAXIMUM_PERMITTED_LOAN :{WHITE}... úverovy limit je {CURRENCY_LONG} STR_ERROR_MAXIMUM_PERMITTED_LOAN :{WHITE}... úverovy limit je {CURRENCY_LONG}
STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemôžeš si požičať viac peňazí... STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemôžete si požičať viac peňazí...
STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... úver už bol splatený STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... úver už bol splatený
STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} potrebuješ STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} potrebuješ
STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Úver sa nedá splatiť... STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Úver sa nedá splatiť...
STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Nie je možné presunúť peniaze, ktoré sú požičané z banky... STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Nie je možné presunúť peniaze, ktoré sú požičané z banky...
STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Nie je možné presunúť peniaze tejto spoločnosti... STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Nie je možné presunúť peniaze tejto spoločnosti...
STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Spoločnosť nie je možné kúpiť ... STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Spoločnosť nie je možné kúpiť ...
STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nemôžeš postaviť sídlo spoločnosti... STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nemôžete tu postaviť sídlo spoločnosti...
STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nemôžeš kúpiť 25% podiel v tejto spoločnosti... STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nemôžeš kúpiť 25% podiel v tejto spoločnosti...
STR_ERROR_CAN_T_SELL_25_SHARE_IN :{WHITE}25% podiel v tejto spoločnosti sa nedá predať ... STR_ERROR_CAN_T_SELL_25_SHARE_IN :{WHITE}25% podiel v tejto spoločnosti sa nedá predať ...
STR_ERROR_PROTECTED :{WHITE}S akciami tejto spoločnosti nie je zatiaľ možné obchodovať... STR_ERROR_PROTECTED :{WHITE}S akciami tejto spoločnosti nie je zatiaľ možné obchodovať...
@@ -4506,10 +4506,10 @@ STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... v ce
STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... príliš veľa priemyslu STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... príliš veľa priemyslu
STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nemožno vygenerovať priemysel... STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nemožno vygenerovať priemysel...
STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING} sa tu nedá postaviť... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING} sa tu nedá postaviť...
STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Nemôžeš tu postaviť tento typ priemyslu... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Nemôžete tu postaviť tento typ priemyslu...
STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... príliš blízko iného priemyslu STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... príliš blízko iného priemyslu
STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... najskôr je potrebné založiť mesto STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... najskôr je potrebné založiť mesto
STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... povolené len jedno pre 1mesto STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... povolené len jedno pre každé mesto
STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200 :{WHITE}... môže byť postavené v mestách z populáciou väčšou ako 1200 STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200 :{WHITE}... môže byť postavené v mestách z populáciou väčšou ako 1200
STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}... môže byť postavené len v dažďovom pralese STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}... môže byť postavené len v dažďovom pralese
STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}... môže byť postavené len v púšti STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}... môže byť postavené len v púšti
@@ -4525,13 +4525,13 @@ STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Nenašli
STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Pre získanie lepšej mapy zmeňte parametre jej generovania STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Pre získanie lepšej mapy zmeňte parametre jej generovania
# Station construction related errors # Station construction related errors
STR_ERROR_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Nemôžeš tu postaviť železničnú stanicu... STR_ERROR_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Nemôžete tu postaviť železničnú stanicu...
STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Nemôžeš tu postaviť autobusovú zastávku... STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Nemôžete tu postaviť autobusovú zastávku...
STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nemôžeš tu postaviť vykládku... STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nemôžeš tu postaviť vykládku...
STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Nemôžeš postaviť električkovú osobnú stanicu... STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Nemôžete tu postaviť električkovú zastávku...
STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Nemôžeš postaviť električkovú nákladnú stanicu... STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Nemôžete tu postaviť električkovú vykládku...
STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Nemôžeš tu postaviť prístav... STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Nemôžete tu postaviť prístav...
STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Nemôžeš tu postaviť letisko... STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Nemôžete tu postaviť letisko...
STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Susedí z viacerými stanicami/výkladkami STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Susedí z viacerými stanicami/výkladkami
STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... stanica je príliš veľká STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... stanica je príliš veľká
@@ -4579,8 +4579,8 @@ STR_ERROR_BUOY_IN_THE_WAY :{WHITE}... bój
STR_ERROR_BUOY_IS_IN_USE :{WHITE}... bóju používa iná spoločnosť! STR_ERROR_BUOY_IS_IN_USE :{WHITE}... bóju používa iná spoločnosť!
# Depot related errors # Depot related errors
STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Nemôžeš tu postaviť vlakové depo... STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Nemôžete tu postaviť vlakové depo...
STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Nemôžeš tu postaviť garáž... STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Nemôžete tu postaviť garáž...
STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Nemôžeš tu postaviť električkové depo... STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Nemôžeš tu postaviť električkové depo...
STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Nemôžeš tu postaviť lodenicu... STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Nemôžeš tu postaviť lodenicu...
@@ -4620,7 +4620,7 @@ STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Cesta je
STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}Nie sú povolené priecestia pre tento typ železnice STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}Nie sú povolené priecestia pre tento typ železnice
STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}Nie sú povolené priecestia pre tento typ cesty STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}Nie sú povolené priecestia pre tento typ cesty
STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Nemôžeš tu umiestniť návestidlá... STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Nemôžeš tu umiestniť návestidlá...
STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Nemôžeš tu stavať železničné koľaje... STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Nemôžete tu postaviť železničnú trať...
STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Nemôžeš tu odstrániť železničné koľaje... STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Nemôžeš tu odstrániť železničné koľaje...
STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Nemôžeš tu odstrániť návestidlá... STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Nemôžeš tu odstrániť návestidlá...
STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}Tu nie je možné zameniť návestidlá... STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}Tu nie je možné zameniť návestidlá...
@@ -4632,7 +4632,7 @@ STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}Nemôže
# Road construction errors # Road construction errors
STR_ERROR_MUST_REMOVE_ROAD_FIRST :{WHITE}Najprv treba odstrániť cestu STR_ERROR_MUST_REMOVE_ROAD_FIRST :{WHITE}Najprv treba odstrániť cestu
STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION :{WHITE}... na jednosmerných cestách nie sú dovolené križovatky STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION :{WHITE}... na jednosmerných cestách nie sú dovolené križovatky
STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}Nemôžeš tu postaviť cestu... STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}Nemôžete tu postaviť cestu...
STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}Nemôžeš tu stavať električkovú trať... STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}Nemôžeš tu stavať električkovú trať...
STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Nemôžeš tu odstrániť cestu... STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Nemôžeš tu odstrániť cestu...
STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Nemôžeš tu odstrániť električkovú trať... STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Nemôžeš tu odstrániť električkovú trať...
@@ -4646,15 +4646,15 @@ STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}... neko
# Waterway construction errors # Waterway construction errors
STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Tu sa nedá postaviť vodný kanál... STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Tu sa nedá postaviť vodný kanál...
STR_ERROR_CAN_T_BUILD_LOCKS :{WHITE}Tu sa nedá postaviť stavidlo... STR_ERROR_CAN_T_BUILD_LOCKS :{WHITE}Nemôžete tu postaviť stavidlá...
STR_ERROR_CAN_T_PLACE_RIVERS :{WHITE}Tu nie je možné umiestniť rieku... STR_ERROR_CAN_T_PLACE_RIVERS :{WHITE}Tu nie je možné umiestniť rieku...
STR_ERROR_MUST_BE_BUILT_ON_WATER :{WHITE}... musíš postaviť na vode STR_ERROR_MUST_BE_BUILT_ON_WATER :{WHITE}... musíš postaviť na vode
STR_ERROR_CAN_T_BUILD_ON_WATER :{WHITE}... nemôžeš postav na vode STR_ERROR_CAN_T_BUILD_ON_WATER :{WHITE}... nemôže byť postavené na vode
STR_ERROR_CAN_T_BUILD_ON_SEA :{WHITE}... nemôžeš postav na otvorenom mori STR_ERROR_CAN_T_BUILD_ON_SEA :{WHITE}... nemôže byť postavené na otvorenom mori
STR_ERROR_CAN_T_BUILD_ON_CANAL :{WHITE}... nemôže byť postavené na vodnom kanále STR_ERROR_CAN_T_BUILD_ON_CANAL :{WHITE}... nemôže byť postavené na vodnom kanále
STR_ERROR_CAN_T_BUILD_ON_RIVER :{WHITE}... nemôže byť postavené na rieke STR_ERROR_CAN_T_BUILD_ON_RIVER :{WHITE}... nemôže byť postavené na rieke
STR_ERROR_MUST_DEMOLISH_CANAL_FIRST :{WHITE}Najprv sa musí zbúrať vodný kanál STR_ERROR_MUST_DEMOLISH_CANAL_FIRST :{WHITE}Najprv sa musí zbúrať vodný kanál
STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Tu nie je možné postaviť akvadukt... STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Nemôžete tu postaviť akvadukt...
# Tree related errors # Tree related errors
STR_ERROR_TREE_ALREADY_HERE :{WHITE}... strom tu už je STR_ERROR_TREE_ALREADY_HERE :{WHITE}... strom tu už je
@@ -4662,7 +4662,7 @@ STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE :{WHITE}... zlý
STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Nemôžeš tu zasadiť strom... STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Nemôžeš tu zasadiť strom...
# Bridge related errors # Bridge related errors
STR_ERROR_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Nemôžeš tu postaviť most... STR_ERROR_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Nemôžete tu postaviť most...
STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Most musíš najskôr zbúrať STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Most musíš najskôr zbúrať
STR_ERROR_CAN_T_START_AND_END_ON :{WHITE}Nemožno začať a skončiť na tom istom mieste STR_ERROR_CAN_T_START_AND_END_ON :{WHITE}Nemožno začať a skončiť na tom istom mieste
STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT :{WHITE}Konce mosta nie sú v rovnakej výške STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT :{WHITE}Konce mosta nie sú v rovnakej výške
@@ -4780,7 +4780,7 @@ STR_ERROR_CAN_T_ADD_ORDER_SHARED :{WHITE}... vozi
STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Nemožno zdieľať zoznam príkazov ... STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Nemožno zdieľať zoznam príkazov ...
STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST :{WHITE}Nie je možné prestať zdieľať zoznam príkazov... STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST :{WHITE}Nie je možné prestať zdieľať zoznam príkazov...
STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Nemozno kopirovat zoznam prikazov ... STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Nemožno kopírovať zoznam príkazov ...
STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... príliš ďaleko z predchádzajúceho cieľa STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... príliš ďaleko z predchádzajúceho cieľa
STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... lietadlo nemá dostatočný dosah STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... lietadlo nemá dostatočný dosah

View File

@@ -149,14 +149,14 @@ STR_ABBREV_PAPER :{TINY_FONT}PP
STR_ABBREV_GOLD :{TINY_FONT}OR STR_ABBREV_GOLD :{TINY_FONT}OR
STR_ABBREV_WATER :{TINY_FONT}AG STR_ABBREV_WATER :{TINY_FONT}AG
STR_ABBREV_WHEAT :{TINY_FONT}TG STR_ABBREV_WHEAT :{TINY_FONT}TG
STR_ABBREV_RUBBER :{TINY_FONT}GM STR_ABBREV_RUBBER :{TINY_FONT}CA
STR_ABBREV_SUGAR :{TINY_FONT}AZ STR_ABBREV_SUGAR :{TINY_FONT}AZ
STR_ABBREV_TOYS :{TINY_FONT}JG STR_ABBREV_TOYS :{TINY_FONT}JG
STR_ABBREV_SWEETS :{TINY_FONT}DC STR_ABBREV_SWEETS :{TINY_FONT}DC
STR_ABBREV_COLA :{TINY_FONT}CL STR_ABBREV_COLA :{TINY_FONT}CL
STR_ABBREV_CANDYFLOSS :{TINY_FONT}AA STR_ABBREV_CANDYFLOSS :{TINY_FONT}AA
STR_ABBREV_BUBBLES :{TINY_FONT}BU STR_ABBREV_BUBBLES :{TINY_FONT}BU
STR_ABBREV_TOFFEE :{TINY_FONT}CM STR_ABBREV_TOFFEE :{TINY_FONT}TF
STR_ABBREV_BATTERIES :{TINY_FONT}PI STR_ABBREV_BATTERIES :{TINY_FONT}PI
STR_ABBREV_PLASTIC :{TINY_FONT}PL STR_ABBREV_PLASTIC :{TINY_FONT}PL
STR_ABBREV_FIZZY_DRINKS :{TINY_FONT}RF STR_ABBREV_FIZZY_DRINKS :{TINY_FONT}RF
@@ -242,8 +242,8 @@ STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Cierra l
STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Título de la ventana - arrastra para moverla STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Título de la ventana - arrastra para moverla
STR_TOOLTIP_SHADE :{BLACK}Oculta la ventana - muestra sólo el título de la ventana STR_TOOLTIP_SHADE :{BLACK}Oculta la ventana - muestra sólo el título de la ventana
STR_TOOLTIP_DEBUG :{BLACK}Muestra la información de depuración NewGRF STR_TOOLTIP_DEBUG :{BLACK}Muestra la información de depuración NewGRF
STR_TOOLTIP_DEFSIZE :{BLACK}Redimensionar ventana al tamaño por defecto. Ctrl+Clic permite almacenar el tamaño actual como tamaño por defecto STR_TOOLTIP_DEFSIZE :{BLACK}Redimensionar ventana al tamaño por defecto. Ctrl+clic permite almacenar el tamaño actual como tamaño por defecto
STR_TOOLTIP_STICKY :{BLACK}Esta ventana no se cerrará tras usar el comando 'Cerrar Todas las Ventanas'. Ctrl+Clic permite guardar el estado como estado por defecto STR_TOOLTIP_STICKY :{BLACK}Esta ventana no se cerrará tras usar el comando 'Cerrar Todas las Ventanas'. Ctrl+clic permite guardar el estado como estado por defecto
STR_TOOLTIP_RESIZE :{BLACK}Clica y arrastra para redimensionar la ventana STR_TOOLTIP_RESIZE :{BLACK}Clica y arrastra para redimensionar la ventana
STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Alterna el tamaño de ventana entre grande/pequeño STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Alterna el tamaño de ventana entre grande/pequeño
STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST :{BLACK}Barra de desplazamiento - mueve la lista hacia arriba/abajo STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST :{BLACK}Barra de desplazamiento - mueve la lista hacia arriba/abajo
@@ -340,10 +340,10 @@ STR_TOOLBAR_TOOLTIP_DISPLAY_GOALS_LIST :{BLACK}Muestra
STR_TOOLBAR_TOOLTIP_DISPLAY_GRAPHS :{BLACK}Mostrar gráficas STR_TOOLBAR_TOOLTIP_DISPLAY_GRAPHS :{BLACK}Mostrar gráficas
STR_TOOLBAR_TOOLTIP_DISPLAY_COMPANY_LEAGUE :{BLACK}Mostrar tabla de clasificación de empresas STR_TOOLBAR_TOOLTIP_DISPLAY_COMPANY_LEAGUE :{BLACK}Mostrar tabla de clasificación de empresas
STR_TOOLBAR_TOOLTIP_FUND_CONSTRUCTION_OF_NEW :{BLACK}Financiar la construcción de una industria nueva o mostrar lista de industrias STR_TOOLBAR_TOOLTIP_FUND_CONSTRUCTION_OF_NEW :{BLACK}Financiar la construcción de una industria nueva o mostrar lista de industrias
STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_TRAINS :{BLACK}Mostrar lista de trenes de la empresa. Ctrl+Clic hace que no aparezca la lista de grupos STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_TRAINS :{BLACK}Mostrar lista de trenes de la empresa. Ctrl+clic hace que no aparezca la lista de grupos
STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_ROAD_VEHICLES :{BLACK}Mostrar lista de vehículos de carretera de la empresa. Ctrl+Clic hace que no aparezca la lista de grupos STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_ROAD_VEHICLES :{BLACK}Mostrar lista de vehículos de carretera de la empresa. Ctrl+clic hace que no aparezca la lista de grupos
STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_SHIPS :{BLACK}Mostrar lista de barcos de la empresa. Ctrl+Clic hace que no aparezca la lista de grupos STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_SHIPS :{BLACK}Mostrar lista de barcos de la empresa. Ctrl+clic hace que no aparezca la lista de grupos
STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_AIRCRAFT :{BLACK}Mostrar lista de aeronaves de la empresa. Ctrl+Clic hace que no aparezca la lista de grupos STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_AIRCRAFT :{BLACK}Mostrar lista de aeronaves de la empresa. Ctrl+clic hace que no aparezca la lista de grupos
STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN :{BLACK}Acercar vista STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN :{BLACK}Acercar vista
STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT :{BLACK}Alejar vista STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT :{BLACK}Alejar vista
STR_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}Construir ferrocarril STR_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}Construir ferrocarril
@@ -1904,7 +1904,7 @@ STR_LIVERY_SHIP_TOOLTIP :{BLACK}Muestra
STR_LIVERY_AIRCRAFT_TOOLTIP :{BLACK}Muestra el esquema de color de las aeronaves STR_LIVERY_AIRCRAFT_TOOLTIP :{BLACK}Muestra el esquema de color de las aeronaves
STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Selecciona el color primario para el esquema seleccionado. Ctrl+clic fijará este color para todo el esquema STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Selecciona el color primario para el esquema seleccionado. Ctrl+clic fijará este color para todo el esquema
STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Selecciona el color secundario para el esquema seleccionado. Ctrl+clic fijará este color para todo el esquema STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Selecciona el color secundario para el esquema seleccionado. Ctrl+clic fijará este color para todo el esquema
STR_LIVERY_PANEL_TOOLTIP :{BLACK}Selecciona un esquema de color a modificar, o selecciona varios pulsando Ctrl+Clic. Pulsa en la caja para cambiar el uso del esquema STR_LIVERY_PANEL_TOOLTIP :{BLACK}Selecciona un esquema de color a modificar, o selecciona varios pulsando Ctrl+clic. Pulsa en la caja para cambiar el uso del esquema
STR_LIVERY_DEFAULT :Estación Normal STR_LIVERY_DEFAULT :Estación Normal
STR_LIVERY_STEAM :Locomotora a Vapor STR_LIVERY_STEAM :Locomotora a Vapor
@@ -2359,15 +2359,15 @@ STR_MISSING_GRAPHICS_ERROR_QUIT :{BLACK}Salir de
# Transparency settings window # Transparency settings window
STR_TRANSPARENCY_CAPTION :{WHITE}Opciones de Transparencia STR_TRANSPARENCY_CAPTION :{WHITE}Opciones de Transparencia
STR_TRANSPARENT_SIGNS_TOOLTIP :{BLACK}Ajustar transparencia para carteles. Ctrl+Clic para bloquear STR_TRANSPARENT_SIGNS_TOOLTIP :{BLACK}Ajustar transparencia para carteles. Ctrl+clic para bloquear
STR_TRANSPARENT_TREES_TOOLTIP :{BLACK}Ajustar transparencia para árboles. Ctrl+Clic para bloquear STR_TRANSPARENT_TREES_TOOLTIP :{BLACK}Ajustar transparencia para árboles. Ctrl+clic para bloquear
STR_TRANSPARENT_HOUSES_TOOLTIP :{BLACK}Ajustar transparencia para casas. Ctrl+Clic para bloquear STR_TRANSPARENT_HOUSES_TOOLTIP :{BLACK}Ajustar transparencia para casas. Ctrl+clic para bloquear
STR_TRANSPARENT_INDUSTRIES_TOOLTIP :{BLACK}Ajustar transparencia para industrias. Ctrl+Clic para bloquear STR_TRANSPARENT_INDUSTRIES_TOOLTIP :{BLACK}Ajustar transparencia para industrias. Ctrl+clic para bloquear
STR_TRANSPARENT_BUILDINGS_TOOLTIP :{BLACK}Ajustar transparencia para construcciones como estaciones, depósitos o puntos de ruta. Ctrl+Clic para bloquear STR_TRANSPARENT_BUILDINGS_TOOLTIP :{BLACK}Ajustar transparencia para construcciones como estaciones, depósitos o puntos de ruta. Ctrl+clic para bloquear
STR_TRANSPARENT_BRIDGES_TOOLTIP :{BLACK}Ajustar transparencia para puentes. Ctrl+Clic para bloquear STR_TRANSPARENT_BRIDGES_TOOLTIP :{BLACK}Ajustar transparencia para puentes. Ctrl+clic para bloquear
STR_TRANSPARENT_STRUCTURES_TOOLTIP :{BLACK}Ajustar transparencia para estructuras como faros o antenas. Ctrl+Clic para bloquear STR_TRANSPARENT_STRUCTURES_TOOLTIP :{BLACK}Ajustar transparencia para estructuras como faros o antenas. Ctrl+clic para bloquear
STR_TRANSPARENT_CATENARY_TOOLTIP :{BLACK}Ajustar transparencia para catenaria. Ctrl+Clic para bloquear STR_TRANSPARENT_CATENARY_TOOLTIP :{BLACK}Ajustar transparencia para catenaria. Ctrl+clic para bloquear
STR_TRANSPARENT_LOADING_TOOLTIP :{BLACK}Ajustar transparencia para los indicadores de carga. Ctrl+Clic para bloquear STR_TRANSPARENT_LOADING_TOOLTIP :{BLACK}Ajustar transparencia para los indicadores de carga. Ctrl+clic para bloquear
STR_TRANSPARENT_INVISIBLE_TOOLTIP :{BLACK}Establece los objetos como invisibles en vez de transparentes STR_TRANSPARENT_INVISIBLE_TOOLTIP :{BLACK}Establece los objetos como invisibles en vez de transparentes
# Linkgraph legend window # Linkgraph legend window
@@ -3069,7 +3069,7 @@ STR_SPRITE_ALIGNER_GOTO_TOOLTIP :{BLACK}Va al sp
STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Sprite anterior STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Sprite anterior
STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Salta al sprite anterior (ignorando pseudosprites, sprites recoloreados y sprites de fuente) y pasa del primer al último sprite STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Salta al sprite anterior (ignorando pseudosprites, sprites recoloreados y sprites de fuente) y pasa del primer al último sprite
STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Representa el sprite seleccionado. Su alineamiento es ignorado al dibujarlo STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Representa el sprite seleccionado. Su alineamiento es ignorado al dibujarlo
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Mover el sprite, cambiando los ajustes X e Y. Ctrl+Clic mueve el sprite ocho unidades de una sola vez STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Mover el sprite, cambiando los ajustes X e Y. Ctrl+clic mueve el sprite ocho unidades de una sola vez
STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Reiniciar coordenadas relativas STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Reiniciar coordenadas relativas
STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Reinicia las coordenadas relativas actuales STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Reinicia las coordenadas relativas actuales
STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}Coordenada X: {NUM}, Coordenada Y: {NUM} (Absoluta) STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}Coordenada X: {NUM}, Coordenada Y: {NUM} (Absoluta)
@@ -3173,7 +3173,7 @@ STR_TOWN_DIRECTORY_CAPTION :{WHITE}Municipi
STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ninguna - STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ninguna -
STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA})
STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Ciudad){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Ciudad){BLACK} ({COMMA})
STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nombres de los municipios - Clic sobre un nombre para centrar la vista principal en él. Ctrl+Clic abre una ventana de visualización en dicha posición STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nombres de los municipios - Clic sobre un nombre para centrar la vista principal en él. Ctrl+clic abre una ventana de visualización en dicha posición
STR_TOWN_POPULATION :{BLACK}Población mundial: {COMMA} STR_TOWN_POPULATION :{BLACK}Población mundial: {COMMA}
# Town view window # Town view window
@@ -3191,7 +3191,7 @@ STR_TOWN_VIEW_TOWN_GROWS_EVERY :{BLACK}El munic
STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}El municipio crece cada {ORANGE}{COMMA}{BLACK}{NBSP}día{P "" s} (edificios financiados) STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}El municipio crece cada {ORANGE}{COMMA}{BLACK}{NBSP}día{P "" s} (edificios financiados)
STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}El municipio {RED}no{BLACK} está creciendo STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}El municipio {RED}no{BLACK} está creciendo
STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Nivel de ruido en el municipio: {ORANGE}{COMMA}{BLACK} Máx.: {ORANGE}{COMMA} STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Nivel de ruido en el municipio: {ORANGE}{COMMA}{BLACK} Máx.: {ORANGE}{COMMA}
STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista sobre el municipio. Ctrl+Clic abre un punto de vista en dicha posición STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista sobre el municipio. Ctrl+clic abre un punto de vista en dicha posición
STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Autoridad local STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Autoridad local
STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Muestra la información sobre las autoridades locales STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Muestra la información sobre las autoridades locales
STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Cambia el nombre del municipio STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Cambia el nombre del municipio
@@ -3280,7 +3280,7 @@ STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{STRING
STR_SUBSIDIES_NONE :{ORANGE}- Ninguno - STR_SUBSIDIES_NONE :{ORANGE}- Ninguno -
STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}Líneas ya subvencionadas: STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}Líneas ya subvencionadas:
STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} desde {STRING} a {STRING}{YELLOW} ({COMPANY}{YELLOW}, hasta {DATE_SHORT}) STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} desde {STRING} a {STRING}{YELLOW} ({COMPANY}{YELLOW}, hasta {DATE_SHORT})
STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Clic sobre el servicio para centrar la vista principal en esta industria/municipio. Ctrl+Clic abre un punto de vista en dicha posición STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Clic sobre el servicio para centrar la vista principal en esta industria/municipio. Ctrl+clic abre un punto de vista en dicha posición
# Story book window # Story book window
STR_STORY_BOOK_CAPTION :{WHITE}Historia de {COMPANY} STR_STORY_BOOK_CAPTION :{WHITE}Historia de {COMPANY}
@@ -3296,7 +3296,7 @@ STR_STORY_BOOK_NEXT_PAGE_TOOLTIP :{BLACK}Ir a la
STR_STORY_BOOK_INVALID_GOAL_REF :{RED}Referencia de objetivo inválida STR_STORY_BOOK_INVALID_GOAL_REF :{RED}Referencia de objetivo inválida
# Station list window # Station list window
STR_STATION_LIST_TOOLTIP :{BLACK}Nombres de estación - Clic sobre un nombre para centrar la vista principal en la estación. Ctrl+Clic abre un punto de vista en dicha posición STR_STATION_LIST_TOOLTIP :{BLACK}Nombres de estación - Clic sobre un nombre para centrar la vista principal en la estación. Ctrl+clic abre un punto de vista en dicha posición
STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE :{BLACK}Mantén pulsado Ctrl para seleccionar más de un elemento STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE :{BLACK}Mantén pulsado Ctrl para seleccionar más de un elemento
STR_STATION_LIST_CAPTION :{WHITE}{COMPANY} - {COMMA} Estaciones STR_STATION_LIST_CAPTION :{WHITE}{COMPANY} - {COMMA} Estaciones
STR_STATION_LIST_STATION :{YELLOW}{STATION} {STATION_FEATURES} STR_STATION_LIST_STATION :{YELLOW}{STATION} {STATION_FEATURES}
@@ -3358,7 +3358,7 @@ STR_CARGO_RATING_EXCELLENT :Excelente
STR_CARGO_RATING_OUTSTANDING :Excepcional STR_CARGO_RATING_OUTSTANDING :Excepcional
############ range for rating ends ############ range for rating ends
STR_STATION_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista en la posición de la estación. Ctrl+Clic abre un punto de vista en dicha posición STR_STATION_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista en la posición de la estación. Ctrl+clic abre un punto de vista en dicha posición
STR_STATION_VIEW_RENAME_TOOLTIP :{BLACK}Cambia el nombre de la estación STR_STATION_VIEW_RENAME_TOOLTIP :{BLACK}Cambia el nombre de la estación
STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP :{BLACK}Muestra todos los trenes que tienen esta estación en su horario STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP :{BLACK}Muestra todos los trenes que tienen esta estación en su horario
@@ -3373,7 +3373,7 @@ STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}Evita qu
# Waypoint/buoy view window # Waypoint/buoy view window
STR_WAYPOINT_VIEW_CAPTION :{WHITE}{WAYPOINT} STR_WAYPOINT_VIEW_CAPTION :{WHITE}{WAYPOINT}
STR_WAYPOINT_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista en posición del punto de ruta. Ctrl+Clic abre un punto de vista en dicha posición STR_WAYPOINT_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista en posición del punto de ruta. Ctrl+clic abre un punto de vista en dicha posición
STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME :{BLACK}Cambiar nombre del punto de ruta STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME :{BLACK}Cambiar nombre del punto de ruta
STR_BUOY_VIEW_CENTER_TOOLTIP :{BLACK}Centra la vista en posición de la boya. Ctrl+clic abre un punto de vista en dicha posición STR_BUOY_VIEW_CENTER_TOOLTIP :{BLACK}Centra la vista en posición de la boya. Ctrl+clic abre un punto de vista en dicha posición
STR_BUOY_VIEW_CHANGE_BUOY_NAME :{BLACK}Cambiar nombre de boya STR_BUOY_VIEW_CHANGE_BUOY_NAME :{BLACK}Cambiar nombre de boya
@@ -3826,15 +3826,15 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Centra l
STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Centra la vista principal en la posición del barco. Doble clic seguirá al barco en la vista principal. Ctrl+clic abre un nuevo punto de vista en dicha posición. STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Centra la vista principal en la posición del barco. Doble clic seguirá al barco en la vista principal. Ctrl+clic abre un nuevo punto de vista en dicha posición.
STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Centra la vista principal en la posición de la aeronave. Doble clic seguirá la aeronave en la vista principal. Ctrl+clic abre un nuevo punto de vista en dicha posición. STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Centra la vista principal en la posición de la aeronave. Doble clic seguirá la aeronave en la vista principal. Ctrl+clic abre un nuevo punto de vista en dicha posición.
STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar tren al depósito. Ctrl+Clic para realizar solamente mantenimiento STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar tren al depósito. Ctrl+clic para realizar solamente mantenimiento
STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar vehículo al depósito. Ctrl+Clic para realizar solamente mantenimiento STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar vehículo al depósito. Ctrl+clic para realizar solamente mantenimiento
STR_VEHICLE_VIEW_SHIP_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar barco al astillero. Ctrl+Clic para realizar solamente mantenimiento STR_VEHICLE_VIEW_SHIP_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar barco al astillero. Ctrl+clic para realizar solamente mantenimiento
STR_VEHICLE_VIEW_AIRCRAFT_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar aeronave al hangar. Ctrl+Clic para realizar solamente mantenimiento STR_VEHICLE_VIEW_AIRCRAFT_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar aeronave al hangar. Ctrl+clic para realizar solamente mantenimiento
STR_VEHICLE_VIEW_CLONE_TRAIN_INFO :{BLACK}Esto comprará una copia del tren incluyendo sus vagones. Ctrl+Clic compartirá las órdenes. Mayús+Clic muestra una estimación del precio sin realizar la compra STR_VEHICLE_VIEW_CLONE_TRAIN_INFO :{BLACK}Esto comprará una copia del tren incluyendo sus vagones. Ctrl+clic compartirá las órdenes. Mayús+clic muestra una estimación del precio sin realizar la compra
STR_VEHICLE_VIEW_CLONE_ROAD_VEHICLE_INFO :{BLACK}Esto comprará una copia del vehículo. Ctrl+Clic compartirá las órdenes. Mayús+Clic muestra una estimación del precio sin realizar la compra STR_VEHICLE_VIEW_CLONE_ROAD_VEHICLE_INFO :{BLACK}Esto comprará una copia del vehículo. Ctrl+clic compartirá las órdenes. Mayús+clic muestra una estimación del precio sin realizar la compra
STR_VEHICLE_VIEW_CLONE_SHIP_INFO :{BLACK}Esto comprará una copia del barco. Ctrl+Clic compartirá las órdenes. Mayús+Clic muestra una estimación del precio sin realizar la compra STR_VEHICLE_VIEW_CLONE_SHIP_INFO :{BLACK}Esto comprará una copia del barco. Ctrl+clic compartirá las órdenes. Mayús+clic muestra una estimación del precio sin realizar la compra
STR_VEHICLE_VIEW_CLONE_AIRCRAFT_INFO :{BLACK}Esto comprará una copia de la aeronave. Ctrl+Clic compartirá las órdenes. Mayús+Clic muestra una estimación del precio sin realizar la compra STR_VEHICLE_VIEW_CLONE_AIRCRAFT_INFO :{BLACK}Esto comprará una copia de la aeronave. Ctrl+clic compartirá las órdenes. Mayús+clic muestra una estimación del precio sin realizar la compra
STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP :{BLACK}Fuerza al tren a proceder sin esperar a la apertura de señal STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP :{BLACK}Fuerza al tren a proceder sin esperar a la apertura de señal
@@ -3846,10 +3846,10 @@ STR_VEHICLE_VIEW_AIRCRAFT_REFIT_TOOLTIP :{BLACK}Reforma
STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP :{BLACK}Cambia la dirección del tren STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP :{BLACK}Cambia la dirección del tren
STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP :{BLACK}Fuerza al vehículo a dar la vuelta STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP :{BLACK}Fuerza al vehículo a dar la vuelta
STR_VEHICLE_VIEW_TRAIN_ORDERS_TOOLTIP :{BLACK}Ver órdenes del tren. Ctrl+Clic muestra su horario STR_VEHICLE_VIEW_TRAIN_ORDERS_TOOLTIP :{BLACK}Ver órdenes del tren. Ctrl+clic muestra su horario
STR_VEHICLE_VIEW_ROAD_VEHICLE_ORDERS_TOOLTIP :{BLACK}Ver órdenes del vehículo Ctrl+Clic muestra su horario STR_VEHICLE_VIEW_ROAD_VEHICLE_ORDERS_TOOLTIP :{BLACK}Ver órdenes del vehículo Ctrl+clic muestra su horario
STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Ver órdenes del barco. Ctrl+Clic muestra su horario STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Ver órdenes del barco. Ctrl+clic muestra su horario
STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Ver órdenes de la aeronave. Ctrl+Clic muestra su horario STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Ver órdenes de la aeronave. Ctrl+clic muestra su horario
STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Muestra los detalles del tren STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Muestra los detalles del tren
STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Muestra los detalles del vehículo STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Muestra los detalles del vehículo
@@ -3919,8 +3919,8 @@ STR_VEHICLE_INFO_FEEDER_CARGO_VALUE :{BLACK}Crédito
STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS :{BLACK}Intervalo de mantenimiento: {LTBLUE}{COMMA}{NBSP}días{BLACK} Último mantenimiento: {LTBLUE}{DATE_LONG} STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS :{BLACK}Intervalo de mantenimiento: {LTBLUE}{COMMA}{NBSP}días{BLACK} Último mantenimiento: {LTBLUE}{DATE_LONG}
STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT :{BLACK}Intervalo de mantenimiento: {LTBLUE}{COMMA}%{BLACK} Último mantenimiento: {LTBLUE}{DATE_LONG} STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT :{BLACK}Intervalo de mantenimiento: {LTBLUE}{COMMA}%{BLACK} Último mantenimiento: {LTBLUE}{DATE_LONG}
STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Incrementar intervalo de mantenimiento en 10. Ctrl+Clic incrementa el intervalo de mantenimiento en 5 STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Incrementar intervalo de mantenimiento en 10. Ctrl+clic incrementa el intervalo de mantenimiento en 5
STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Reducir intervalo de mantenimiento en 10. Ctrl+Clic reduce el intervalo de mantenimiento en 5 STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Reducir intervalo de mantenimiento en 10. Ctrl+clic reduce el intervalo de mantenimiento en 5
STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP :{BLACK}Cambia el tipo de intervalo de mantenimiento STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP :{BLACK}Cambia el tipo de intervalo de mantenimiento
STR_VEHICLE_DETAILS_DEFAULT :Por defecto STR_VEHICLE_DETAILS_DEFAULT :Por defecto

View File

@@ -1007,6 +1007,8 @@ STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Acelerac
STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Activar esta casilla para intentar emplear la aceleración por hardware. Este cambio solo tiene efecto tras reiniciar el juego STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Activar esta casilla para intentar emplear la aceleración por hardware. Este cambio solo tiene efecto tras reiniciar el juego
STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Esta configuración solo tendrá efecto después de reiniciar el juego STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Esta configuración solo tendrá efecto después de reiniciar el juego
STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}VSync
STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Activar esta casilla para realizar sincronización vertical de pantalla (VSync). Este cambio solo tiene efecto tras reiniciar el juego y si la aceleración por hardware está activada.
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Tamaño de la interfaz STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Tamaño de la interfaz
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Elegir el tamaño de los elementos de la interfaz STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Elegir el tamaño de los elementos de la interfaz

View File

@@ -1006,6 +1006,8 @@ STR_GAME_OPTIONS_VIDEO_ACCELERATION :{BLACK}Hårdvar
STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Markera denna rutan för att tillåta OpenTTD att försöka använda hårdvaruacceleration. Ändrad inställning kommer bara att gälla efter omstart. STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP :{BLACK}Markera denna rutan för att tillåta OpenTTD att försöka använda hårdvaruacceleration. Ändrad inställning kommer bara att gälla efter omstart.
STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Inställningen kommer bara att gälla efter omstart av spelet STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART :{WHITE}Inställningen kommer bara att gälla efter omstart av spelet
STR_GAME_OPTIONS_VIDEO_VSYNC :{BLACK}VSync
STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Markera den här rutan för att v-synka skärmen. Ändringar i den här inställningen kommer bara att tillämpas vid omstart av spelet. Fungerar bara med hårdvaruacceleration aktiverad.
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Gränssnittstorlek STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Gränssnittstorlek
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Välj vilken gränssnittsstorlek som ska användas STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Välj vilken gränssnittsstorlek som ska användas
@@ -3884,7 +3886,7 @@ STR_VEHICLE_COMMAND_STARTED_SMALL :{TINY_FONT}{GRE
STR_VEHICLE_COMMAND_STARTED :{GREEN}Startad STR_VEHICLE_COMMAND_STARTED :{GREEN}Startad
# Vehicle details # Vehicle details
STR_VEHICLE_DETAILS_CAPTION :{WHITE}{VEHICLE} (Details) STR_VEHICLE_DETAILS_CAPTION :{WHITE}{VEHICLE} (Detaljer)
STR_VEHICLE_NAME_BUTTON :{BLACK}Namn STR_VEHICLE_NAME_BUTTON :{BLACK}Namn
STR_VEHICLE_DETAILS_TRAIN_RENAME :{BLACK}Byt namn på tåg STR_VEHICLE_DETAILS_TRAIN_RENAME :{BLACK}Byt namn på tåg

View File

@@ -1163,12 +1163,9 @@ struct QueryWindow : public Window {
this->caption = caption; this->caption = caption;
this->message = message; this->message = message;
this->proc = callback; this->proc = callback;
this->parent = parent;
this->InitNested(WN_CONFIRM_POPUP_QUERY); this->InitNested(WN_CONFIRM_POPUP_QUERY);
this->parent = parent;
this->left = parent->left + (parent->width / 2) - (this->width / 2);
this->top = parent->top + (parent->height / 2) - (this->height / 2);
} }
~QueryWindow() ~QueryWindow()
@@ -1176,6 +1173,14 @@ struct QueryWindow : public Window {
if (this->proc != nullptr) this->proc(this->parent, false); if (this->proc != nullptr) this->proc(this->parent, false);
} }
void FindWindowPlacementAndResize(int def_width, int def_height) override
{
/* Position query window over the calling window, ensuring it's within screen bounds. */
this->left = Clamp(parent->left + (parent->width / 2) - (this->width / 2), 0, _screen.width - this->width);
this->top = Clamp(parent->top + (parent->height / 2) - (this->height / 2), 0, _screen.height - this->height);
this->SetDirty();
}
void SetStringParameters(int widget) const override void SetStringParameters(int widget) const override
{ {
switch (widget) { switch (widget) {

View File

@@ -162,15 +162,22 @@ void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song)
} }
void MusicDriver_FluidSynth::StopSong() void MusicDriver_FluidSynth::StopSong()
{
{ {
std::lock_guard<std::mutex> lock{ _midi.synth_mutex }; std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
if (!_midi.player) return; if (!_midi.player) return;
fluid_player_stop(_midi.player); fluid_player_stop(_midi.player);
}
/* The join must be run without lock as the Music rendering needs to be
* running so FluidSynth's internals can actually stop the playing. */
if (fluid_player_join(_midi.player) != FLUID_OK) { if (fluid_player_join(_midi.player) != FLUID_OK) {
DEBUG(driver, 0, "Could not join player"); DEBUG(driver, 0, "Could not join player");
} }
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
delete_fluid_player(_midi.player); delete_fluid_player(_midi.player);
fluid_synth_system_reset(_midi.synth); fluid_synth_system_reset(_midi.synth);
fluid_synth_all_sounds_off(_midi.synth, -1); fluid_synth_all_sounds_off(_midi.synth, -1);

View File

@@ -4,9 +4,11 @@ add_files(
config.h config.h
core.cpp core.cpp
core.h core.h
game.h game_info.cpp
game_info.h
host.cpp host.cpp
host.h host.h
os_abstraction.cpp
os_abstraction.h os_abstraction.h
packet.cpp packet.cpp
packet.h packet.h
@@ -17,6 +19,7 @@ add_files(
tcp_connect.cpp tcp_connect.cpp
tcp_content.cpp tcp_content.cpp
tcp_content.h tcp_content.h
tcp_content_type.h
tcp_game.cpp tcp_game.cpp
tcp_game.h tcp_game.h
tcp_http.cpp tcp_http.cpp

View File

@@ -316,7 +316,7 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, strerror(errno)); DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkError::GetLast().AsString());
return INVALID_SOCKET; return INVALID_SOCKET;
} }
@@ -326,12 +326,12 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
/* Emscripten is asynchronous, and as such a connect() is still in /* Emscripten is asynchronous, and as such a connect() is still in
* progress by the time the call returns. */ * progress by the time the call returns. */
if (err != 0 && errno != EINPROGRESS) if (err != 0 && !NetworkError::GetLast().IsConnectInProgress())
#else #else
if (err != 0) if (err != 0)
#endif #endif
{ {
DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, strerror(errno)); DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, NetworkError::GetLast().AsString());
closesocket(sock); closesocket(sock);
return INVALID_SOCKET; return INVALID_SOCKET;
} }
@@ -369,7 +369,7 @@ static SOCKET ListenLoopProc(addrinfo *runp)
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, strerror(errno)); DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, NetworkError::GetLast().AsString());
return INVALID_SOCKET; return INVALID_SOCKET;
} }
@@ -380,24 +380,24 @@ static SOCKET ListenLoopProc(addrinfo *runp)
int on = 1; int on = 1;
/* The (const char*) cast is needed for windows!! */ /* The (const char*) cast is needed for windows!! */
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) { if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) {
DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, strerror(errno)); DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, NetworkError::GetLast().AsString());
} }
#ifndef __OS2__ #ifndef __OS2__
if (runp->ai_family == AF_INET6 && if (runp->ai_family == AF_INET6 &&
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) { setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) {
DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, strerror(errno)); DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, NetworkError::GetLast().AsString());
} }
#endif #endif
if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) { if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) {
DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, strerror(errno)); DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, NetworkError::GetLast().AsString());
closesocket(sock); closesocket(sock);
return INVALID_SOCKET; return INVALID_SOCKET;
} }
if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) { if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, strerror(errno)); DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, NetworkError::GetLast().AsString());
closesocket(sock); closesocket(sock);
return INVALID_SOCKET; return INVALID_SOCKET;
} }

View File

@@ -47,32 +47,3 @@ void NetworkCoreShutdown()
WSACleanup(); WSACleanup();
#endif #endif
} }
/**
* Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
* @param p the packet to write the data to
* @param grf the GRFIdentifier to serialize
*/
void NetworkSocketHandler::SendGRFIdentifier(Packet *p, const GRFIdentifier *grf)
{
uint j;
p->Send_uint32(grf->grfid);
for (j = 0; j < sizeof(grf->md5sum); j++) {
p->Send_uint8 (grf->md5sum[j]);
}
}
/**
* Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
* @param p the packet to read the data from
* @param grf the GRFIdentifier to deserialize
*/
void NetworkSocketHandler::ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf)
{
uint j;
grf->grfid = p->Recv_uint32();
for (j = 0; j < sizeof(grf->md5sum); j++) {
grf->md5sum[j] = p->Recv_uint8();
}
}

View File

@@ -71,8 +71,6 @@ public:
*/ */
void Reopen() { this->has_quit = false; } void Reopen() { this->has_quit = false; }
void SendGRFIdentifier(Packet *p, const GRFIdentifier *grf);
void ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf);
void SendCompanyInformation(Packet *p, const struct Company *c, const struct NetworkCompanyStats *stats, uint max_len = NETWORK_COMPANY_NAME_LENGTH); void SendCompanyInformation(Packet *p, const struct Company *c, const struct NetworkCompanyStats *stats, uint max_len = NETWORK_COMPANY_NAME_LENGTH);
}; };

View File

@@ -0,0 +1,326 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file game_info.cpp Functions to convert NetworkGameInfo to Packet and back.
*/
#include "../../stdafx.h"
#include "game_info.h"
#include "../../core/bitmath_func.hpp"
#include "../../company_base.h"
#include "../../date_func.h"
#include "../../debug.h"
#include "../../map_func.h"
#include "../../settings_type.h"
#include "../../string_func.h"
#include "../../rev.h"
#include "../network_func.h"
#include "../network.h"
#include "packet.h"
#include "../../safeguards.h"
/**
* How many hex digits of the git hash to include in network revision string.
* Determined as 10 hex digits + 2 characters for -g/-u/-m prefix.
*/
static const uint GITHASH_SUFFIX_LEN = 12;
NetworkServerGameInfo _network_game_info; ///< Information about our game.
/**
* Get the network version string used by this build.
* The returned string is guaranteed to be at most NETWORK_REVISON_LENGTH bytes.
*/
const char *GetNetworkRevisionString()
{
/* This will be allocated on heap and never free'd, but only once so not a "real" leak. */
static char *network_revision = nullptr;
if (!network_revision) {
/* Start by taking a chance on the full revision string. */
network_revision = stredup(_openttd_revision);
/* Ensure it's not longer than the packet buffer length. */
if (strlen(network_revision) >= NETWORK_REVISION_LENGTH) network_revision[NETWORK_REVISION_LENGTH - 1] = '\0';
/* Tag names are not mangled further. */
if (_openttd_revision_tagged) {
DEBUG(net, 1, "Network revision name is '%s'", network_revision);
return network_revision;
}
/* Prepare a prefix of the git hash.
* Size is length + 1 for terminator, +2 for -g prefix. */
assert(_openttd_revision_modified < 3);
char githash_suffix[GITHASH_SUFFIX_LEN + 1] = "-";
githash_suffix[1] = "gum"[_openttd_revision_modified];
for (uint i = 2; i < GITHASH_SUFFIX_LEN; i++) {
githash_suffix[i] = _openttd_revision_hash[i-2];
}
/* Where did the hash start in the original string?
* Overwrite from that position, unless that would go past end of packet buffer length. */
ptrdiff_t hashofs = strrchr(_openttd_revision, '-') - _openttd_revision;
if (hashofs + strlen(githash_suffix) + 1 > NETWORK_REVISION_LENGTH) hashofs = strlen(network_revision) - strlen(githash_suffix);
/* Replace the git hash in revision string. */
strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH);
assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than
DEBUG(net, 1, "Network revision name is '%s'", network_revision);
}
return network_revision;
}
/**
* Extract the git hash from the revision string.
* @param revstr The revision string (formatted as DATE-BRANCH-GITHASH).
* @return The git has part of the revision.
*/
static const char *ExtractNetworkRevisionHash(const char *revstr)
{
return strrchr(revstr, '-');
}
/**
* Checks whether the given version string is compatible with our version.
* First tries to match the full string, if that fails, attempts to compare just git hashes.
* @param other the version string to compare to
*/
bool IsNetworkCompatibleVersion(const char *other)
{
if (strncmp(GetNetworkRevisionString(), other, NETWORK_REVISION_LENGTH - 1) == 0) return true;
/* If this version is tagged, then the revision string must be a complete match,
* since there is no git hash suffix in it.
* This is needed to avoid situations like "1.9.0-beta1" comparing equal to "2.0.0-beta1". */
if (_openttd_revision_tagged) return false;
const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString());
const char *hash2 = ExtractNetworkRevisionHash(other);
return hash1 != nullptr && hash2 != nullptr && strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0;
}
/**
* Fill a NetworkGameInfo structure with the latest information of the server.
* @param ngi the NetworkGameInfo struct to fill with data.
*/
void FillNetworkGameInfo(NetworkGameInfo &ngi)
{
/* Update some game_info */
ngi.clients_on = _network_game_info.clients_on;
ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
ngi.server_lang = _settings_client.network.server_lang;
ngi.use_password = !StrEmpty(_settings_client.network.server_password);
ngi.clients_max = _settings_client.network.max_clients;
ngi.companies_on = (byte)Company::GetNumItems();
ngi.companies_max = _settings_client.network.max_companies;
ngi.spectators_on = NetworkSpectatorCount();
ngi.spectators_max = _settings_client.network.max_spectators;
ngi.game_date = _date;
ngi.map_width = MapSizeX();
ngi.map_height = MapSizeY();
ngi.map_set = _settings_game.game_creation.landscape;
ngi.dedicated = _network_dedicated;
ngi.grfconfig = _grfconfig;
strecpy(ngi.map_name, _network_game_info.map_name, lastof(ngi.map_name));
strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name));
strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision));
}
/**
* 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.
*/
static void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
{
/* Find the matching GRF file */
const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum);
if (f == nullptr) {
/* 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->ident.grfid, config->ident.md5sum, true);
config->status = GCS_NOT_FOUND;
} else {
config->filename = f->filename;
config->name = f->name;
config->info = f->info;
config->url = f->url;
}
SetBit(config->flags, GCF_COPY);
}
/**
* Serializes the NetworkGameInfo struct to the packet.
* @param p the packet to write the data to.
* @param info the NetworkGameInfo struct to serialize from.
*/
void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
{
p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
/*
* Please observe the order.
* The parts must be read in the same order as they are sent!
*/
/* Update the documentation in game_info.h on changes
* to the NetworkGameInfo wire-protocol! */
/* 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 != nullptr; c = c->next) {
if (!HasBit(c->flags, GCF_STATIC)) count++;
}
p->Send_uint8 (count); // Send number of GRFs
/* Send actual GRF Identifications */
for (c = info->grfconfig; c != nullptr; c = c->next) {
if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(p, &c->ident);
}
}
/* NETWORK_GAME_INFO_VERSION = 3 */
p->Send_uint32(info->game_date);
p->Send_uint32(info->start_date);
/* NETWORK_GAME_INFO_VERSION = 2 */
p->Send_uint8 (info->companies_max);
p->Send_uint8 (info->companies_on);
p->Send_uint8 (info->spectators_max);
/* NETWORK_GAME_INFO_VERSION = 1 */
p->Send_string(info->server_name);
p->Send_string(info->server_revision);
p->Send_uint8 (info->server_lang);
p->Send_bool (info->use_password);
p->Send_uint8 (info->clients_max);
p->Send_uint8 (info->clients_on);
p->Send_uint8 (info->spectators_on);
p->Send_string(info->map_name);
p->Send_uint16(info->map_width);
p->Send_uint16(info->map_height);
p->Send_uint8 (info->map_set);
p->Send_bool (info->dedicated);
}
/**
* Deserializes the NetworkGameInfo struct from the packet.
* @param p the packet to read the data from.
* @param info the NetworkGameInfo to deserialize into.
*/
void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info)
{
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
info->game_info_version = p->Recv_uint8();
/*
* Please observe the order.
* The parts must be read in the same order as they are sent!
*/
/* Update the documentation in game_info.h on changes
* to the NetworkGameInfo wire-protocol! */
switch (info->game_info_version) {
case 4: {
GRFConfig **dst = &info->grfconfig;
uint i;
uint num_grfs = p->Recv_uint8();
/* Broken/bad data. It cannot have that many NewGRFs. */
if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
for (i = 0; i < num_grfs; i++) {
GRFConfig *c = new GRFConfig();
DeserializeGRFIdentifier(p, &c->ident);
HandleIncomingNetworkGameInfoGRFConfig(c);
/* Append GRFConfig to the list */
*dst = c;
dst = &c->next;
}
FALLTHROUGH;
}
case 3:
info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
FALLTHROUGH;
case 2:
info->companies_max = p->Recv_uint8 ();
info->companies_on = p->Recv_uint8 ();
info->spectators_max = p->Recv_uint8 ();
FALLTHROUGH;
case 1:
p->Recv_string(info->server_name, sizeof(info->server_name));
p->Recv_string(info->server_revision, sizeof(info->server_revision));
info->server_lang = p->Recv_uint8 ();
info->use_password = p->Recv_bool ();
info->clients_max = p->Recv_uint8 ();
info->clients_on = p->Recv_uint8 ();
info->spectators_on = p->Recv_uint8 ();
if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
}
p->Recv_string(info->map_name, sizeof(info->map_name));
info->map_width = p->Recv_uint16();
info->map_height = p->Recv_uint16();
info->map_set = p->Recv_uint8 ();
info->dedicated = p->Recv_bool ();
if (info->server_lang >= NETWORK_NUM_LANGUAGES) info->server_lang = 0;
if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
}
}
/**
* Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
* @param p the packet to write the data to.
* @param grf the GRFIdentifier to serialize.
*/
void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf)
{
uint j;
p->Send_uint32(grf->grfid);
for (j = 0; j < sizeof(grf->md5sum); j++) {
p->Send_uint8(grf->md5sum[j]);
}
}
/**
* Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
* @param p the packet to read the data from.
* @param grf the GRFIdentifier to deserialize.
*/
void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf)
{
uint j;
grf->grfid = p->Recv_uint32();
for (j = 0; j < sizeof(grf->md5sum); j++) {
grf->md5sum[j] = p->Recv_uint8();
}
}

View File

@@ -0,0 +1,107 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file game_info.h Convert NetworkGameInfo to Packet and back.
*/
#ifndef NETWORK_CORE_GAME_INFO_H
#define NETWORK_CORE_GAME_INFO_H
#include "config.h"
#include "core.h"
#include "../../newgrf_config.h"
#include "../../date_type.h"
/*
* NetworkGameInfo has several revisions which we still need to support on the
* wire. The table below shows the version and size for each field of the
* serialized NetworkGameInfo.
*
* Version: Bytes: Description:
* all 1 the version of this packet's structure
*
* 4+ 1 number of GRFs attached (n)
* 4+ n * 20 unique identifier for GRF files. Consists of:
* - one 4 byte variable with the GRF ID
* - 16 bytes (sent sequentially) for the MD5 checksum
* of the GRF
*
* 3+ 4 current game date in days since 1-1-0 (DMY)
* 3+ 4 game introduction date in days since 1-1-0 (DMY)
*
* 2+ 1 maximum number of companies allowed on the server
* 2+ 1 number of companies on the server
* 2+ 1 maximum number of spectators allowed on the server
*
* 1+ var string with the name of the server
* 1+ var string with the revision of the server
* 1+ 1 the language run on the server
* (0 = any, 1 = English, 2 = German, 3 = French)
* 1+ 1 whether the server uses a password (0 = no, 1 = yes)
* 1+ 1 maximum number of clients allowed on the server
* 1+ 1 number of clients on the server
* 1+ 1 number of spectators on the server
* 1 & 2 2 current game date in days since 1-1-1920 (DMY)
* 1 & 2 2 game introduction date in days since 1-1-1920 (DMY)
* 1+ var string with the name of the map
* 1+ 2 width of the map in tiles
* 1+ 2 height of the map in tiles
* 1+ 1 type of map:
* (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland)
* 1+ 1 whether the server is dedicated (0 = no, 1 = yes)
*/
/**
* The game information that is not generated on-the-fly and has to
* be sent to the clients.
*/
struct NetworkServerGameInfo {
char map_name[NETWORK_NAME_LENGTH]; ///< Map which is played ["random" for a randomized map]
byte clients_on; ///< Current count of clients on server
};
/**
* The game information that is sent from the server to the clients.
*/
struct NetworkGameInfo : NetworkServerGameInfo {
GRFConfig *grfconfig; ///< List of NewGRF files used
Date start_date; ///< When the game started
Date game_date; ///< Current date
uint16 map_width; ///< Map width
uint16 map_height; ///< Map height
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 dedicated; ///< Is this a dedicated server?
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
bool use_password; ///< Is this server passworded?
byte game_info_version; ///< Version of the game info
byte server_lang; ///< Language of the server (we should make a nice table for this)
byte clients_max; ///< Max clients allowed on server
byte companies_on; ///< How many started companies do we have
byte companies_max; ///< Max companies allowed on server
byte spectators_on; ///< How many spectators do we have?
byte spectators_max; ///< Max spectators allowed on server
byte map_set; ///< Graphical set
};
extern NetworkServerGameInfo _network_game_info;
const char *GetNetworkRevisionString();
bool IsNetworkCompatibleVersion(const char *other);
void FillNetworkGameInfo(NetworkGameInfo &ngi);
void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf);
void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf);
void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info);
void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info);
#endif /* NETWORK_CORE_GAME_INFO_H */

View File

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

View File

@@ -14,6 +14,28 @@
#ifndef NETWORK_CORE_OS_ABSTRACTION_H #ifndef NETWORK_CORE_OS_ABSTRACTION_H
#define NETWORK_CORE_OS_ABSTRACTION_H #define NETWORK_CORE_OS_ABSTRACTION_H
#include <string>
/**
* Abstraction of a network error where all implementation details of the
* error codes are encapsulated in this class and the abstraction layer.
*/
class NetworkError {
private:
int error; ///< The underlying error number from errno or WSAGetLastError.
mutable std::string message; ///< The string representation of the error (set on first call to #AsString).
public:
NetworkError(int error);
bool HasError() const;
bool WouldBlock() const;
bool IsConnectionReset() const;
bool IsConnectInProgress() const;
const char *AsString() const;
static NetworkError GetLast();
};
/* Include standard stuff per OS */ /* Include standard stuff per OS */
/* Windows stuff */ /* Windows stuff */
@@ -23,9 +45,6 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <windows.h> #include <windows.h>
#define GET_LAST_ERROR() WSAGetLastError()
#undef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
/* Windows has some different names for some types */ /* Windows has some different names for some types */
typedef unsigned long in_addr_t; typedef unsigned long in_addr_t;
@@ -49,9 +68,7 @@ typedef unsigned long in_addr_t;
# endif # endif
# define SOCKET int # define SOCKET int
# define INVALID_SOCKET -1 # define INVALID_SOCKET -1
# define ioctlsocket ioctl
# define closesocket close # define closesocket close
# define GET_LAST_ERROR() (errno)
/* Need this for FIONREAD on solaris */ /* Need this for FIONREAD on solaris */
# define BSD_COMP # define BSD_COMP
@@ -99,9 +116,7 @@ typedef unsigned long in_addr_t;
#if defined(__OS2__) #if defined(__OS2__)
# define SOCKET int # define SOCKET int
# define INVALID_SOCKET -1 # define INVALID_SOCKET -1
# define ioctlsocket ioctl
# define closesocket close # define closesocket close
# define GET_LAST_ERROR() (sock_errno())
/* Includes needed for OS/2 systems */ /* Includes needed for OS/2 systems */
# include <types.h> # include <types.h>
@@ -173,41 +188,10 @@ static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address
} }
#endif #endif
/**
* Try to set the socket into non-blocking mode.
* @param d The socket to set the non-blocking more for.
* @return True if setting the non-blocking mode succeeded, otherwise false.
*/
static inline bool SetNonBlocking(SOCKET d)
{
#ifdef __EMSCRIPTEN__
return true;
#else
# ifdef _WIN32
u_long nonblocking = 1;
# else
int nonblocking = 1;
# endif
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
#endif
}
/** bool SetNonBlocking(SOCKET d);
* Try to set the socket to not delay sending. bool SetNoDelay(SOCKET d);
* @param d The socket to disable the delaying for. NetworkError GetSocketError(SOCKET d);
* @return True if disabling the delaying succeeded, otherwise false.
*/
static inline bool SetNoDelay(SOCKET d)
{
#ifdef __EMSCRIPTEN__
return true;
#else
/* XXX should this be done at all? */
int b = 1;
/* The (const char*) cast is needed for windows */
return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
#endif
}
/* Make sure these structures have the size we expect them to be */ /* Make sure these structures have the size we expect them to be */
static_assert(sizeof(in_addr) == 4); ///< IPv4 addresses should be 4 bytes. static_assert(sizeof(in_addr) == 4); ///< IPv4 addresses should be 4 bytes.

View File

@@ -105,11 +105,11 @@ SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down)
while (p != nullptr) { while (p != nullptr) {
res = send(this->sock, (const char*)p->buffer + p->pos, p->size - p->pos, 0); res = send(this->sock, (const char*)p->buffer + p->pos, p->size - p->pos, 0);
if (res == -1) { if (res == -1) {
int err = GET_LAST_ERROR(); NetworkError err = NetworkError::GetLast();
if (err != EWOULDBLOCK) { if (!err.WouldBlock()) {
/* Something went wrong.. close client! */ /* Something went wrong.. close client! */
if (!closing_down) { if (!closing_down) {
DEBUG(net, 0, "send failed with error %d", err); DEBUG(net, 0, "send failed with error %s", err.AsString());
this->CloseConnection(); this->CloseConnection();
} }
return SPS_CLOSED; return SPS_CLOSED;
@@ -160,10 +160,10 @@ Packet *NetworkTCPSocketHandler::ReceivePacket()
/* Read the size of the packet */ /* Read the size of the packet */
res = recv(this->sock, (char*)p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0); res = recv(this->sock, (char*)p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0);
if (res == -1) { if (res == -1) {
int err = GET_LAST_ERROR(); NetworkError err = NetworkError::GetLast();
if (err != EWOULDBLOCK) { if (!err.WouldBlock()) {
/* Something went wrong... (104 is connection reset by peer) */ /* Something went wrong... */
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err); if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString());
this->CloseConnection(); this->CloseConnection();
return nullptr; return nullptr;
} }
@@ -191,10 +191,10 @@ Packet *NetworkTCPSocketHandler::ReceivePacket()
while (p->pos < p->size) { while (p->pos < p->size) {
res = recv(this->sock, (char*)p->buffer + p->pos, p->size - p->pos, 0); res = recv(this->sock, (char*)p->buffer + p->pos, p->size - p->pos, 0);
if (res == -1) { if (res == -1) {
int err = GET_LAST_ERROR(); NetworkError err = NetworkError::GetLast();
if (err != EWOULDBLOCK) { if (!err.WouldBlock()) {
/* Something went wrong... (104 is connection reset by peer) */ /* Something went wrong... */
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err); if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString());
this->CloseConnection(); this->CloseConnection();
return nullptr; return nullptr;
} }

View File

@@ -16,81 +16,7 @@
#include "tcp.h" #include "tcp.h"
#include "packet.h" #include "packet.h"
#include "../../debug.h" #include "../../debug.h"
#include "tcp_content_type.h"
/** The values in the enum are important; they are used as database 'keys' */
enum ContentType {
CONTENT_TYPE_BEGIN = 1, ///< Helper to mark the begin of the types
CONTENT_TYPE_BASE_GRAPHICS = 1, ///< The content consists of base graphics
CONTENT_TYPE_NEWGRF = 2, ///< The content consists of a NewGRF
CONTENT_TYPE_AI = 3, ///< The content consists of an AI
CONTENT_TYPE_AI_LIBRARY = 4, ///< The content consists of an AI library
CONTENT_TYPE_SCENARIO = 5, ///< The content consists of a scenario
CONTENT_TYPE_HEIGHTMAP = 6, ///< The content consists of a heightmap
CONTENT_TYPE_BASE_SOUNDS = 7, ///< The content consists of base sounds
CONTENT_TYPE_BASE_MUSIC = 8, ///< The content consists of base music
CONTENT_TYPE_GAME = 9, ///< The content consists of a game script
CONTENT_TYPE_GAME_LIBRARY = 10, ///< The content consists of a GS library
CONTENT_TYPE_END, ///< Helper to mark the end of the types
};
/** Enum with all types of TCP content packets. The order MUST not be changed **/
enum PacketContentType {
PACKET_CONTENT_CLIENT_INFO_LIST, ///< Queries the content server for a list of info of a given content type
PACKET_CONTENT_CLIENT_INFO_ID, ///< Queries the content server for information about a list of internal IDs
PACKET_CONTENT_CLIENT_INFO_EXTID, ///< Queries the content server for information about a list of external IDs
PACKET_CONTENT_CLIENT_INFO_EXTID_MD5, ///< Queries the content server for information about a list of external IDs and MD5
PACKET_CONTENT_SERVER_INFO, ///< Reply of content server with information about content
PACKET_CONTENT_CLIENT_CONTENT, ///< Request a content file given an internal ID
PACKET_CONTENT_SERVER_CONTENT, ///< Reply with the content of the given ID
PACKET_CONTENT_END, ///< Must ALWAYS be on the end of this list!! (period)
};
/** Unique identifier for the content. */
enum ContentID {
INVALID_CONTENT_ID = UINT32_MAX, ///< Sentinel for invalid content.
};
/** Container for all important information about a piece of content. */
struct ContentInfo {
/** The state the content can be in. */
enum State {
UNSELECTED, ///< The content has not been selected
SELECTED, ///< The content has been manually selected
AUTOSELECTED, ///< The content has been selected as dependency
ALREADY_HERE, ///< The content is already at the client side
DOES_NOT_EXIST, ///< The content does not exist in the content system
INVALID, ///< The content's invalid
};
ContentType type; ///< Type of content
ContentID id; ///< Unique (server side) ID for the content
uint32 filesize; ///< Size of the file
char filename[48]; ///< Filename (for the .tar.gz; only valid on download)
char name[32]; ///< Name of the content
char version[16]; ///< Version of the content
char url[96]; ///< URL related to the content
char description[512]; ///< Description of the content
uint32 unique_id; ///< Unique ID; either GRF ID or shortname
byte md5sum[16]; ///< The MD5 checksum
uint8 dependency_count; ///< Number of dependencies
ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids)
uint8 tag_count; ///< Number of tags
char (*tags)[32]; ///< Malloced array of tags (strings)
State state; ///< Whether the content info is selected (for download)
bool upgrade; ///< This item is an upgrade
ContentInfo();
~ContentInfo();
void TransferFrom(ContentInfo *other);
size_t Size() const;
bool IsSelected() const;
bool IsValid() const;
#ifndef OPENTTD_MSU
const char *GetTextfile(TextfileType type) const;
#endif /* OPENTTD_MSU */
};
/** Base socket handler for all Content TCP sockets */ /** Base socket handler for all Content TCP sockets */
class NetworkContentSocketHandler : public NetworkTCPSocketHandler { class NetworkContentSocketHandler : public NetworkTCPSocketHandler {

View File

@@ -0,0 +1,90 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file tcp_content_type.h Basic types related to the content on the content server.
*/
#ifndef NETWORK_CORE_TCP_CONTENT_TYPE_H
#define NETWORK_CORE_TCP_CONTENT_TYPE_H
/** The values in the enum are important; they are used as database 'keys' */
enum ContentType {
CONTENT_TYPE_BEGIN = 1, ///< Helper to mark the begin of the types
CONTENT_TYPE_BASE_GRAPHICS = 1, ///< The content consists of base graphics
CONTENT_TYPE_NEWGRF = 2, ///< The content consists of a NewGRF
CONTENT_TYPE_AI = 3, ///< The content consists of an AI
CONTENT_TYPE_AI_LIBRARY = 4, ///< The content consists of an AI library
CONTENT_TYPE_SCENARIO = 5, ///< The content consists of a scenario
CONTENT_TYPE_HEIGHTMAP = 6, ///< The content consists of a heightmap
CONTENT_TYPE_BASE_SOUNDS = 7, ///< The content consists of base sounds
CONTENT_TYPE_BASE_MUSIC = 8, ///< The content consists of base music
CONTENT_TYPE_GAME = 9, ///< The content consists of a game script
CONTENT_TYPE_GAME_LIBRARY = 10, ///< The content consists of a GS library
CONTENT_TYPE_END, ///< Helper to mark the end of the types
};
/** Enum with all types of TCP content packets. The order MUST not be changed **/
enum PacketContentType {
PACKET_CONTENT_CLIENT_INFO_LIST, ///< Queries the content server for a list of info of a given content type
PACKET_CONTENT_CLIENT_INFO_ID, ///< Queries the content server for information about a list of internal IDs
PACKET_CONTENT_CLIENT_INFO_EXTID, ///< Queries the content server for information about a list of external IDs
PACKET_CONTENT_CLIENT_INFO_EXTID_MD5, ///< Queries the content server for information about a list of external IDs and MD5
PACKET_CONTENT_SERVER_INFO, ///< Reply of content server with information about content
PACKET_CONTENT_CLIENT_CONTENT, ///< Request a content file given an internal ID
PACKET_CONTENT_SERVER_CONTENT, ///< Reply with the content of the given ID
PACKET_CONTENT_END, ///< Must ALWAYS be on the end of this list!! (period)
};
/** Unique identifier for the content. */
enum ContentID {
INVALID_CONTENT_ID = UINT32_MAX, ///< Sentinel for invalid content.
};
/** Container for all important information about a piece of content. */
struct ContentInfo {
/** The state the content can be in. */
enum State {
UNSELECTED, ///< The content has not been selected
SELECTED, ///< The content has been manually selected
AUTOSELECTED, ///< The content has been selected as dependency
ALREADY_HERE, ///< The content is already at the client side
DOES_NOT_EXIST, ///< The content does not exist in the content system
INVALID, ///< The content's invalid
};
ContentType type; ///< Type of content
ContentID id; ///< Unique (server side) ID for the content
uint32 filesize; ///< Size of the file
char filename[48]; ///< Filename (for the .tar.gz; only valid on download)
char name[32]; ///< Name of the content
char version[16]; ///< Version of the content
char url[96]; ///< URL related to the content
char description[512]; ///< Description of the content
uint32 unique_id; ///< Unique ID; either GRF ID or shortname
byte md5sum[16]; ///< The MD5 checksum
uint8 dependency_count; ///< Number of dependencies
ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids)
uint8 tag_count; ///< Number of tags
char (*tags)[32]; ///< Malloced array of tags (strings)
State state; ///< Whether the content info is selected (for download)
bool upgrade; ///< This item is an upgrade
ContentInfo();
~ContentInfo();
void TransferFrom(ContentInfo *other);
size_t Size() const;
bool IsSelected() const;
bool IsValid() const;
#ifndef OPENTTD_MSU
const char *GetTextfile(TextfileType type) const;
#endif /* OPENTTD_MSU */
};
#endif /* NETWORK_CORE_TCP_CONTENT_TYPE_H */

View File

@@ -71,6 +71,8 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet *p)
case PACKET_SERVER_BANNED: return this->Receive_SERVER_BANNED(p); case PACKET_SERVER_BANNED: return this->Receive_SERVER_BANNED(p);
case PACKET_CLIENT_JOIN: return this->Receive_CLIENT_JOIN(p); case PACKET_CLIENT_JOIN: return this->Receive_CLIENT_JOIN(p);
case PACKET_SERVER_ERROR: return this->Receive_SERVER_ERROR(p); case PACKET_SERVER_ERROR: return this->Receive_SERVER_ERROR(p);
case PACKET_CLIENT_GAME_INFO: return this->Receive_CLIENT_GAME_INFO(p);
case PACKET_SERVER_GAME_INFO: return this->Receive_SERVER_GAME_INFO(p);
case PACKET_CLIENT_COMPANY_INFO: return this->Receive_CLIENT_COMPANY_INFO(p); case PACKET_CLIENT_COMPANY_INFO: return this->Receive_CLIENT_COMPANY_INFO(p);
case PACKET_SERVER_COMPANY_INFO: return this->Receive_SERVER_COMPANY_INFO(p); case PACKET_SERVER_COMPANY_INFO: return this->Receive_SERVER_COMPANY_INFO(p);
case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(p); case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(p);
@@ -157,6 +159,8 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p) { ret
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_BANNED); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_BANNED); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_JOIN); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_JOIN); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_ERROR); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_ERROR); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_INFO); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_INFO); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_INFO); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); }

View File

@@ -24,7 +24,7 @@
*/ */
enum PacketGameType { enum PacketGameType {
/* /*
* These first three pair of packets (thus six in * These first four pair of packets (thus eight in
* total) must remain in this order for backward * total) must remain in this order for backward
* and forward compatibility between clients that * and forward compatibility between clients that
* are trying to join directly. * are trying to join directly.
@@ -42,6 +42,10 @@ enum PacketGameType {
PACKET_CLIENT_COMPANY_INFO, ///< Request information about all companies. PACKET_CLIENT_COMPANY_INFO, ///< Request information about all companies.
PACKET_SERVER_COMPANY_INFO, ///< Information about a single company. PACKET_SERVER_COMPANY_INFO, ///< Information about a single company.
/* Packets used to get the game info. */
PACKET_SERVER_GAME_INFO, ///< Information about the server.
PACKET_CLIENT_GAME_INFO, ///< Request information about the server.
/* /*
* Packets after here assume that the client * Packets after here assume that the client
* and server are running the same version. As * and server are running the same version. As
@@ -183,6 +187,19 @@ protected:
*/ */
virtual NetworkRecvStatus Receive_SERVER_ERROR(Packet *p); virtual NetworkRecvStatus Receive_SERVER_ERROR(Packet *p);
/**
* Request game information.
* @param p The packet that was just received.
*/
virtual NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet *p);
/**
* Sends information about the game.
* Serialized NetworkGameInfo. See game_info.h for details.
* @param p The packet that was just received.
*/
virtual NetworkRecvStatus Receive_SERVER_GAME_INFO(Packet *p);
/** /**
* Request company information (in detail). * Request company information (in detail).
* @param p The packet that was just received. * @param p The packet that was just received.

View File

@@ -13,6 +13,7 @@
#include "../../debug.h" #include "../../debug.h"
#include "../../rev.h" #include "../../rev.h"
#include "../network_func.h" #include "../network_func.h"
#include "game_info.h"
#include "tcp_http.h" #include "tcp_http.h"
@@ -230,10 +231,10 @@ int NetworkHTTPSocketHandler::Receive()
for (;;) { for (;;) {
ssize_t res = recv(this->sock, (char *)this->recv_buffer + this->recv_pos, lengthof(this->recv_buffer) - this->recv_pos, 0); ssize_t res = recv(this->sock, (char *)this->recv_buffer + this->recv_pos, lengthof(this->recv_buffer) - this->recv_pos, 0);
if (res == -1) { if (res == -1) {
int err = GET_LAST_ERROR(); NetworkError err = NetworkError::GetLast();
if (err != EWOULDBLOCK) { if (!err.WouldBlock()) {
/* Something went wrong... (104 is connection reset by peer) */ /* Something went wrong... */
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err); if (!err.IsConnectionReset()) DEBUG(net, 0, "recv failed with error %s", err.AsString());
return -1; return -1;
} }
/* Connection would block, so stop for now */ /* Connection would block, so stop for now */

View File

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

View File

@@ -12,6 +12,7 @@
#include "../../stdafx.h" #include "../../stdafx.h"
#include "../../date_func.h" #include "../../date_func.h"
#include "../../debug.h" #include "../../debug.h"
#include "game_info.h"
#include "udp.h" #include "udp.h"
#include "../../safeguards.h" #include "../../safeguards.h"
@@ -94,7 +95,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
/* Enable broadcast */ /* Enable broadcast */
unsigned long val = 1; unsigned long val = 1;
if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) { if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
DEBUG(net, 1, "[udp] setting broadcast failed with: %i", GET_LAST_ERROR()); DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkError::GetLast().AsString());
} }
} }
@@ -103,7 +104,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString().c_str()); DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString().c_str());
/* Check for any errors, but ignore it otherwise */ /* Check for any errors, but ignore it otherwise */
if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", send.GetAddressAsString().c_str(), GET_LAST_ERROR()); if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", send.GetAddressAsString().c_str(), NetworkError::GetLast().AsString());
if (!all) break; if (!all) break;
} }
@@ -149,143 +150,6 @@ void NetworkUDPSocketHandler::ReceivePackets()
} }
} }
/**
* Serializes the NetworkGameInfo struct to the packet
* @param p the packet to write the data to
* @param info the NetworkGameInfo struct to serialize
*/
void NetworkUDPSocketHandler::SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
{
p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
/*
* Please observe the order.
* The parts must be read in the same order as they are sent!
*/
/* Update the documentation in udp.h on changes
* to the NetworkGameInfo wire-protocol! */
/* 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 != nullptr; c = c->next) {
if (!HasBit(c->flags, GCF_STATIC)) count++;
}
p->Send_uint8 (count); // Send number of GRFs
/* Send actual GRF Identifications */
for (c = info->grfconfig; c != nullptr; c = c->next) {
if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
}
}
/* NETWORK_GAME_INFO_VERSION = 3 */
p->Send_uint32(info->game_date);
p->Send_uint32(info->start_date);
/* NETWORK_GAME_INFO_VERSION = 2 */
p->Send_uint8 (info->companies_max);
p->Send_uint8 (info->companies_on);
p->Send_uint8 (info->spectators_max);
/* NETWORK_GAME_INFO_VERSION = 1 */
p->Send_string(info->server_name);
p->Send_string(info->server_revision);
p->Send_uint8 (info->server_lang);
p->Send_bool (info->use_password);
p->Send_uint8 (info->clients_max);
p->Send_uint8 (info->clients_on);
p->Send_uint8 (info->spectators_on);
p->Send_string(info->map_name);
p->Send_uint16(info->map_width);
p->Send_uint16(info->map_height);
p->Send_uint8 (info->map_set);
p->Send_bool (info->dedicated);
}
/**
* Deserializes the NetworkGameInfo struct from the packet
* @param p the packet to read the data from
* @param info the NetworkGameInfo to deserialize into
*/
void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info)
{
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
info->game_info_version = p->Recv_uint8();
/*
* Please observe the order.
* The parts must be read in the same order as they are sent!
*/
/* Update the documentation in udp.h on changes
* to the NetworkGameInfo wire-protocol! */
switch (info->game_info_version) {
case 4: {
GRFConfig **dst = &info->grfconfig;
uint i;
uint num_grfs = p->Recv_uint8();
/* Broken/bad data. It cannot have that many NewGRFs. */
if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
for (i = 0; i < num_grfs; i++) {
GRFConfig *c = new GRFConfig();
this->ReceiveGRFIdentifier(p, &c->ident);
this->HandleIncomingNetworkGameInfoGRFConfig(c);
/* Append GRFConfig to the list */
*dst = c;
dst = &c->next;
}
FALLTHROUGH;
}
case 3:
info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
FALLTHROUGH;
case 2:
info->companies_max = p->Recv_uint8 ();
info->companies_on = p->Recv_uint8 ();
info->spectators_max = p->Recv_uint8 ();
FALLTHROUGH;
case 1:
p->Recv_string(info->server_name, sizeof(info->server_name));
p->Recv_string(info->server_revision, sizeof(info->server_revision));
info->server_lang = p->Recv_uint8 ();
info->use_password = p->Recv_bool ();
info->clients_max = p->Recv_uint8 ();
info->clients_on = p->Recv_uint8 ();
info->spectators_on = p->Recv_uint8 ();
if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
}
p->Recv_string(info->map_name, sizeof(info->map_name));
info->map_width = p->Recv_uint16();
info->map_height = p->Recv_uint16();
info->map_set = p->Recv_uint8 ();
info->dedicated = p->Recv_bool ();
if (info->server_lang >= NETWORK_NUM_LANGUAGES) info->server_lang = 0;
if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
}
}
/** /**
* Handle an incoming packets by sending it to the correct function. * Handle an incoming packets by sending it to the correct function.
* @param p the received packet * @param p the received packet

View File

@@ -13,7 +13,6 @@
#define NETWORK_CORE_UDP_H #define NETWORK_CORE_UDP_H
#include "address.h" #include "address.h"
#include "game.h"
#include "packet.h" #include "packet.h"
/** Enum with all types of UDP packets. The order MUST not be changed **/ /** Enum with all types of UDP packets. The order MUST not be changed **/
@@ -63,40 +62,7 @@ protected:
/** /**
* Return of server information to the client. * Return of server information to the client.
* This packet has several legacy versions, so we list the version and size of each "field": * Serialized NetworkGameInfo. See game_info.h for details.
*
* Version: Bytes: Description:
* all 1 the version of this packet's structure
*
* 4+ 1 number of GRFs attached (n)
* 4+ n * 20 unique identifier for GRF files. Consists of:
* - one 4 byte variable with the GRF ID
* - 16 bytes (sent sequentially) for the MD5 checksum
* of the GRF
*
* 3+ 4 current game date in days since 1-1-0 (DMY)
* 3+ 4 game introduction date in days since 1-1-0 (DMY)
*
* 2+ 1 maximum number of companies allowed on the server
* 2+ 1 number of companies on the server
* 2+ 1 maximum number of spectators allowed on the server
*
* 1+ var string with the name of the server
* 1+ var string with the revision of the server
* 1+ 1 the language run on the server
* (0 = any, 1 = English, 2 = German, 3 = French)
* 1+ 1 whether the server uses a password (0 = no, 1 = yes)
* 1+ 1 maximum number of clients allowed on the server
* 1+ 1 number of clients on the server
* 1+ 1 number of spectators on the server
* 1 & 2 2 current game date in days since 1-1-1920 (DMY)
* 1 & 2 2 game introduction date in days since 1-1-1920 (DMY)
* 1+ var string with the name of the map
* 1+ 2 width of the map in tiles
* 1+ 2 height of the map in tiles
* 1+ 1 type of map:
* (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland)
* 1+ 1 whether the server is dedicated (0 = no, 1 = yes)
* @param p The received packet. * @param p The received packet.
* @param client_addr The origin of the packet. * @param client_addr The origin of the packet.
*/ */
@@ -217,15 +183,6 @@ protected:
virtual void Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr); virtual void Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr);
void HandleUDPPacket(Packet *p, NetworkAddress *client_addr); void HandleUDPPacket(Packet *p, NetworkAddress *client_addr);
/**
* 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
*/
virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) { NOT_REACHED(); }
public: public:
NetworkUDPSocketHandler(NetworkAddressList *bind = nullptr); NetworkUDPSocketHandler(NetworkAddressList *bind = nullptr);
@@ -237,9 +194,6 @@ public:
void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false); void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false);
void ReceivePackets(); void ReceivePackets();
void SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info);
void ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info);
}; };
#endif /* NETWORK_CORE_UDP_H */ #endif /* NETWORK_CORE_UDP_H */

View File

@@ -54,7 +54,6 @@ bool _network_server; ///< network-server is active
bool _network_available; ///< is network mode available? bool _network_available; ///< is network mode available?
bool _network_dedicated; ///< are we a dedicated server? bool _network_dedicated; ///< are we a dedicated server?
bool _is_network_server; ///< Does this client wants to be a network-server? bool _is_network_server; ///< Does this client wants to be a network-server?
NetworkServerGameInfo _network_game_info; ///< Information about our game.
NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies. NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies.
ClientID _network_own_client_id; ///< Our client identifier. ClientID _network_own_client_id; ///< Our client identifier.
ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client. ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client.
@@ -177,12 +176,15 @@ const char *GenerateCompanyPasswordHash(const char *password, const char *passwo
if (StrEmpty(password)) return password; if (StrEmpty(password)) return password;
char salted_password[NETWORK_SERVER_ID_LENGTH]; char salted_password[NETWORK_SERVER_ID_LENGTH];
size_t password_length = strlen(password);
size_t password_server_id_length = strlen(password_server_id);
memset(salted_password, 0, sizeof(salted_password));
seprintf(salted_password, lastof(salted_password), "%s", password);
/* Add the game seed and the server's ID as the salt. */ /* Add the game seed and the server's ID as the salt. */
for (uint i = 0; i < NETWORK_SERVER_ID_LENGTH - 1; i++) { for (uint i = 0; i < NETWORK_SERVER_ID_LENGTH - 1; i++) {
salted_password[i] ^= password_server_id[i] ^ (password_game_seed >> (i % 32)); char password_char = (i < password_length ? password[i] : 0);
char server_id_char = (i < password_server_id_length ? password_server_id[i] : 0);
char seed_char = password_game_seed >> (i % 32);
salted_password[i] = password_char ^ server_id_char ^ seed_char;
} }
Md5 checksum; Md5 checksum;
@@ -278,7 +280,7 @@ uint NetworkCalculateLag(const NetworkClientSocket *cs)
/* There was a non-recoverable error, drop back to the main menu with a nice /* There was a non-recoverable error, drop back to the main menu with a nice
* error */ * error */
void NetworkError(StringID error_string) void ShowNetworkError(StringID error_string)
{ {
_switch_mode = SM_MENU; _switch_mode = SM_MENU;
ShowErrorMessage(error_string, INVALID_STRING_ID, WL_CRITICAL); ShowErrorMessage(error_string, INVALID_STRING_ID, WL_CRITICAL);
@@ -572,9 +574,10 @@ public:
} }
}; };
/* Query a server to fetch his game-info /**
* If game_info is true, only the gameinfo is fetched, * Query a server to fetch his game-info.
* else only the client_info is fetched */ * @param address the address to query.
*/
void NetworkTCPQueryServer(NetworkAddress address) void NetworkTCPQueryServer(NetworkAddress address)
{ {
if (!_network_available) return; if (!_network_available) return;
@@ -644,7 +647,7 @@ public:
void OnFailure() override void OnFailure() override
{ {
NetworkError(STR_NETWORK_ERROR_NOCONNECTION); ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
} }
void OnConnect(SOCKET s) override void OnConnect(SOCKET s) override
@@ -658,25 +661,45 @@ public:
/* Used by clients, to connect to a server */ /* Used by clients, to connect to a server */
void NetworkClientConnectGame(NetworkAddress address, CompanyID join_as, const char *join_server_password, const char *join_company_password) void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password, const char *join_company_password)
{ {
if (!_network_available) return; if (!_network_available) return;
if (address.GetPort() == 0) return; if (port == 0) return;
strecpy(_settings_client.network.last_host, address.GetHostname(), lastof(_settings_client.network.last_host)); strecpy(_settings_client.network.last_host, hostname, lastof(_settings_client.network.last_host));
_settings_client.network.last_port = address.GetPort(); _settings_client.network.last_port = port;
_network_join_as = join_as; _network_join_as = join_as;
_network_join_server_password = join_server_password; _network_join_server_password = join_server_password;
_network_join_company_password = join_company_password; _network_join_company_password = join_company_password;
if (_game_mode == GM_MENU) {
/* From the menu we can immediately continue with the actual join. */
NetworkClientJoinGame();
} else {
/* When already playing a game, first go back to the main menu. This
* disconnects the user from the current game, meaning we can safely
* load in the new. After all, there is little point in continueing to
* play on a server if we are connecting to another one.
*/
_switch_mode = SM_JOIN_GAME;
}
}
/**
* Actually perform the joining to the server. Use #NetworkClientConnectGame
* when you want to connect to a specific server/company. This function
* assumes _network_join is already fully set up.
*/
void NetworkClientJoinGame()
{
NetworkDisconnect(); NetworkDisconnect();
NetworkInitialize(); NetworkInitialize();
_network_join_status = NETWORK_JOIN_STATUS_CONNECTING; _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
ShowJoinStatusWindow(); ShowJoinStatusWindow();
new TCPClientConnecter(address); new TCPClientConnecter(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
} }
static void NetworkInitGameInfo() static void NetworkInitGameInfo()
@@ -1027,12 +1050,13 @@ static void NetworkGenerateServerId()
seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output); seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output);
} }
void NetworkStartDebugLog(NetworkAddress address) void NetworkStartDebugLog(const char *hostname, uint16 port)
{ {
extern SOCKET _debug_socket; // Comes from debug.c extern SOCKET _debug_socket; // Comes from debug.c
DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", address.GetHostname(), address.GetPort()); DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", hostname, port);
NetworkAddress address(hostname, port);
SOCKET s = address.Connect(); SOCKET s = address.Connect();
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
DEBUG(net, 0, "Failed to open socket for redirection DEBUG()"); DEBUG(net, 0, "Failed to open socket for redirection DEBUG()");
@@ -1077,79 +1101,6 @@ void NetworkShutDown()
NetworkCoreShutdown(); NetworkCoreShutdown();
} }
/**
* How many hex digits of the git hash to include in network revision string.
* Determined as 10 hex digits + 2 characters for -g/-u/-m prefix.
*/
static const uint GITHASH_SUFFIX_LEN = 12;
/**
* Get the network version string used by this build.
* The returned string is guaranteed to be at most NETWORK_REVISON_LENGTH bytes.
*/
const char * GetNetworkRevisionString()
{
/* This will be allocated on heap and never free'd, but only once so not a "real" leak. */
static char *network_revision = nullptr;
if (!network_revision) {
/* Start by taking a chance on the full revision string. */
network_revision = stredup(_openttd_revision);
/* Ensure it's not longer than the packet buffer length. */
if (strlen(network_revision) >= NETWORK_REVISION_LENGTH) network_revision[NETWORK_REVISION_LENGTH - 1] = '\0';
/* Tag names are not mangled further. */
if (_openttd_revision_tagged) {
DEBUG(net, 1, "Network revision name is '%s'", network_revision);
return network_revision;
}
/* Prepare a prefix of the git hash.
* Size is length + 1 for terminator, +2 for -g prefix. */
assert(_openttd_revision_modified < 3);
char githash_suffix[GITHASH_SUFFIX_LEN + 1] = "-";
githash_suffix[1] = "gum"[_openttd_revision_modified];
for (uint i = 2; i < GITHASH_SUFFIX_LEN; i++) {
githash_suffix[i] = _openttd_revision_hash[i-2];
}
/* Where did the hash start in the original string?
* Overwrite from that position, unless that would go past end of packet buffer length. */
ptrdiff_t hashofs = strrchr(_openttd_revision, '-') - _openttd_revision;
if (hashofs + strlen(githash_suffix) + 1 > NETWORK_REVISION_LENGTH) hashofs = strlen(network_revision) - strlen(githash_suffix);
/* Replace the git hash in revision string. */
strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH);
assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than
DEBUG(net, 1, "Network revision name is '%s'", network_revision);
}
return network_revision;
}
static const char *ExtractNetworkRevisionHash(const char *revstr)
{
return strrchr(revstr, '-');
}
/**
* Checks whether the given version string is compatible with our version.
* First tries to match the full string, if that fails, attempts to compare just git hashes.
* @param other the version string to compare to
*/
bool IsNetworkCompatibleVersion(const char *other)
{
if (strncmp(GetNetworkRevisionString(), other, NETWORK_REVISION_LENGTH - 1) == 0) return true;
/* If this version is tagged, then the revision string must be a complete match,
* since there is no git hash suffix in it.
* This is needed to avoid situations like "1.9.0-beta1" comparing equal to "2.0.0-beta1". */
if (_openttd_revision_tagged) return false;
const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString());
const char *hash2 = ExtractNetworkRevisionHash(other);
return hash1 && hash2 && (strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0);
}
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
extern "C" { extern "C" {

View File

@@ -10,6 +10,7 @@
#include "../stdafx.h" #include "../stdafx.h"
#include "../strings_func.h" #include "../strings_func.h"
#include "../date_func.h" #include "../date_func.h"
#include "core/game_info.h"
#include "network_admin.h" #include "network_admin.h"
#include "network_base.h" #include "network_base.h"
#include "network_server.h" #include "network_server.h"

View File

@@ -14,6 +14,7 @@
#include "core/address.h" #include "core/address.h"
#include "../core/pool_type.hpp" #include "../core/pool_type.hpp"
#include "../company_type.h" #include "../company_type.h"
#include "../date_type.h"
/** Type for the pool with client information. */ /** Type for the pool with client information. */
typedef Pool<NetworkClientInfo, ClientIndex, 8, MAX_CLIENT_SLOTS, PT_NCLIENT> NetworkClientInfoPool; typedef Pool<NetworkClientInfo, ClientIndex, 8, MAX_CLIENT_SLOTS, PT_NCLIENT> NetworkClientInfoPool;

View File

@@ -23,6 +23,7 @@
#include "../gfx_func.h" #include "../gfx_func.h"
#include "../error.h" #include "../error.h"
#include "../rev.h" #include "../rev.h"
#include "core/game_info.h"
#include "network.h" #include "network.h"
#include "network_base.h" #include "network_base.h"
#include "network_client.h" #include "network_client.h"
@@ -280,7 +281,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
#else #else
if (_sync_seed_1 != _random.state[0]) { if (_sync_seed_1 != _random.state[0]) {
#endif #endif
NetworkError(STR_NETWORK_ERROR_DESYNC); ShowNetworkError(STR_NETWORK_ERROR_DESYNC);
DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract); DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract);
DEBUG(net, 0, "Sync error detected!"); DEBUG(net, 0, "Sync error detected!");
my_client->ClientError(NETWORK_RECV_STATUS_DESYNC); my_client->ClientError(NETWORK_RECV_STATUS_DESYNC);
@@ -723,7 +724,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P
/* Check all GRFs */ /* Check all GRFs */
for (; grf_count > 0; grf_count--) { for (; grf_count > 0; grf_count--) {
GRFIdentifier c; GRFIdentifier c;
this->ReceiveGRFIdentifier(p, &c); DeserializeGRFIdentifier(p, &c);
/* Check whether we know this GRF */ /* Check whether we know this GRF */
const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum); const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);

View File

@@ -17,14 +17,13 @@
// #define DEBUG_DUMP_COMMANDS // #define DEBUG_DUMP_COMMANDS
// #define DEBUG_FAILED_DUMP_COMMANDS // #define DEBUG_FAILED_DUMP_COMMANDS
#include "core/address.h"
#include "network_type.h" #include "network_type.h"
#include "../console_type.h" #include "../console_type.h"
#include "../gfx_type.h" #include "../gfx_type.h"
#include "../openttd.h" #include "../openttd.h"
#include "../company_type.h" #include "../company_type.h"
#include "../string_type.h"
extern NetworkServerGameInfo _network_game_info;
extern NetworkCompanyState *_network_company_states; extern NetworkCompanyState *_network_company_states;
extern ClientID _network_own_client_id; extern ClientID _network_own_client_id;
@@ -44,12 +43,13 @@ void NetworkDisconnect(bool blocking = false, bool close_admins = true);
void NetworkGameLoop(); void NetworkGameLoop();
void NetworkBackgroundLoop(); void NetworkBackgroundLoop();
void ParseConnectionString(const char **company, const char **port, char *connection_string); void ParseConnectionString(const char **company, const char **port, char *connection_string);
void NetworkStartDebugLog(NetworkAddress address); void NetworkStartDebugLog(const char *hostname, uint16 port);
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkPopulateCompanyStats(NetworkCompanyStats *stats);
void NetworkUpdateClientInfo(ClientID client_id); void NetworkUpdateClientInfo(ClientID client_id);
void NetworkClientsToSpectators(CompanyID cid); void NetworkClientsToSpectators(CompanyID cid);
void NetworkClientConnectGame(NetworkAddress address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr); void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr);
void NetworkClientJoinGame();
void NetworkClientRequestMove(CompanyID company, const char *pass = ""); void NetworkClientRequestMove(CompanyID company, const char *pass = "");
void NetworkClientSendRcon(const char *password, const char *command); void NetworkClientSendRcon(const char *password, const char *command);
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0);

View File

@@ -11,6 +11,7 @@
#define NETWORK_GAMELIST_H #define NETWORK_GAMELIST_H
#include "core/address.h" #include "core/address.h"
#include "core/game_info.h"
#include "network_type.h" #include "network_type.h"
/** Structure with information shown in the game list (GUI) */ /** Structure with information shown in the game list (GUI) */

View File

@@ -1536,15 +1536,15 @@ struct NetworkLobbyWindow : public Window {
case WID_NL_JOIN: // Join company case WID_NL_JOIN: // Join company
/* Button can be clicked only when it is enabled. */ /* Button can be clicked only when it is enabled. */
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), this->company); NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, this->company);
break; break;
case WID_NL_NEW: // New company case WID_NL_NEW: // New company
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_NEW_COMPANY); NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_NEW_COMPANY);
break; break;
case WID_NL_SPECTATE: // Spectate game case WID_NL_SPECTATE: // Spectate game
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_SPECTATOR); NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_SPECTATOR);
break; break;
case WID_NL_REFRESH: // Refresh case WID_NL_REFRESH: // Refresh

View File

@@ -11,6 +11,7 @@
#define NETWORK_GUI_H #define NETWORK_GUI_H
#include "../company_type.h" #include "../company_type.h"
#include "../date_type.h"
#include "../economy_type.h" #include "../economy_type.h"
#include "../window_type.h" #include "../window_type.h"
#include "network_type.h" #include "network_type.h"

View File

@@ -135,8 +135,6 @@ void NetworkAddServer(const char *b);
void NetworkRebuildHostList(); void NetworkRebuildHostList();
void UpdateNetworkGameWindow(); void UpdateNetworkGameWindow();
bool IsNetworkCompatibleVersion(const char *version);
/* From network_command.cpp */ /* From network_command.cpp */
/** /**
* Everything we need to know about a command to be able to execute it. * Everything we need to know about a command to be able to execute it.
@@ -155,7 +153,7 @@ void NetworkExecuteLocalCommandQueue();
void NetworkFreeLocalCommandQueue(); void NetworkFreeLocalCommandQueue();
void NetworkSyncCommandQueue(NetworkClientSocket *cs); void NetworkSyncCommandQueue(NetworkClientSocket *cs);
void NetworkError(StringID error_string); void ShowNetworkError(StringID error_string);
void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0); void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0);
uint NetworkCalculateLag(const NetworkClientSocket *cs); uint NetworkCalculateLag(const NetworkClientSocket *cs);
StringID GetNetworkErrorMsg(NetworkErrorCode err); StringID GetNetworkErrorMsg(NetworkErrorCode err);

View File

@@ -10,6 +10,7 @@
#include "../stdafx.h" #include "../stdafx.h"
#include "../strings_func.h" #include "../strings_func.h"
#include "../date_func.h" #include "../date_func.h"
#include "core/game_info.h"
#include "network_admin.h" #include "network_admin.h"
#include "network_server.h" #include "network_server.h"
#include "network_udp.h" #include "network_udp.h"
@@ -363,6 +364,20 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendClientInfo(NetworkClientIn
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
} }
/** Send the client information about the server. */
NetworkRecvStatus ServerNetworkGameSocketHandler::SendGameInfo()
{
NetworkGameInfo ngi;
FillNetworkGameInfo(ngi);
Packet *p = new Packet(PACKET_SERVER_GAME_INFO);
SerializeNetworkGameInfo(p, &ngi);
this->SendPacket(p);
return NETWORK_RECV_STATUS_OKAY;
}
/** Send the client information about the companies. */ /** Send the client information about the companies. */
NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo()
{ {
@@ -488,7 +503,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
p->Send_uint8 (grf_count); p->Send_uint8 (grf_count);
for (c = _grfconfig; c != nullptr; c = c->next) { for (c = _grfconfig; c != nullptr; c = c->next) {
if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident); if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(p, &c->ident);
} }
this->SendPacket(p); this->SendPacket(p);
@@ -605,7 +620,7 @@ void ServerNetworkGameSocketHandler::CheckNextClientToSendMap(NetworkClientSocke
/** This sends the map to the client */ /** This sends the map to the client */
NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
{ {
static uint sent_packets; // How many packets we did send successfully last time static uint16 sent_packets; // How many packets we did send successfully last time
if (this->status < STATUS_AUTHORIZED) { if (this->status < STATUS_AUTHORIZED) {
/* Illegal call, return error and ignore the packet */ /* Illegal call, return error and ignore the packet */
@@ -665,8 +680,10 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
return NETWORK_RECV_STATUS_CONN_LOST; return NETWORK_RECV_STATUS_CONN_LOST;
case SPS_ALL_SENT: case SPS_ALL_SENT:
/* All are sent, increase the sent_packets */ /* All are sent, increase the sent_packets but do not overflow! */
if (has_packets) sent_packets *= 2; if (has_packets && sent_packets < std::numeric_limits<decltype(sent_packets)>::max() / 2) {
sent_packets *= 2;
}
break; break;
case SPS_PARTLY_SENT: case SPS_PARTLY_SENT:
@@ -875,6 +892,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendConfigUpdate()
* DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p * DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
************/ ************/
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p)
{
return this->SendGameInfo();
}
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p)
{ {
return this->SendCompanyInfo(); return this->SendCompanyInfo();

View File

@@ -24,6 +24,7 @@ extern NetworkClientSocketPool _networkclientsocket_pool;
class ServerNetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkGameSocketHandler, public TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED> { class ServerNetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkGameSocketHandler, public TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED> {
protected: protected:
NetworkRecvStatus Receive_CLIENT_JOIN(Packet *p) override; NetworkRecvStatus Receive_CLIENT_JOIN(Packet *p) override;
NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet *p) override;
NetworkRecvStatus Receive_CLIENT_COMPANY_INFO(Packet *p) override; NetworkRecvStatus Receive_CLIENT_COMPANY_INFO(Packet *p) override;
NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet *p) override; NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet *p) override;
NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet *p) override; NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet *p) override;
@@ -40,6 +41,7 @@ protected:
NetworkRecvStatus Receive_CLIENT_NEWGRFS_CHECKED(Packet *p) override; NetworkRecvStatus Receive_CLIENT_NEWGRFS_CHECKED(Packet *p) override;
NetworkRecvStatus Receive_CLIENT_MOVE(Packet *p) override; NetworkRecvStatus Receive_CLIENT_MOVE(Packet *p) override;
NetworkRecvStatus SendGameInfo();
NetworkRecvStatus SendCompanyInfo(); NetworkRecvStatus SendCompanyInfo();
NetworkRecvStatus SendNewGRFCheck(); NetworkRecvStatus SendNewGRFCheck();
NetworkRecvStatus SendWelcome(); NetworkRecvStatus SendWelcome();

View File

@@ -10,7 +10,7 @@
#ifndef NETWORK_TYPE_H #ifndef NETWORK_TYPE_H
#define NETWORK_TYPE_H #define NETWORK_TYPE_H
#include "core/game.h" #include "core/config.h"
/** How many clients can we have */ /** How many clients can we have */
static const uint MAX_CLIENTS = 255; static const uint MAX_CLIENTS = 255;

View File

@@ -16,6 +16,7 @@
#include "../date_func.h" #include "../date_func.h"
#include "../map_func.h" #include "../map_func.h"
#include "../debug.h" #include "../debug.h"
#include "core/game_info.h"
#include "network_gamelist.h" #include "network_gamelist.h"
#include "network_internal.h" #include "network_internal.h"
#include "network_udp.h" #include "network_udp.h"
@@ -171,31 +172,10 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, Networ
} }
NetworkGameInfo ngi; NetworkGameInfo ngi;
FillNetworkGameInfo(ngi);
/* Update some game_info */
ngi.clients_on = _network_game_info.clients_on;
ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
ngi.server_lang = _settings_client.network.server_lang;
ngi.use_password = !StrEmpty(_settings_client.network.server_password);
ngi.clients_max = _settings_client.network.max_clients;
ngi.companies_on = (byte)Company::GetNumItems();
ngi.companies_max = _settings_client.network.max_companies;
ngi.spectators_on = NetworkSpectatorCount();
ngi.spectators_max = _settings_client.network.max_spectators;
ngi.game_date = _date;
ngi.map_width = MapSizeX();
ngi.map_height = MapSizeY();
ngi.map_set = _settings_game.game_creation.landscape;
ngi.dedicated = _network_dedicated;
ngi.grfconfig = _grfconfig;
strecpy(ngi.map_name, _network_game_info.map_name, lastof(ngi.map_name));
strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name));
strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision));
Packet packet(PACKET_UDP_SERVER_RESPONSE); Packet packet(PACKET_UDP_SERVER_RESPONSE);
this->SendNetworkGameInfo(&packet, &ngi); SerializeNetworkGameInfo(&packet, &ngi);
/* Let the client know that we are here */ /* Let the client know that we are here */
this->SendPacket(&packet, client_addr); this->SendPacket(&packet, client_addr);
@@ -286,7 +266,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ
GRFIdentifier c; GRFIdentifier c;
const GRFConfig *f; const GRFConfig *f;
this->ReceiveGRFIdentifier(p, &c); DeserializeGRFIdentifier(p, &c);
/* Find the matching GRF file */ /* Find the matching GRF file */
f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum); f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);
@@ -313,7 +293,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ
/* The name could be an empty string, if so take the filename */ /* The name could be an empty string, if so take the filename */
strecpy(name, in_reply[i]->GetName(), lastof(name)); strecpy(name, in_reply[i]->GetName(), lastof(name));
this->SendGRFIdentifier(&packet, &in_reply[i]->ident); SerializeGRFIdentifier(&packet, &in_reply[i]->ident);
packet.Send_string(name); packet.Send_string(name);
} }
@@ -328,7 +308,6 @@ protected:
void Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr) override; void Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr) override;
void Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr) override; void Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr) override;
void Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr) override; void Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr) override;
void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) override;
public: public:
virtual ~ClientNetworkUDPSocketHandler() {} virtual ~ClientNetworkUDPSocketHandler() {}
}; };
@@ -346,7 +325,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd
item = NetworkGameListAddItem(*client_addr); item = NetworkGameListAddItem(*client_addr);
ClearGRFConfigList(&item->info.grfconfig); ClearGRFConfigList(&item->info.grfconfig);
this->ReceiveNetworkGameInfo(p, &item->info); DeserializeNetworkGameInfo(p, &item->info);
item->info.compatible = true; item->info.compatible = true;
{ {
@@ -375,7 +354,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd
packet.Send_uint8(in_request_count); packet.Send_uint8(in_request_count);
for (i = 0; i < in_request_count; i++) { for (i = 0; i < in_request_count; i++) {
this->SendGRFIdentifier(&packet, &in_request[i]->ident); SerializeGRFIdentifier(&packet, &in_request[i]->ident);
} }
this->SendPacket(&packet, &item->address); this->SendPacket(&packet, &item->address);
@@ -449,7 +428,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
char name[NETWORK_GRF_NAME_LENGTH]; char name[NETWORK_GRF_NAME_LENGTH];
GRFIdentifier c; GRFIdentifier c;
this->ReceiveGRFIdentifier(p, &c); DeserializeGRFIdentifier(p, &c);
p->Recv_string(name, sizeof(name)); p->Recv_string(name, sizeof(name));
/* An empty name is not possible under normal circumstances /* An empty name is not possible under normal circumstances
@@ -466,25 +445,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
} }
} }
void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
{
/* Find the matching GRF file */
const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum);
if (f == nullptr) {
/* 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->ident.grfid, config->ident.md5sum, true);
config->status = GCS_NOT_FOUND;
} else {
config->filename = f->filename;
config->name = f->name;
config->info = f->info;
config->url = f->url;
}
SetBit(config->flags, GCF_COPY);
}
/** Broadcast to all ips */ /** Broadcast to all ips */
static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket) static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
{ {

View File

@@ -17,6 +17,7 @@
#include "window_func.h" #include "window_func.h"
#include "progress.h" #include "progress.h"
#include "video/video_driver.hpp" #include "video/video_driver.hpp"
#include "string_func.h"
#include "strings_func.h" #include "strings_func.h"
#include "textfile_gui.h" #include "textfile_gui.h"
#include "thread.h" #include "thread.h"

View File

@@ -281,13 +281,17 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
if (this->tile == INVALID_TILE) break; if (this->tile == INVALID_TILE) break;
return GetClosestIndustry(this->tile, MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid), this->industry); return GetClosestIndustry(this->tile, MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid), this->industry);
/* Get town zone and Manhattan distance of closest town */ /* Get town zone and Manhattan distance of closest town */
case 0x65: case 0x65: {
if (this->tile == INVALID_TILE) break; if (this->tile == INVALID_TILE) break;
return GetTownRadiusGroup(this->industry->town, this->tile) << 16 | std::min(DistanceManhattan(this->tile, this->industry->town->xy), 0xFFFFu); TileIndex tile = GetNearbyTile(parameter, this->tile, true);
/* Get square of Euclidian distance of closes town */ return GetTownRadiusGroup(this->industry->town, tile) << 16 | std::min(DistanceManhattan(tile, this->industry->town->xy), 0xFFFFu);
case 0x66: }
/* Get square of Euclidian distance of closest town */
case 0x66: {
if (this->tile == INVALID_TILE) break; if (this->tile == INVALID_TILE) break;
return GetTownRadiusGroup(this->industry->town, this->tile) << 16 | std::min(DistanceSquare(this->tile, this->industry->town->xy), 0xFFFFu); TileIndex tile = GetNearbyTile(parameter, this->tile, true);
return DistanceSquare(tile, this->industry->town->xy);
}
/* Count of industry, distance of closest instance /* Count of industry, distance of closest instance
* 68 is the same as 67, but with a filtering on selected layout */ * 68 is the same as 67, but with a filtering on selected layout */

View File

@@ -303,8 +303,8 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte local_id, uint32 grfid,
/* Get town zone and Manhattan distance of closest town */ /* Get town zone and Manhattan distance of closest town */
case 0x45: return GetTownRadiusGroup(t, this->tile) << 16 | std::min(DistanceManhattan(this->tile, t->xy), 0xFFFFu); case 0x45: return GetTownRadiusGroup(t, this->tile) << 16 | std::min(DistanceManhattan(this->tile, t->xy), 0xFFFFu);
/* Get square of Euclidian distance of closes town */ /* Get square of Euclidian distance of closest town */
case 0x46: return GetTownRadiusGroup(t, this->tile) << 16 | std::min(DistanceSquare(this->tile, t->xy), 0xFFFFu); case 0x46: return DistanceSquare(this->tile, t->xy);
/* Object colour */ /* Object colour */
case 0x47: return this->obj->colour; case 0x47: return this->obj->colour;

View File

@@ -32,6 +32,7 @@
#include "screenshot.h" #include "screenshot.h"
#include "network/network.h" #include "network/network.h"
#include "network/network_func.h" #include "network/network_func.h"
#include "network/core/game_info.h"
#include "ai/ai.hpp" #include "ai/ai.hpp"
#include "ai/ai_config.hpp" #include "ai/ai_config.hpp"
#include "settings_func.h" #include "settings_func.h"
@@ -495,7 +496,7 @@ struct AfterNewGRFScan : NewGRFScanCallback {
LoadIntroGame(); LoadIntroGame();
_switch_mode = SM_NONE; _switch_mode = SM_NONE;
NetworkClientConnectGame(NetworkAddress(network_conn, rport), join_as, join_server_password, join_company_password); NetworkClientConnectGame(network_conn, rport, join_as, join_server_password, join_company_password);
} }
/* After the scan we're not used anymore. */ /* After the scan we're not used anymore. */
@@ -783,7 +784,7 @@ int openttd_main(int argc, char *argv[])
ParseConnectionString(&not_used, &port, debuglog_conn); ParseConnectionString(&not_used, &port, debuglog_conn);
if (port != nullptr) rport = atoi(port); if (port != nullptr) rport = atoi(port);
NetworkStartDebugLog(NetworkAddress(debuglog_conn, rport)); NetworkStartDebugLog(debuglog_conn, rport);
} }
if (!HandleBootstrap()) { if (!HandleBootstrap()) {
@@ -1108,6 +1109,11 @@ void SwitchToMode(SwitchMode new_mode)
break; break;
} }
case SM_JOIN_GAME: // Join a multiplayer game
LoadIntroGame();
NetworkClientJoinGame();
break;
case SM_MENU: // Switch to game intro menu case SM_MENU: // Switch to game intro menu
LoadIntroGame(); LoadIntroGame();
if (BaseSounds::ini_set.empty() && BaseSounds::GetUsedSet()->fallback && SoundDriver::GetInstance()->HasOutput()) { if (BaseSounds::ini_set.empty() && BaseSounds::GetUsedSet()->fallback && SoundDriver::GetInstance()->HasOutput()) {
@@ -1504,7 +1510,7 @@ void GameLoop()
if (_network_reconnect > 0 && --_network_reconnect == 0) { if (_network_reconnect > 0 && --_network_reconnect == 0) {
/* This means that we want to reconnect to the last host /* This means that we want to reconnect to the last host
* We do this here, because it means that the network is really closed */ * We do this here, because it means that the network is really closed */
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_SPECTATOR); NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_SPECTATOR);
} }
/* Singleplayer */ /* Singleplayer */
StateGameLoop(); StateGameLoop();

View File

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

View File

@@ -77,8 +77,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,11,0,${REV_ISODATE} FILEVERSION ${REV_MAJOR},${REV_MINOR},${REV_BUILD},${REV_ISODATE}
PRODUCTVERSION 1,11,0,${REV_ISODATE} PRODUCTVERSION ${REV_MAJOR},${REV_MINOR},${REV_BUILD},${REV_ISODATE}
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L

View File

@@ -5,5 +5,4 @@ add_files(
follow_track.hpp follow_track.hpp
pathfinder_func.h pathfinder_func.h
pathfinder_type.h pathfinder_type.h
pf_performance_timer.hpp
) )

View File

@@ -18,7 +18,6 @@
#include "../tunnelbridge_map.h" #include "../tunnelbridge_map.h"
#include "../depot_map.h" #include "../depot_map.h"
#include "pathfinder_func.h" #include "pathfinder_func.h"
#include "pf_performance_timer.hpp"
/** /**
* Track follower helper template class (can serve pathfinders and vehicle * Track follower helper template class (can serve pathfinders and vehicle
@@ -49,34 +48,32 @@ struct CFollowTrackT
bool m_is_station; ///< last turn passed station bool m_is_station; ///< last turn passed station
int m_tiles_skipped; ///< number of skipped tunnel or station tiles int m_tiles_skipped; ///< number of skipped tunnel or station tiles
ErrorCode m_err; ErrorCode m_err;
CPerformanceTimer *m_pPerf;
RailTypes m_railtypes; RailTypes m_railtypes;
inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES, CPerformanceTimer *pPerf = nullptr) inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES)
{ {
Init(v, railtype_override, pPerf); Init(v, railtype_override);
} }
inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES, CPerformanceTimer *pPerf = nullptr) inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES)
{ {
assert(IsRailTT()); assert(IsRailTT());
m_veh = nullptr; m_veh = nullptr;
Init(o, railtype_override, pPerf); Init(o, railtype_override);
} }
inline void Init(const VehicleType *v, RailTypes railtype_override, CPerformanceTimer *pPerf) inline void Init(const VehicleType *v, RailTypes railtype_override)
{ {
assert(!IsRailTT() || (v != nullptr && v->type == VEH_TRAIN)); assert(!IsRailTT() || (v != nullptr && v->type == VEH_TRAIN));
m_veh = v; m_veh = v;
Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override, pPerf); Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override);
} }
inline void Init(Owner o, RailTypes railtype_override, CPerformanceTimer *pPerf) inline void Init(Owner o, RailTypes railtype_override)
{ {
assert(!IsRoadTT() || m_veh != nullptr); assert(!IsRoadTT() || m_veh != nullptr);
assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES); assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES);
m_veh_owner = o; m_veh_owner = o;
m_pPerf = pPerf;
/* don't worry, all is inlined so compiler should remove unnecessary initializations */ /* don't worry, all is inlined so compiler should remove unnecessary initializations */
m_old_tile = INVALID_TILE; m_old_tile = INVALID_TILE;
m_old_td = INVALID_TRACKDIR; m_old_td = INVALID_TRACKDIR;
@@ -237,7 +234,6 @@ protected:
/** stores track status (available trackdirs) for the new tile into m_new_td_bits */ /** stores track status (available trackdirs) for the new tile into m_new_td_bits */
inline bool QueryNewTileTrackStatus() inline bool QueryNewTileTrackStatus()
{ {
CPerfStart perf(*m_pPerf);
if (IsRailTT() && IsPlainRailTile(m_new_tile)) { if (IsRailTT() && IsPlainRailTile(m_new_tile)) {
m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101); m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101);
} else if (IsRoadTT()) { } else if (IsRoadTT()) {

View File

@@ -8,6 +8,7 @@
/** @file npf.cpp Implementation of the NPF pathfinder. */ /** @file npf.cpp Implementation of the NPF pathfinder. */
#include "../../stdafx.h" #include "../../stdafx.h"
#include "../../debug.h"
#include "../../network/network.h" #include "../../network/network.h"
#include "../../viewport_func.h" #include "../../viewport_func.h"
#include "../../ship.h" #include "../../ship.h"

View File

@@ -12,12 +12,8 @@
#include "../../landscape.h" #include "../../landscape.h"
#include "../pathfinder_func.h" #include "../pathfinder_func.h"
#include "../pf_performance_timer.hpp"
#include "yapf.h" #include "yapf.h"
//#undef FORCEINLINE
//#define inline inline
#include "../../misc/blob.hpp" #include "../../misc/blob.hpp"
#include "../../misc/str.hpp" #include "../../misc/str.hpp"
#include "../../misc/fixedsizearray.hpp" #include "../../misc/fixedsizearray.hpp"

View File

@@ -13,8 +13,6 @@
#include "../../debug.h" #include "../../debug.h"
#include "../../settings_type.h" #include "../../settings_type.h"
extern int _total_pf_time_us;
/** /**
* CYapfBaseT - A-star type path finder base class. * CYapfBaseT - A-star type path finder base class.
* Derive your own pathfinder from it. You must provide the following template argument: * Derive your own pathfinder from it. You must provide the following template argument:
@@ -67,12 +65,6 @@ protected:
int m_stats_cost_calcs; ///< stats - how many node's costs were calculated int m_stats_cost_calcs; ///< stats - how many node's costs were calculated
int m_stats_cache_hits; ///< stats - how many node's costs were reused from cache int m_stats_cache_hits; ///< stats - how many node's costs were reused from cache
public:
CPerformanceTimer m_perf_cost; ///< stats - total CPU time of this run
CPerformanceTimer m_perf_slope_cost; ///< stats - slope calculation CPU time
CPerformanceTimer m_perf_ts_cost; ///< stats - GetTrackStatus() CPU time
CPerformanceTimer m_perf_other_cost; ///< stats - other CPU time
public: public:
int m_num_steps; ///< this is there for debugging purposes (hope it doesn't hurt) int m_num_steps; ///< this is there for debugging purposes (hope it doesn't hurt)
@@ -120,9 +112,6 @@ public:
{ {
m_veh = v; m_veh = v;
CPerformanceTimer perf;
perf.Start();
Yapf().PfSetStartupNodes(); Yapf().PfSetStartupNodes();
bool bDestFound = true; bool bDestFound = true;
@@ -150,11 +139,6 @@ public:
bDestFound &= (m_pBestDestNode != nullptr); bDestFound &= (m_pBestDestNode != nullptr);
perf.Stop();
if (_debug_yapf_level >= 2) {
int t = perf.Get(1000000);
_total_pf_time_us += t;
if (_debug_yapf_level >= 3) { if (_debug_yapf_level >= 3) {
UnitID veh_idx = (m_veh != nullptr) ? m_veh->unitnumber : 0; UnitID veh_idx = (m_veh != nullptr) ? m_veh->unitnumber : 0;
char ttc = Yapf().TransportTypeChar(); char ttc = Yapf().TransportTypeChar();
@@ -162,13 +146,11 @@ public:
int cost = bDestFound ? m_pBestDestNode->m_cost : -1; int cost = bDestFound ? m_pBestDestNode->m_cost : -1;
int dist = bDestFound ? m_pBestDestNode->m_estimate - m_pBestDestNode->m_cost : -1; int dist = bDestFound ? m_pBestDestNode->m_estimate - m_pBestDestNode->m_cost : -1;
DEBUG(yapf, 3, "[YAPF%c]%c%4d- %d us - %d rounds - %d open - %d closed - CHR %4.1f%% - C %d D %d - c%d(sc%d, ts%d, o%d) -- ", DEBUG(yapf, 3, "[YAPF%c]%c%4d- %d rounds - %d open - %d closed - CHR %4.1f%% - C %d D %d",
ttc, bDestFound ? '-' : '!', veh_idx, t, m_num_steps, m_nodes.OpenCount(), m_nodes.ClosedCount(), ttc, bDestFound ? '-' : '!', veh_idx, m_num_steps, m_nodes.OpenCount(), m_nodes.ClosedCount(), cache_hit_ratio, cost, dist
cache_hit_ratio, cost, dist, m_perf_cost.Get(1000000), m_perf_slope_cost.Get(1000000),
m_perf_ts_cost.Get(1000000), m_perf_other_cost.Get(1000000)
); );
} }
}
return bDestFound; return bDestFound;
} }

View File

@@ -182,16 +182,8 @@ protected:
inline static Cache& stGetGlobalCache() inline static Cache& stGetGlobalCache()
{ {
static int last_rail_change_counter = 0; static int last_rail_change_counter = 0;
static Date last_date = 0;
static Cache C; static Cache C;
/* some statistics */
if (last_date != _date) {
last_date = _date;
DEBUG(yapf, 2, "Pf time today: %5d ms", _total_pf_time_us / 1000);
_total_pf_time_us = 0;
}
/* delete the cache sometimes... */ /* delete the cache sometimes... */
if (last_rail_change_counter != Cache::s_rail_change_counter) { if (last_rail_change_counter != Cache::s_rail_change_counter) {
last_rail_change_counter = Cache::s_rail_change_counter; last_rail_change_counter = Cache::s_rail_change_counter;

View File

@@ -83,7 +83,6 @@ protected:
public: public:
inline int SlopeCost(TileIndex tile, Trackdir td) inline int SlopeCost(TileIndex tile, Trackdir td)
{ {
CPerfStart perf_cost(Yapf().m_perf_slope_cost);
if (!stSlopeCost(tile, td)) return 0; if (!stSlopeCost(tile, td)) return 0;
return Yapf().PfGetSettings().rail_slope_penalty; return Yapf().PfGetSettings().rail_slope_penalty;
} }
@@ -169,7 +168,6 @@ public:
{ {
int cost = 0; int cost = 0;
/* if there is one-way signal in the opposite direction, then it is not our way */ /* if there is one-way signal in the opposite direction, then it is not our way */
CPerfStart perf_cost(Yapf().m_perf_other_cost);
if (IsTileType(tile, MP_RAILWAY)) { if (IsTileType(tile, MP_RAILWAY)) {
bool has_signal_against = HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir)); bool has_signal_against = HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir));
bool has_signal_along = HasSignalOnTrackdir(tile, trackdir); bool has_signal_along = HasSignalOnTrackdir(tile, trackdir);
@@ -272,8 +270,6 @@ public:
assert(tf->m_new_tile == n.m_key.m_tile); assert(tf->m_new_tile == n.m_key.m_tile);
assert((HasTrackdir(tf->m_new_td_bits, n.m_key.m_td))); assert((HasTrackdir(tf->m_new_td_bits, n.m_key.m_td)));
CPerfStart perf_cost(Yapf().m_perf_cost);
/* Does the node have some parent node? */ /* Does the node have some parent node? */
bool has_parent = (n.m_parent != nullptr); bool has_parent = (n.m_parent != nullptr);
@@ -323,7 +319,7 @@ public:
EndSegmentReasonBits end_segment_reason = ESRB_NONE; EndSegmentReasonBits end_segment_reason = ESRB_NONE;
TrackFollower tf_local(v, Yapf().GetCompatibleRailTypes(), &Yapf().m_perf_ts_cost); TrackFollower tf_local(v, Yapf().GetCompatibleRailTypes());
if (!has_parent) { if (!has_parent) {
/* We will jump to the middle of the cost calculator assuming that segment cache is not used. */ /* We will jump to the middle of the cost calculator assuming that segment cache is not used. */
@@ -481,7 +477,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
/* Move to the next tile/trackdir. */ /* Move to the next tile/trackdir. */
tf = &tf_local; tf = &tf_local;
tf_local.Init(v, Yapf().GetCompatibleRailTypes(), &Yapf().m_perf_ts_cost); tf_local.Init(v, Yapf().GetCompatibleRailTypes());
if (!tf_local.Follow(cur.tile, cur.td)) { if (!tf_local.Follow(cur.tile, cur.td)) {
assert(tf_local.m_err != TrackFollower::EC_NONE); assert(tf_local.m_err != TrackFollower::EC_NONE);

View File

@@ -34,8 +34,6 @@ template <typename Tpf> void DumpState(Tpf &pf1, Tpf &pf2)
fclose(f2); fclose(f2);
} }
int _total_pf_time_us = 0;
template <class Types> template <class Types>
class CYapfReserveTrack class CYapfReserveTrack
{ {

View File

@@ -35,7 +35,7 @@ bool IsReleasedVersion()
* *
* <modified> shows a "M", if the binary is made from modified source code. * <modified> shows a "M", if the binary is made from modified source code.
*/ */
const char _openttd_revision[] = "1.11.1"; const char _openttd_revision[] = "1.11.2";
/** /**
* The text version of OpenTTD's build date. * The text version of OpenTTD's build date.
@@ -48,7 +48,7 @@ const char _openttd_build_date[] = __DATE__ " " __TIME__;
/** /**
* The git revision hash of this version. * The git revision hash of this version.
*/ */
const char _openttd_revision_hash[] = "0be22efffc3c14db08baf5e58c448b5d074f4427"; const char _openttd_revision_hash[] = "672f285218c6817784d86f737987b75db4bc78fc";
/** /**
* The year of this version. * The year of this version.
@@ -85,4 +85,4 @@ const byte _openttd_revision_tagged = 1;
* final release will always have a lower version number than the released * final release will always have a lower version number than the released
* version, thus making comparisons on specific revisions easy. * version, thus making comparisons on specific revisions easy.
*/ */
const uint32 _openttd_newgrf_version = 1 << 28 | 11 << 24 | 0 << 20 | 1 << 19 | 28004; const uint32 _openttd_newgrf_version = 1 << 28 | 11 << 24 | 2 << 20 | 1 << 19 | 28004;

View File

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

View File

@@ -219,6 +219,7 @@ void UpdateAllVirtCoords()
UpdateAllStationVirtCoords(); UpdateAllStationVirtCoords();
UpdateAllSignVirtCoords(); UpdateAllSignVirtCoords();
UpdateAllTownVirtCoords(); UpdateAllTownVirtCoords();
UpdateAllTextEffectVirtCoords();
RebuildViewportKdtree(); RebuildViewportKdtree();
} }

View File

@@ -864,7 +864,7 @@ static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the curre
*/ */
static void ScreenshotConfirmationCallback(Window *w, bool confirmed) static void ScreenshotConfirmationCallback(Window *w, bool confirmed)
{ {
if (confirmed) MakeScreenshot(_confirmed_screenshot_type, nullptr); if (confirmed) MakeScreenshot(_confirmed_screenshot_type, {});
} }
/** /**
@@ -890,24 +890,20 @@ void MakeScreenshotWithConfirm(ScreenshotType t)
ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmationCallback); ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmationCallback);
} else { } else {
/* Less than 64M pixels, just do it */ /* Less than 64M pixels, just do it */
MakeScreenshot(t, nullptr); MakeScreenshot(t, {});
} }
} }
/** /**
* Make a screenshot. * Make a screenshot.
* Unconditionally take a screenshot of the requested type.
* @param t the type of screenshot to make. * @param t the type of screenshot to make.
* @param name the name to give to the screenshot. * @param name the name to give to the screenshot.
* @param width the width of the screenshot of, or 0 for current viewport width (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM). * @param width the width of the screenshot of, or 0 for current viewport width (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
* @param height the height of the screenshot of, or 0 for current viewport height (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM). * @param height the height of the screenshot of, or 0 for current viewport height (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
* @return true iff the screenshot was made successfully * @return true iff the screenshot was made successfully
* @see MakeScreenshotWithConfirm
*/ */
bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 height) static bool RealMakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height)
{ {
VideoDriver::VideoBufferLocker lock;
if (t == SC_VIEWPORT) { if (t == SC_VIEWPORT) {
/* First draw the dirty parts of the screen and only then change the name /* First draw the dirty parts of the screen and only then change the name
* of the screenshot. This way the screenshot will always show the name * of the screenshot. This way the screenshot will always show the name
@@ -918,7 +914,7 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei
} }
_screenshot_name[0] = '\0'; _screenshot_name[0] = '\0';
if (name != nullptr) strecpy(_screenshot_name, name, lastof(_screenshot_name)); if (!name.empty()) strecpy(_screenshot_name, name.c_str(), lastof(_screenshot_name));
bool ret; bool ret;
switch (t) { switch (t) {
@@ -957,7 +953,7 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei
if (t == SC_HEIGHTMAP) { if (t == SC_HEIGHTMAP) {
SetDParamStr(0, _screenshot_name); SetDParamStr(0, _screenshot_name);
SetDParam(1, _heightmap_highest_peak); SetDParam(1, _heightmap_highest_peak);
ShowErrorMessage(STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY, INVALID_STRING_ID, WL_CRITICAL); ShowErrorMessage(STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING);
} else { } else {
SetDParamStr(0, _screenshot_name); SetDParamStr(0, _screenshot_name);
ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING);
@@ -969,6 +965,32 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei
return ret; return ret;
} }
/**
* Schedule making a screenshot.
* Unconditionally take a screenshot of the requested type.
* @param t the type of screenshot to make.
* @param name the name to give to the screenshot.
* @param width the width of the screenshot of, or 0 for current viewport width (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
* @param height the height of the screenshot of, or 0 for current viewport height (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
* @return true iff the screenshot was successfully made.
* @see MakeScreenshotWithConfirm
*/
bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height)
{
if (t == SC_CRASHLOG) {
/* Video buffer might or might not be locked. */
VideoDriver::VideoBufferLocker lock;
return RealMakeScreenshot(t, name, width, height);
}
VideoDriver::GetInstance()->QueueOnMainThread([=] { // Capture by value to not break scope.
RealMakeScreenshot(t, name, width, height);
});
return true;
}
/** /**
* Return the owner of a tile to display it with in the small map in mode "Owner". * Return the owner of a tile to display it with in the small map in mode "Owner".

View File

@@ -28,7 +28,7 @@ enum ScreenshotType {
void SetupScreenshotViewport(ScreenshotType t, struct Viewport *vp, uint32 width = 0, uint32 height = 0); void SetupScreenshotViewport(ScreenshotType t, struct Viewport *vp, uint32 width = 0, uint32 height = 0);
bool MakeHeightmapScreenshot(const char *filename); bool MakeHeightmapScreenshot(const char *filename);
void MakeScreenshotWithConfirm(ScreenshotType t); void MakeScreenshotWithConfirm(ScreenshotType t);
bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width = 0, uint32 height = 0); bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width = 0, uint32 height = 0);
bool MakeMinimapWorldScreenshot(); bool MakeMinimapWorldScreenshot();
extern char _screenshot_format_name[8]; extern char _screenshot_format_name[8];

View File

@@ -2394,9 +2394,9 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
for (uint i = 0; i < st->airport.GetNumHangars(); ++i) { for (uint i = 0; i < st->airport.GetNumHangars(); ++i) {
DeleteWindowById( TileIndex tile_cur = st->airport.GetHangarTile(i);
WC_VEHICLE_DEPOT, st->airport.GetHangarTile(i) OrderBackup::Reset(tile_cur, false);
); DeleteWindowById(WC_VEHICLE_DEPOT, tile_cur);
} }
const AirportSpec *as = st->airport.GetSpec(); const AirportSpec *as = st->airport.GetSpec();
@@ -2418,7 +2418,6 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]); cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur, false);
DeleteAnimatedTile(tile_cur); DeleteAnimatedTile(tile_cur);
DoClearSquare(tile_cur); DoClearSquare(tile_cur);
DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur); DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);

View File

@@ -153,9 +153,6 @@ void CheckRedrawStationCoverage(const Window *w)
* @param type Cargo type * @param type Cargo type
* @param amount Cargo amount * @param amount Cargo amount
* @param rating ratings data for that particular cargo * @param rating ratings data for that particular cargo
*
* @note Each cargo-bar is 16 pixels wide and 6 pixels high
* @note Each rating 14 pixels wide and 1 pixel high and is 1 pixel below the cargo-bar
*/ */
static void StationsWndShowStationRating(int left, int right, int y, CargoID type, uint amount, byte rating) static void StationsWndShowStationRating(int left, int right, int y, CargoID type, uint amount, byte rating)
{ {
@@ -165,32 +162,33 @@ static void StationsWndShowStationRating(int left, int right, int y, CargoID typ
const CargoSpec *cs = CargoSpec::Get(type); const CargoSpec *cs = CargoSpec::Get(type);
if (!cs->IsValid()) return; if (!cs->IsValid()) return;
int padding = ScaleFontTrad(1);
int width = right - left;
int colour = cs->rating_colour; int colour = cs->rating_colour;
TextColour tc = GetContrastColour(colour); TextColour tc = GetContrastColour(colour);
uint w = (std::min(amount, units_full) + 5) / 36; uint w = std::min(amount + 5, units_full) * width / units_full;
int height = GetCharacterHeight(FS_SMALL); int height = GetCharacterHeight(FS_SMALL) + padding - 1;
/* Draw total cargo (limited) on station (fits into 16 pixels) */ if (amount > 30) {
if (w != 0) GfxFillRect(left, y, left + w - 1, y + height, colour); /* Draw total cargo (limited) on station */
GfxFillRect(left, y, left + w - 1, y + height, colour);
/* Draw a one pixel-wide bar of additional cargo meter, useful } else {
/* Draw a (scaled) one pixel-wide bar of additional cargo meter, useful
* for stations with only a small amount (<=30) */ * for stations with only a small amount (<=30) */
if (w == 0) { uint rest = ScaleFontTrad(amount) / 5;
uint rest = amount / 5;
if (rest != 0) { if (rest != 0) {
w += left; GfxFillRect(left, y + height - rest, left + padding - 1, y + height, colour);
GfxFillRect(w, y + height - rest, w, y + height, colour);
} }
} }
DrawString(left + 1, right, y, cs->abbrev, tc); DrawString(left + padding, right, y, cs->abbrev, tc);
/* Draw green/red ratings bar (fits into 14 pixels) */ /* Draw green/red ratings bar (fits under the waiting bar) */
y += height + 2; y += height + padding + 1;
GfxFillRect(left + 1, y, left + 14, y, PC_RED); GfxFillRect(left + padding, y, right - padding - 1, y + padding - 1, PC_RED);
rating = std::min<uint>(rating, rating_full) / 16; w = std::min<uint>(rating, rating_full) * (width - padding - padding) / rating_full;
if (rating != 0) GfxFillRect(left + 1, y, left + rating, y, PC_GREEN); if (w != 0) GfxFillRect(left + padding, y, left + w - 1, y + padding - 1, PC_GREEN);
} }
typedef GUIList<const Station*> GUIStationList; typedef GUIList<const Station*> GUIStationList;
@@ -214,6 +212,7 @@ protected:
GUIStationList stations; GUIStationList stations;
Scrollbar *vscroll; Scrollbar *vscroll;
uint rating_width;
/** /**
* (Re)Build station list * (Re)Build station list
@@ -392,16 +391,17 @@ public:
} }
case WID_STL_LIST: case WID_STL_LIST:
resize->height = FONT_HEIGHT_NORMAL; resize->height = std::max(FONT_HEIGHT_NORMAL, FONT_HEIGHT_SMALL + ScaleFontTrad(3));
size->height = WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM; size->height = WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM;
break;
case WID_STL_TRAIN: /* Determine appropriate width for mini station rating graph */
case WID_STL_TRUCK: this->rating_width = 0;
case WID_STL_BUS: const CargoSpec *cs;
case WID_STL_AIRPLANE: FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
case WID_STL_SHIP: this->rating_width = std::max(this->rating_width, GetStringBoundingBox(cs->abbrev).width);
size->height = std::max<uint>(FONT_HEIGHT_SMALL, 10) + padding.height; }
/* Approximately match original 16 pixel wide rating bars by multiplying string width by 1.6 */
this->rating_width = this->rating_width * 16 / 10;
break; break;
case WID_STL_CARGOALL: case WID_STL_CARGOALL:
@@ -445,6 +445,12 @@ public:
bool rtl = _current_text_dir == TD_RTL; bool rtl = _current_text_dir == TD_RTL;
int max = std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->stations.size()); int max = std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->stations.size());
int y = r.top + WD_FRAMERECT_TOP; int y = r.top + WD_FRAMERECT_TOP;
uint line_height = this->GetWidget<NWidgetBase>(widget)->resize_y;
/* Spacing between station name and first rating graph. */
int text_spacing = ScaleFontTrad(5);
/* Spacing between additional rating graphs. */
int rating_spacing = ScaleFontTrad(4);
for (int i = this->vscroll->GetPosition(); i < max; ++i) { // do until max number of stations of owner for (int i = this->vscroll->GetPosition(); i < max; ++i) { // do until max number of stations of owner
const Station *st = this->stations[i]; const Station *st = this->stations[i];
assert(st->xy != INVALID_TILE); assert(st->xy != INVALID_TILE);
@@ -455,8 +461,8 @@ public:
SetDParam(0, st->index); SetDParam(0, st->index);
SetDParam(1, st->facilities); SetDParam(1, st->facilities);
int x = DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_STATION_LIST_STATION); int x = DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y + (line_height - FONT_HEIGHT_NORMAL) / 2, STR_STATION_LIST_STATION);
x += rtl ? -5 : 5; x += rtl ? -text_spacing : text_spacing;
/* show cargo waiting and station ratings */ /* show cargo waiting and station ratings */
for (uint j = 0; j < _sorted_standard_cargo_specs_size; j++) { for (uint j = 0; j < _sorted_standard_cargo_specs_size; j++) {
@@ -467,17 +473,17 @@ public:
* instead of drawing to the left and then incrementing * instead of drawing to the left and then incrementing
* the space. */ * the space. */
if (rtl) { if (rtl) {
x -= 20; x -= rating_width + rating_spacing;
if (x < r.left + WD_FRAMERECT_LEFT) break; if (x < r.left + WD_FRAMERECT_LEFT) break;
} }
StationsWndShowStationRating(x, x + 16, y, cid, st->goods[cid].cargo.TotalCount(), st->goods[cid].rating); StationsWndShowStationRating(x, x + rating_width, y, cid, st->goods[cid].cargo.TotalCount(), st->goods[cid].rating);
if (!rtl) { if (!rtl) {
x += 20; x += rating_width + rating_spacing;
if (x > r.right - WD_FRAMERECT_RIGHT) break; if (x > r.right - WD_FRAMERECT_RIGHT) break;
} }
} }
} }
y += FONT_HEIGHT_NORMAL; y += line_height;
} }
if (this->vscroll->GetCount() == 0) { // company has no stations if (this->vscroll->GetCount() == 0) { // company has no stations
@@ -488,30 +494,30 @@ public:
} }
case WID_STL_NOCARGOWAITING: { case WID_STL_NOCARGOWAITING: {
int cg_ofst = this->IsWidgetLowered(widget) ? 2 : 1; int cg_ofst = this->IsWidgetLowered(widget) ? 1 : 0;
DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + cg_ofst, STR_ABBREV_NONE, TC_BLACK, SA_HOR_CENTER); DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + (r.bottom - r.top - FONT_HEIGHT_SMALL) / 2 + cg_ofst, STR_ABBREV_NONE, TC_BLACK, SA_HOR_CENTER);
break; break;
} }
case WID_STL_CARGOALL: { case WID_STL_CARGOALL: {
int cg_ofst = this->IsWidgetLowered(widget) ? 2 : 1; int cg_ofst = this->IsWidgetLowered(widget) ? 1 : 0;
DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + cg_ofst, STR_ABBREV_ALL, TC_BLACK, SA_HOR_CENTER); DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + (r.bottom - r.top - FONT_HEIGHT_SMALL) / 2 + cg_ofst, STR_ABBREV_ALL, TC_BLACK, SA_HOR_CENTER);
break; break;
} }
case WID_STL_FACILALL: { case WID_STL_FACILALL: {
int cg_ofst = this->IsWidgetLowered(widget) ? 2 : 1; int cg_ofst = this->IsWidgetLowered(widget) ? 1 : 0;
DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + cg_ofst, STR_ABBREV_ALL, TC_BLACK, SA_HOR_CENTER); DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + (r.bottom - r.top - FONT_HEIGHT_SMALL) / 2 + cg_ofst, STR_ABBREV_ALL, TC_BLACK, SA_HOR_CENTER);
break; break;
} }
default: default:
if (widget >= WID_STL_CARGOSTART) { if (widget >= WID_STL_CARGOSTART) {
const CargoSpec *cs = _sorted_cargo_specs[widget - WID_STL_CARGOSTART]; const CargoSpec *cs = _sorted_cargo_specs[widget - WID_STL_CARGOSTART];
int cg_ofst = HasBit(this->cargo_filter, cs->Index()) ? 2 : 1; int cg_ofst = HasBit(this->cargo_filter, cs->Index()) ? 1 : 0;
GfxFillRect(r.left + cg_ofst, r.top + cg_ofst, r.right - 2 + cg_ofst, r.bottom - 2 + cg_ofst, cs->rating_colour); GfxFillRect(r.left + cg_ofst + 1, r.top + cg_ofst + 1, r.right - 1 + cg_ofst, r.bottom - 1 + cg_ofst, cs->rating_colour);
TextColour tc = GetContrastColour(cs->rating_colour); TextColour tc = GetContrastColour(cs->rating_colour);
DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + cg_ofst, cs->abbrev, tc, SA_HOR_CENTER); DrawString(r.left + cg_ofst, r.right + cg_ofst, r.top + (r.bottom - r.top - FONT_HEIGHT_SMALL) / 2 + cg_ofst, cs->abbrev, tc, SA_HOR_CENTER);
} }
break; break;
} }
@@ -720,7 +726,8 @@ static NWidgetBase *CargoWidgets(int *biggest_index)
for (uint i = 0; i < _sorted_standard_cargo_specs_size; i++) { for (uint i = 0; i < _sorted_standard_cargo_specs_size; i++) {
NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, WID_STL_CARGOSTART + i); NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, WID_STL_CARGOSTART + i);
panel->SetMinimalSize(14, 11); panel->SetMinimalSize(14, 0);
panel->SetMinimalTextLines(1, 0, FS_NORMAL);
panel->SetResize(0, 0); panel->SetResize(0, 0);
panel->SetFill(0, 1); panel->SetFill(0, 1);
panel->SetDataTip(0, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE); panel->SetDataTip(0, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE);
@@ -739,16 +746,16 @@ static const NWidgetPart _nested_company_stations_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY),
EndContainer(), EndContainer(),
NWidget(NWID_HORIZONTAL), NWidget(NWID_HORIZONTAL),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_TRAIN), SetMinimalSize(14, 11), SetDataTip(STR_TRAIN, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_TRAIN), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(STR_TRAIN, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_TRUCK), SetMinimalSize(14, 11), SetDataTip(STR_LORRY, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_TRUCK), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(STR_LORRY, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_BUS), SetMinimalSize(14, 11), SetDataTip(STR_BUS, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_BUS), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(STR_BUS, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_SHIP), SetMinimalSize(14, 11), SetDataTip(STR_SHIP, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_SHIP), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(STR_SHIP, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_AIRPLANE), SetMinimalSize(14, 11), SetDataTip(STR_PLANE, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_AIRPLANE), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(STR_PLANE, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE), SetFill(0, 1),
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_STL_FACILALL), SetMinimalSize(14, 11), SetDataTip(0x0, STR_STATION_LIST_SELECT_ALL_FACILITIES), SetFill(0, 1), NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_STL_FACILALL), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(0x0, STR_STATION_LIST_SELECT_ALL_FACILITIES), SetFill(0, 1),
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(5, 11), SetFill(0, 1), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(5, 0), SetFill(0, 1), EndContainer(),
NWidgetFunction(CargoWidgets), NWidgetFunction(CargoWidgets),
NWidget(WWT_PANEL, COLOUR_GREY, WID_STL_NOCARGOWAITING), SetMinimalSize(14, 11), SetDataTip(0x0, STR_STATION_LIST_NO_WAITING_CARGO), SetFill(0, 1), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_STL_NOCARGOWAITING), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(0x0, STR_STATION_LIST_NO_WAITING_CARGO), SetFill(0, 1), EndContainer(),
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_STL_CARGOALL), SetMinimalSize(14, 11), SetDataTip(0x0, STR_STATION_LIST_SELECT_ALL_TYPES), SetFill(0, 1), NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_STL_CARGOALL), SetMinimalSize(14, 0), SetMinimalTextLines(1, 0), SetDataTip(0x0, STR_STATION_LIST_SELECT_ALL_TYPES), SetFill(0, 1),
NWidget(WWT_PANEL, COLOUR_GREY), SetDataTip(0x0, STR_NULL), SetResize(1, 0), SetFill(1, 1), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), SetDataTip(0x0, STR_NULL), SetResize(1, 0), SetFill(1, 1), EndContainer(),
EndContainer(), EndContainer(),
NWidget(NWID_HORIZONTAL), NWidget(NWID_HORIZONTAL),

View File

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

View File

@@ -192,19 +192,35 @@ static void str_validate(T &dst, const char *str, const char *last, StringValida
while (str <= last && *str != '\0') { while (str <= last && *str != '\0') {
size_t len = Utf8EncodedCharLen(*str); size_t len = Utf8EncodedCharLen(*str);
/* If the character is unknown, i.e. encoded length is 0
* we assume worst case for the length check.
* The length check is needed to prevent Utf8Decode to read
* over the terminating '\0' if that happens to be placed
* within the encoding of an UTF8 character. */
if ((len == 0 && str + 4 > last) || str + len > last) break;
WChar c; WChar c;
len = Utf8Decode(&c, str); /* If the first byte does not look like the first byte of an encoded
/* It's possible to encode the string termination character * character, i.e. encoded length is 0, then this byte is definitely bad
* into a multiple bytes. This prevents those termination * and it should be skipped.
* characters to be skipped */ * When the first byte looks like the first byte of an encoded character,
if (c == '\0') break; * then the remaining bytes in the string are checked whether the whole
* encoded character can be there. If that is not the case, this byte is
* skipped.
* Finally we attempt to decode the encoded character, which does certain
* extra validations to see whether the correct number of bytes were used
* to encode the character. If that is not the case, the byte is probably
* invalid and it is skipped. We could emit a question mark, but then the
* logic below cannot just copy bytes, it would need to re-encode the
* decoded characters as the length in bytes may have changed.
*
* The goals here is to get as much valid Utf8 encoded characters from the
* source string to the destination string.
*
* Note: a multi-byte encoded termination ('\0') will trigger the encoded
* char length and the decoded length to differ, so it will be ignored as
* invalid character data. If it were to reach the termination, then we
* would also reach the "last" byte of the string and a normal '\0'
* termination will be placed after it.
*/
if (len == 0 || str + len > last || len != Utf8Decode(&c, str)) {
/* Maybe the next byte is still a valid character? */
str++;
continue;
}
if ((IsPrintable(c) && (c < SCC_SPRITE_START || c > SCC_SPRITE_END)) || ((settings & SVS_ALLOW_CONTROL_CODE) != 0 && c == SCC_ENCODED)) { if ((IsPrintable(c) && (c < SCC_SPRITE_START || c > SCC_SPRITE_END)) || ((settings & SVS_ALLOW_CONTROL_CODE) != 0 && c == SCC_ENCODED)) {
/* Copy the character back. Even if dst is current the same as str /* Copy the character back. Even if dst is current the same as str
@@ -225,6 +241,8 @@ static void str_validate(T &dst, const char *str, const char *last, StringValida
if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) *dst++ = '?'; if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) *dst++ = '?';
} }
} }
/* String termination, if needed, is left to the caller of this function. */
} }
/** /**

View File

@@ -30,25 +30,25 @@
#include "core/bitmath_func.hpp" #include "core/bitmath_func.hpp"
#include "string_type.h" #include "string_type.h"
char *strecat(char *dst, const char *src, const char *last); char *strecat(char *dst, const char *src, const char *last) NOACCESS(3);
char *strecpy(char *dst, const char *src, const char *last); char *strecpy(char *dst, const char *src, const char *last) NOACCESS(3);
char *stredup(const char *src, const char *last = nullptr); char *stredup(const char *src, const char *last = nullptr) NOACCESS(2);
int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4); int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4) NOACCESS(2);
int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) WARN_FORMAT(3, 0); int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) WARN_FORMAT(3, 0) NOACCESS(2);
char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2); char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2);
void str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); void str_validate(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2);
std::string str_validate(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); std::string str_validate(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
void ValidateString(const char *str); void ValidateString(const char *str);
void str_fix_scc_encoded(char *str, const char *last); void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2);
void str_strip_colours(char *str); void str_strip_colours(char *str);
bool strtolower(char *str); bool strtolower(char *str);
bool strtolower(std::string &str, std::string::size_type offs = 0); bool strtolower(std::string &str, std::string::size_type offs = 0);
bool StrValid(const char *str, const char *last); bool StrValid(const char *str, const char *last) NOACCESS(2);
/** /**
* Check if a string buffer is empty. * Check if a string buffer is empty.

View File

@@ -73,7 +73,17 @@ void UpdateTextEffect(TextEffectID te_id, StringID msg)
te->params_1 = GetDParam(0); te->params_1 = GetDParam(0);
te->params_2 = GetDParam(1); te->params_2 = GetDParam(1);
te->UpdatePosition(te->center, te->top, msg); te->UpdatePosition(te->center, te->top, te->string_id, te->string_id - 1);
}
void UpdateAllTextEffectVirtCoords()
{
for (auto &te : _text_effects) {
if (te.string_id == INVALID_STRING_ID) continue;
SetDParam(0, te.params_1);
SetDParam(1, te.params_2);
te.UpdatePosition(te.center, te.top, te.string_id, te.string_id - 1);
}
} }
void RemoveTextEffect(TextEffectID te_id) void RemoveTextEffect(TextEffectID te_id)

View File

@@ -32,6 +32,7 @@ void InitTextEffects();
void DrawTextEffects(DrawPixelInfo *dpi); void DrawTextEffects(DrawPixelInfo *dpi);
void UpdateTextEffect(TextEffectID effect_id, StringID msg); void UpdateTextEffect(TextEffectID effect_id, StringID msg);
void RemoveTextEffect(TextEffectID effect_id); void RemoveTextEffect(TextEffectID effect_id);
void UpdateAllTextEffectVirtCoords();
/* misc_gui.cpp */ /* misc_gui.cpp */
TextEffectID ShowFillingPercent(int x, int y, int z, uint8 percent, StringID colour); TextEffectID ShowFillingPercent(int x, int y, int z, uint8 percent, StringID colour);

View File

@@ -240,6 +240,11 @@ Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bo
return d; return d;
} }
void BaseVehicleListWindow::OnInit()
{
this->order_arrow_width = GetStringBoundingBox(STR_TINY_RIGHT_ARROW).width;
}
/** /**
* Display the Action dropdown window. * Display the Action dropdown window.
* @param show_autoreplace If true include the autoreplace item. * @param show_autoreplace If true include the autoreplace item.
@@ -1406,14 +1411,14 @@ static const NWidgetPart _nested_vehicle_list[] = {
EndContainer(), EndContainer(),
}; };
static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, VehicleOrderID start = 0) static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, uint order_arrow_width, VehicleOrderID start)
{ {
const Order *order = v->GetOrder(start); const Order *order = v->GetOrder(start);
if (order == nullptr) return; if (order == nullptr) return;
bool rtl = _current_text_dir == TD_RTL; bool rtl = _current_text_dir == TD_RTL;
int l_offset = rtl ? 0 : ScaleGUITrad(6); int l_offset = rtl ? 0 : order_arrow_width;
int r_offset = rtl ? ScaleGUITrad(6) : 0; int r_offset = rtl ? order_arrow_width : 0;
int i = 0; int i = 0;
VehicleOrderID oid = start; VehicleOrderID oid = start;
@@ -1438,11 +1443,11 @@ static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, Veh
} }
/** Draw small order list in the vehicle GUI, but without the little black arrow. This is used for shared order groups. */ /** Draw small order list in the vehicle GUI, but without the little black arrow. This is used for shared order groups. */
static void DrawSmallOrderList(const Order *order, int left, int right, int y) static void DrawSmallOrderList(const Order *order, int left, int right, int y, uint order_arrow_width)
{ {
bool rtl = _current_text_dir == TD_RTL; bool rtl = _current_text_dir == TD_RTL;
int l_offset = rtl ? 0 : ScaleGUITrad(6); int l_offset = rtl ? 0 : order_arrow_width;
int r_offset = rtl ? ScaleGUITrad(6) : 0; int r_offset = rtl ? order_arrow_width : 0;
int i = 0; int i = 0;
while (order != nullptr) { while (order != nullptr) {
if (order->IsType(OT_GOTO_STATION)) { if (order->IsType(OT_GOTO_STATION)) {
@@ -1550,7 +1555,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
DrawString(text_left, text_right, y, STR_TINY_GROUP, TC_BLACK); DrawString(text_left, text_right, y, STR_TINY_GROUP, TC_BLACK);
} }
if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, v->cur_real_order_index); if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, this->order_arrow_width, v->cur_real_order_index);
StringID str; StringID str;
if (v->IsChainInDepot()) { if (v->IsChainInDepot()) {
@@ -1572,7 +1577,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
DrawVehicleImage(vehgroup.vehicles_begin[i], image_left + 8 * i, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0); DrawVehicleImage(vehgroup.vehicles_begin[i], image_left + 8 * i, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0);
} }
if (show_orderlist) DrawSmallOrderList((vehgroup.vehicles_begin[0])->GetFirstOrder(), orderlist_left, orderlist_right, y); if (show_orderlist) DrawSmallOrderList((vehgroup.vehicles_begin[0])->GetFirstOrder(), orderlist_left, orderlist_right, y, this->order_arrow_width);
SetDParam(0, vehgroup.NumVehicles()); SetDParam(0, vehgroup.NumVehicles());
DrawString(left, right, y + 2, STR_BLACK_COMMA); DrawString(left, right, y + 2, STR_BLACK_COMMA);

View File

@@ -83,6 +83,7 @@ struct BaseVehicleListWindow : public Window {
byte unitnumber_digits; ///< The number of digits of the highest unit number. byte unitnumber_digits; ///< The number of digits of the highest unit number.
Scrollbar *vscroll; Scrollbar *vscroll;
VehicleListIdentifier vli; ///< Identifier of the vehicle list we want to currently show. VehicleListIdentifier vli; ///< Identifier of the vehicle list we want to currently show.
uint order_arrow_width; ///< Width of the arrow in the small order list.
typedef GUIVehicleGroupList::SortFunction VehicleGroupSortFunction; typedef GUIVehicleGroupList::SortFunction VehicleGroupSortFunction;
typedef GUIVehicleList::SortFunction VehicleIndividualSortFunction; typedef GUIVehicleList::SortFunction VehicleIndividualSortFunction;
@@ -104,6 +105,8 @@ struct BaseVehicleListWindow : public Window {
BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno); BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno);
void OnInit() override;
void UpdateSortingFromGrouping(); void UpdateSortingFromGrouping();
void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const; void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const;

View File

@@ -254,7 +254,7 @@ const char *VideoDriver_CocoaOpenGL::AllocateContext(bool allow_software)
CGLSetCurrentContext(this->gl_context); CGLSetCurrentContext(this->gl_context);
return OpenGLBackend::Create(&GetOGLProcAddressCallback); return OpenGLBackend::Create(&GetOGLProcAddressCallback, this->GetScreenSize());
} }
NSView *VideoDriver_CocoaOpenGL::AllocateDrawView() NSView *VideoDriver_CocoaOpenGL::AllocateDrawView()

View File

@@ -464,16 +464,17 @@ void SetupDebugOutput()
/** /**
* Create and initialize the singleton back-end class. * Create and initialize the singleton back-end class.
* @param get_proc Callback to get an OpenGL function from the OS driver. * @param get_proc Callback to get an OpenGL function from the OS driver.
* @param screen_res Current display resolution.
* @return nullptr on success, error message otherwise. * @return nullptr on success, error message otherwise.
*/ */
/* static */ const char *OpenGLBackend::Create(GetOGLProcAddressProc get_proc) /* static */ const char *OpenGLBackend::Create(GetOGLProcAddressProc get_proc, const Dimension &screen_res)
{ {
if (OpenGLBackend::instance != nullptr) OpenGLBackend::Destroy(); if (OpenGLBackend::instance != nullptr) OpenGLBackend::Destroy();
GetOGLProcAddress = get_proc; GetOGLProcAddress = get_proc;
OpenGLBackend::instance = new OpenGLBackend(); OpenGLBackend::instance = new OpenGLBackend();
return OpenGLBackend::instance->Init(); return OpenGLBackend::instance->Init(screen_res);
} }
/** /**
@@ -521,9 +522,10 @@ OpenGLBackend::~OpenGLBackend()
/** /**
* Check for the needed OpenGL functionality and allocate all resources. * Check for the needed OpenGL functionality and allocate all resources.
* @param screen_res Current display resolution.
* @return Error string or nullptr if successful. * @return Error string or nullptr if successful.
*/ */
const char *OpenGLBackend::Init() const char *OpenGLBackend::Init(const Dimension &screen_res)
{ {
if (!BindBasicInfoProcs()) return "OpenGL not supported"; if (!BindBasicInfoProcs()) return "OpenGL not supported";
@@ -546,6 +548,12 @@ const char *OpenGLBackend::Init()
_gl_major_ver = atoi(ver); _gl_major_ver = atoi(ver);
_gl_minor_ver = minor != nullptr ? atoi(minor + 1) : 0; _gl_minor_ver = minor != nullptr ? atoi(minor + 1) : 0;
#ifdef _WIN32
/* Old drivers on Windows (especially if made by Intel) seem to be
* unstable, so cull the oldest stuff here. */
if (!IsOpenGLVersionAtLeast(3, 2)) return "Need at least OpenGL version 3.2 on Windows";
#endif
if (!BindBasicOpenGLProcs()) return "Failed to bind basic OpenGL functions."; if (!BindBasicOpenGLProcs()) return "Failed to bind basic OpenGL functions.";
SetupDebugOutput(); SetupDebugOutput();
@@ -581,6 +589,11 @@ const char *OpenGLBackend::Init()
} }
if (this->persistent_mapping_supported) DEBUG(driver, 3, "OpenGL: Using persistent buffer mapping"); if (this->persistent_mapping_supported) DEBUG(driver, 3, "OpenGL: Using persistent buffer mapping");
/* Check maximum texture size against screen resolution. */
GLint max_tex_size = 0;
_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
if (std::max(screen_res.width, screen_res.height) > (uint)max_tex_size) return "Max supported texture size is too small";
/* Check available texture units. */ /* Check available texture units. */
GLint max_tex_units = 0; GLint max_tex_units = 0;
_glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_tex_units); _glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_tex_units);
@@ -1141,6 +1154,7 @@ void *OpenGLBackend::GetVideoBuffer()
#endif #endif
if (!this->persistent_mapping_supported) { if (!this->persistent_mapping_supported) {
assert(this->vid_buffer == nullptr);
_glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo); _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo);
this->vid_buffer = _glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE); this->vid_buffer = _glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
} else if (this->vid_buffer == nullptr) { } else if (this->vid_buffer == nullptr) {

View File

@@ -74,7 +74,7 @@ private:
OpenGLBackend(); OpenGLBackend();
~OpenGLBackend(); ~OpenGLBackend();
const char *Init(); const char *Init(const Dimension &screen_res);
bool InitShaders(); bool InitShaders();
void InternalClearCursorCache(); void InternalClearCursorCache();
@@ -87,7 +87,7 @@ public:
{ {
return OpenGLBackend::instance; return OpenGLBackend::instance;
} }
static const char *Create(GetOGLProcAddressProc get_proc); static const char *Create(GetOGLProcAddressProc get_proc, const Dimension &screen_res);
static void Destroy(); static void Destroy();
void PrepareContext(); void PrepareContext();

View File

@@ -74,6 +74,8 @@ const char *VideoDriver_SDL_OpenGL::Start(const StringList &param)
this->Stop(); this->Stop();
return "Can't get pointer to screen buffer"; return "Can't get pointer to screen buffer";
} }
/* Main loop expects to start with the buffer unmapped. */
this->ReleaseVideoPointer();
return nullptr; return nullptr;
} }
@@ -117,7 +119,7 @@ const char *VideoDriver_SDL_OpenGL::AllocateContext()
ToggleVsync(_video_vsync); ToggleVsync(_video_vsync);
return OpenGLBackend::Create(&GetOGLProcAddressCallback); return OpenGLBackend::Create(&GetOGLProcAddressCallback, this->GetScreenSize());
} }
void VideoDriver_SDL_OpenGL::PopulateSystemSprites() void VideoDriver_SDL_OpenGL::PopulateSystemSprites()

View File

@@ -97,27 +97,6 @@ void VideoDriver::StopGameThread()
this->game_thread.join(); this->game_thread.join();
} }
void VideoDriver::RealChangeBlitter(const char *repl_blitter)
{
const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName();
DEBUG(driver, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter);
Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter);
if (new_blitter == nullptr) NOT_REACHED();
DEBUG(driver, 1, "Successfully switched to %s.", repl_blitter);
if (!this->AfterBlitterChange()) {
/* Failed to switch blitter, let's hope we can return to the old one. */
if (BlitterFactory::SelectBlitter(cur_blitter) == nullptr || !this->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config");
}
/* Clear caches that might have sprites for another blitter. */
this->ClearSystemSprites();
ClearFontCache();
GfxClearSpriteCache();
ReInitAllWindows();
}
void VideoDriver::Tick() void VideoDriver::Tick()
{ {
if (!this->is_game_threaded && std::chrono::steady_clock::now() >= this->next_game_tick) { if (!this->is_game_threaded && std::chrono::steady_clock::now() >= this->next_game_tick) {
@@ -152,17 +131,15 @@ void VideoDriver::Tick()
this->fast_forward_via_key = false; this->fast_forward_via_key = false;
} }
/* Locking video buffer can block (especially with vsync enabled), do it before taking game state lock. */
this->LockVideoBuffer();
{ {
/* Tell the game-thread to stop so we can have a go. */ /* Tell the game-thread to stop so we can have a go. */
std::lock_guard<std::mutex> lock_wait(this->game_thread_wait_mutex); std::lock_guard<std::mutex> lock_wait(this->game_thread_wait_mutex);
std::lock_guard<std::mutex> lock_state(this->game_state_mutex); std::lock_guard<std::mutex> lock_state(this->game_state_mutex);
this->LockVideoBuffer(); this->DrainCommandQueue();
if (this->change_blitter != nullptr) {
this->RealChangeBlitter(this->change_blitter);
this->change_blitter = nullptr;
}
while (this->PollEvent()) {} while (this->PollEvent()) {}
::InputLoop(); ::InputLoop();

View File

@@ -22,6 +22,7 @@
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <functional>
extern std::string _ini_videodriver; extern std::string _ini_videodriver;
extern std::vector<Dimension> _resolutions; extern std::vector<Dimension> _resolutions;
@@ -36,7 +37,7 @@ class VideoDriver : public Driver {
const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height. const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height.
public: public:
VideoDriver() : fast_forward_key_pressed(false), fast_forward_via_key(false), is_game_threaded(true), change_blitter(nullptr) {} VideoDriver() : fast_forward_key_pressed(false), fast_forward_via_key(false), is_game_threaded(true) {}
/** /**
* Mark a particular area dirty. * Mark a particular area dirty.
@@ -178,12 +179,16 @@ public:
} }
/** /**
* Queue a request to change the blitter. This is not executed immediately, * Queue a function to be called on the main thread with game state
* but instead on the next draw-tick. * lock held and video buffer locked. Queued functions will be
* executed on the next draw tick.
* @param func Function to call.
*/ */
void ChangeBlitter(const char *new_blitter) void QueueOnMainThread(std::function<void()> &&func)
{ {
this->change_blitter = new_blitter; std::lock_guard<std::mutex> lock(this->cmd_queue_mutex);
this->cmd_queue.emplace_back(std::forward<std::function<void()>>(func));
} }
void GameLoopPause(); void GameLoopPause();
@@ -328,11 +333,29 @@ protected:
static void GameThreadThunk(VideoDriver *drv); static void GameThreadThunk(VideoDriver *drv);
private: private:
std::mutex cmd_queue_mutex;
std::vector<std::function<void()>> cmd_queue;
/** Execute all queued commands. */
void DrainCommandQueue()
{
std::vector<std::function<void()>> cmds{};
{
/* Exchange queue with an empty one to limit the time we
* hold the mutex. This also ensures that queued functions can
* add new functions to the queue without everything blocking. */
std::lock_guard<std::mutex> lock(this->cmd_queue_mutex);
cmds.swap(this->cmd_queue);
}
for (auto &f : cmds) {
f();
}
}
void GameLoop(); void GameLoop();
void GameThread(); void GameThread();
void RealChangeBlitter(const char *repl_blitter);
const char *change_blitter; ///< Request to change the blitter. nullptr if no pending request.
}; };
#endif /* VIDEO_VIDEO_DRIVER_HPP */ #endif /* VIDEO_VIDEO_DRIVER_HPP */

View File

@@ -1311,6 +1311,8 @@ const char *VideoDriver_Win32OpenGL::Start(const StringList &param)
_cur_resolution = old_res; _cur_resolution = old_res;
return "Can't get pointer to screen buffer"; return "Can't get pointer to screen buffer";
} }
/* Main loop expects to start with the buffer unmapped. */
this->ReleaseVideoPointer();
MarkWholeScreenDirty(); MarkWholeScreenDirty();
@@ -1360,14 +1362,22 @@ const char *VideoDriver_Win32OpenGL::AllocateContext()
/* Create OpenGL device context. Try to get an 3.2+ context if possible. */ /* Create OpenGL device context. Try to get an 3.2+ context if possible. */
if (_wglCreateContextAttribsARB != nullptr) { if (_wglCreateContextAttribsARB != nullptr) {
/* Try for OpenGL 4.5 first. */
int attribs[] = { int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 2, WGL_CONTEXT_MINOR_VERSION_ARB, 5,
WGL_CONTEXT_FLAGS_ARB, _debug_driver_level >= 8 ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, WGL_CONTEXT_FLAGS_ARB, _debug_driver_level >= 8 ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
_hasWGLARBCreateContextProfile ? WGL_CONTEXT_PROFILE_MASK_ARB : 0, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, // Terminate list if WGL_ARB_create_context_profile isn't supported. _hasWGLARBCreateContextProfile ? WGL_CONTEXT_PROFILE_MASK_ARB : 0, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, // Terminate list if WGL_ARB_create_context_profile isn't supported.
0 0
}; };
rc = _wglCreateContextAttribsARB(this->dc, nullptr, attribs); rc = _wglCreateContextAttribsARB(this->dc, nullptr, attribs);
if (rc == nullptr) {
/* Try again for a 3.2 context. */
attribs[1] = 3;
attribs[3] = 2;
rc = _wglCreateContextAttribsARB(this->dc, nullptr, attribs);
}
} }
if (rc == nullptr) { if (rc == nullptr) {
@@ -1380,7 +1390,7 @@ const char *VideoDriver_Win32OpenGL::AllocateContext()
this->ToggleVsync(_video_vsync); this->ToggleVsync(_video_vsync);
this->gl_rc = rc; this->gl_rc = rc;
return OpenGLBackend::Create(&GetOGLProcAddressCallback); return OpenGLBackend::Create(&GetOGLProcAddressCallback, this->GetScreenSize());
} }
bool VideoDriver_Win32OpenGL::ToggleFullscreen(bool full_screen) bool VideoDriver_Win32OpenGL::ToggleFullscreen(bool full_screen)

Some files were not shown because too many files have changed in this diff Show More