From 257d312a580e7c5d5df5749fafbc9471355a08d1 Mon Sep 17 00:00:00 2001 From: Koen Bussemaker Date: Wed, 10 Apr 2024 20:14:21 +0200 Subject: [PATCH 01/26] Fix #12228, Fix #12231: CheckShipReverse only restricts path when it has to --- src/pathfinder/yapf/yapf_ship.cpp | 110 +++++++++++++----------------- 1 file changed, 49 insertions(+), 61 deletions(-) diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp index 85f05747e5..57d5e9d877 100644 --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -172,6 +172,14 @@ public: return 'w'; } + /** Returns a random trackdir out of a set of trackdirs. */ + static Trackdir GetRandomTrackdir(TrackdirBits trackdirs) + { + const int strip_amount = RandomRange(CountBits(trackdirs)); + for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&trackdirs); + return FindFirstTrackdir(trackdirs); + } + /** Returns a random tile/trackdir that can be reached from the current tile/trackdir, or tile/INVALID_TRACK if none is available. */ static std::pair GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir) { @@ -180,17 +188,15 @@ public: TrackdirBits dirs = follower.m_new_td_bits; const TrackdirBits dirs_without_90_degree = dirs & ~TrackdirCrossesTrackdirs(dir); if (dirs_without_90_degree != TRACKDIR_BIT_NONE) dirs = dirs_without_90_degree; - const int strip_amount = RandomRange(CountBits(dirs)); - for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&dirs); - return { follower.m_new_tile, FindFirstTrackdir(dirs) }; + return { follower.m_new_tile, GetRandomTrackdir(dirs) }; } return { follower.m_new_tile, INVALID_TRACKDIR }; } /** Creates a random path, avoids 90 degree turns. */ - static Trackdir CreateRandomPath(const Ship *v, Trackdir dir, ShipPathCache &path_cache, int path_length) + static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length) { - std::pair tile_dir = { v->tile, dir }; + std::pair tile_dir = { v->tile, v->GetVehicleTrackdir()}; for (int i = 0; i < path_length; ++i) { tile_dir = GetRandomFollowUpTileTrackdir(v, tile_dir.first, tile_dir.second); if (tile_dir.second == INVALID_TRACKDIR) break; @@ -204,19 +210,14 @@ public: return result; } - static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache) + static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, TrackdirBits forward_dirs, TrackdirBits reverse_dirs, + bool &path_found, ShipPathCache &path_cache, Trackdir &best_origin_dir) { - const Trackdir trackdir = v->GetVehicleTrackdir(); - assert(IsValidTrackdir(trackdir)); - - /* Convert origin trackdir to TrackdirBits. */ - const TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir); - const std::vector high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1); if (high_level_path.empty()) { path_found = false; /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */ - return CreateRandomPath(v, trackdir, path_cache, SHIP_LOST_PATH_LENGTH); + return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH); } /* Try one time without restricting the search area, which generally results in better and more natural looking paths. @@ -226,7 +227,7 @@ public: Tpf pf(MAX_SHIP_PF_NODES); /* Set origin and destination nodes */ - pf.SetOrigin(v->tile, trackdirs); + pf.SetOrigin(v->tile, forward_dirs | reverse_dirs); pf.SetDestination(v); const bool is_intermediate_destination = static_cast(high_level_path.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1; if (is_intermediate_destination) pf.SetIntermediateDestination(high_level_path.back()); @@ -239,14 +240,16 @@ public: path_found = pf.FindPath(v); Node *node = pf.GetBestNode(); if (attempt == 0 && !path_found) continue; // Try again with restricted search area. - if (!path_found || node == nullptr) return GetRandomFollowUpTileTrackdir(v, v->tile, trackdir).second; + + /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */ + if (!path_found) return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH); /* Return only the path within the current water region if an intermediate destination was returned. If not, cache the entire path * to the final destination tile. The low-level pathfinder might actually prefer a different docking tile in a nearby region. Without * caching the full path the ship can get stuck in a loop. */ const WaterRegionPatchDesc end_water_patch = GetWaterRegionPatchInfo(node->GetTile()); - const WaterRegionPatchDesc start_water_patch = GetWaterRegionPatchInfo(tile); - assert(start_water_patch == high_level_path.front()); + assert(GetWaterRegionPatchInfo(tile) == high_level_path.front()); + const WaterRegionPatchDesc start_water_patch = high_level_path.front(); while (node->m_parent) { const WaterRegionPatchDesc node_water_patch = GetWaterRegionPatchInfo(node->GetTile()); @@ -262,10 +265,18 @@ public: } node = node->m_parent; } + assert(node->GetTile() == v->tile); + + /* Return INVALID_TRACKDIR to trigger a ship reversal if that is the best option. */ + best_origin_dir = node->GetTrackdir(); + if ((TrackdirToTrackdirBits(best_origin_dir) & forward_dirs) == TRACKDIR_BIT_NONE) { + path_cache.clear(); + return INVALID_TRACKDIR; + } /* A empty path means we are already at the destination. The pathfinder shouldn't have been called at all. * Return a random reachable trackdir to hopefully nudge the ship out of this strange situation. */ - if (path_cache.empty()) return GetRandomFollowUpTileTrackdir(v, v->tile, trackdir).second; + if (path_cache.empty()) return CreateRandomPath(v, path_cache, 1); /* Take out the last trackdir as the result. */ const Trackdir result = path_cache.front(); @@ -284,52 +295,30 @@ public: * Check whether a ship should reverse to reach its destination. * Called when leaving depot. * @param v Ship. - * @param tile Current position. - * @param td1 Forward direction. - * @param td2 Reverse direction. * @param trackdir [out] the best of all possible reversed trackdirs. * @return true if the reverse direction is better. */ - static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, Trackdir *trackdir) + static bool CheckShipReverse(const Ship *v, Trackdir *trackdir) { - const std::vector high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1); - if (high_level_path.empty()) { - if (trackdir) *trackdir = INVALID_TRACKDIR; - return false; - } + bool path_found = false; + ShipPathCache dummy_cache; + Trackdir best_origin_dir = INVALID_TRACKDIR; - /* Create pathfinder instance. */ - Tpf pf(MAX_SHIP_PF_NODES); - /* Set origin and destination nodes. */ if (trackdir == nullptr) { - pf.SetOrigin(tile, TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2)); - } else { - DiagDirection entry = ReverseDiagDir(VehicleExitDir(v->direction, v->state)); - TrackdirBits rtds = DiagdirReachesTrackdirs(entry) & TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, entry)); - pf.SetOrigin(tile, rtds); - } - pf.SetDestination(v); - if (high_level_path.size() > 1) pf.SetIntermediateDestination(high_level_path.back()); - pf.RestrictSearch(high_level_path); - - /* Find best path. */ - if (!pf.FindPath(v)) return false; - - Node *pNode = pf.GetBestNode(); - if (pNode == nullptr) return false; - - /* Path was found, walk through the path back to the origin. */ - while (pNode->m_parent != nullptr) { - pNode = pNode->m_parent; - } - - Trackdir best_trackdir = pNode->GetTrackdir(); - if (trackdir != nullptr) { - *trackdir = best_trackdir; + /* The normal case, typically called when ships leave a dock. */ + const Trackdir reverse_dir = ReverseTrackdir(v->GetVehicleTrackdir()); + const TrackdirBits forward_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir()); + const TrackdirBits reverse_dirs = TrackdirToTrackdirBits(reverse_dir); + (void)ChooseShipTrack(v, v->tile, forward_dirs, reverse_dirs, path_found, dummy_cache, best_origin_dir); + return path_found && best_origin_dir == reverse_dir; } else { - assert(best_trackdir == td1 || best_trackdir == td2); + /* This gets called when a ship suddenly can't move forward, e.g. due to terraforming. */ + const DiagDirection entry = ReverseDiagDir(VehicleExitDir(v->direction, v->state)); + const TrackdirBits reverse_dirs = DiagdirReachesTrackdirs(entry) & TrackStatusToTrackdirBits(GetTileTrackStatus(v->tile, TRANSPORT_WATER, 0, entry)); + (void)ChooseShipTrack(v, v->tile, TRACKDIR_BIT_NONE, reverse_dirs, path_found, dummy_cache, best_origin_dir); + *trackdir = path_found && best_origin_dir != INVALID_TRACKDIR ? best_origin_dir : GetRandomTrackdir(reverse_dirs); + return true; } - return best_trackdir != td1; } }; @@ -437,14 +426,13 @@ struct CYapfShip : CYapfTGetVehicleTrackdir()); + const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, TRACKDIR_BIT_NONE, path_found, path_cache, best_origin_dir); return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK; } bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir) { - Trackdir td = v->GetVehicleTrackdir(); - Trackdir td_rev = ReverseTrackdir(td); - TileIndex tile = v->tile; - return CYapfShip::CheckShipReverse(v, tile, td, td_rev, trackdir); + return CYapfShip::CheckShipReverse(v, trackdir); } From 018326321cef0468855bb9f37622ef948e002ab4 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 17 Apr 2024 04:40:56 +0000 Subject: [PATCH 02/26] Update: Translations from eints english (us): 5 changes by 2TallTyler latvian: 1 change by lexuslatvia --- src/lang/afrikaans.txt | 1 + src/lang/arabic_egypt.txt | 1 + src/lang/basque.txt | 1 + src/lang/belarusian.txt | 1 + src/lang/brazilian_portuguese.txt | 1 + src/lang/bulgarian.txt | 1 + src/lang/catalan.txt | 1 + src/lang/chuvash.txt | 1 + src/lang/croatian.txt | 1 + src/lang/czech.txt | 1 + src/lang/danish.txt | 1 + src/lang/dutch.txt | 1 + src/lang/english_AU.txt | 1 + src/lang/english_US.txt | 6 ++++++ src/lang/esperanto.txt | 1 + src/lang/estonian.txt | 1 + src/lang/faroese.txt | 1 + src/lang/finnish.txt | 1 + src/lang/french.txt | 1 + src/lang/frisian.txt | 1 + src/lang/gaelic.txt | 1 + src/lang/galician.txt | 1 + src/lang/german.txt | 1 + src/lang/greek.txt | 1 + src/lang/hebrew.txt | 1 + src/lang/hindi.txt | 1 + src/lang/hungarian.txt | 1 + src/lang/icelandic.txt | 1 + src/lang/ido.txt | 1 + src/lang/indonesian.txt | 1 + src/lang/irish.txt | 1 + src/lang/italian.txt | 1 + src/lang/japanese.txt | 1 + src/lang/korean.txt | 1 + src/lang/latin.txt | 1 + src/lang/latvian.txt | 2 ++ src/lang/lithuanian.txt | 1 + src/lang/luxembourgish.txt | 1 + src/lang/macedonian.txt | 1 + src/lang/malay.txt | 1 + src/lang/maltese.txt | 1 + src/lang/marathi.txt | 1 + src/lang/norwegian_bokmal.txt | 1 + src/lang/norwegian_nynorsk.txt | 1 + src/lang/persian.txt | 1 + src/lang/polish.txt | 1 + src/lang/portuguese.txt | 1 + src/lang/romanian.txt | 1 + src/lang/russian.txt | 1 + src/lang/serbian.txt | 1 + src/lang/simplified_chinese.txt | 1 + src/lang/slovak.txt | 1 + src/lang/slovenian.txt | 1 + src/lang/spanish.txt | 1 + src/lang/spanish_MX.txt | 1 + src/lang/swedish.txt | 1 + src/lang/tamil.txt | 1 + src/lang/thai.txt | 1 + src/lang/traditional_chinese.txt | 1 + src/lang/turkish.txt | 1 + src/lang/ukrainian.txt | 1 + src/lang/urdu.txt | 1 + src/lang/vietnamese.txt | 1 + src/lang/welsh.txt | 1 + 64 files changed, 70 insertions(+) diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt index ce69bbe327..3d08a12588 100644 --- a/src/lang/afrikaans.txt +++ b/src/lang/afrikaans.txt @@ -4624,6 +4624,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Verander STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Geen voertuie is op die oomblik beskikbaar nie STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Begin na {DATE_SHORT} of gebruik 'n NewGRF wat voertuie vroeër beskikbaar stel + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan nie trein forseer om sein te vermy op gevaar... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kan nie rigting van trein verander nie... diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt index 184010a6a3..2be1344d26 100644 --- a/src/lang/arabic_egypt.txt +++ b/src/lang/arabic_egypt.txt @@ -4418,6 +4418,7 @@ STR_ERROR_CAN_T_CLONE_VEHICLE_LIST :{WHITE}... لي STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}لن تتوافر اى وسائل نقل على اﻹطلاق STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}لا تتوافر اى آليه نقل بعد + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}لا يمكن السماح للقطار بالعبور من الاشارة في وضع الخطر STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}لا يمكن عكس اتجاة القطار... diff --git a/src/lang/basque.txt b/src/lang/basque.txt index 7580ed6e94..cbf591f95d 100644 --- a/src/lang/basque.txt +++ b/src/lang/basque.txt @@ -4369,6 +4369,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}Ez da ib STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Aldatu zure NewGRF konfigurazioa STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Ez dago ibilgailu erabilgarririk oraindik + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Ezin da trena seinalea pasatzera behartu, istripu arriskua... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Ezin da trenaren norabidea aldatu... diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt index 3a1de5eaf2..73d9a197ed 100644 --- a/src/lang/belarusian.txt +++ b/src/lang/belarusian.txt @@ -5631,6 +5631,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Зьмя STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Няма даступных транспартных сродкаў STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Пачніце гульню пасьля {DATE_SHORT} або падключыце NewGRF з транспартам адпаведных часоў. + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Немагчыма іґнараваць сыґнал. Небясьпечна... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Не атрымалася завярнуць цягнік... diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 9ba9130d8c..860a5f0184 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -5287,6 +5287,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Modifiqu STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Não existem veículos disponíveis ainda STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Inicie um novo jogo depois de {DATE_SHORT} ou utilize um NewGRF que forneça veículos iniciais + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Não é possível fazer o trem passar o sinal em perigo... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Não é possível inverter a direção do trem... diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt index 0d9efe83bd..b432c9e60a 100644 --- a/src/lang/bulgarian.txt +++ b/src/lang/bulgarian.txt @@ -4654,6 +4654,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Пром STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Няма налични превозни средства все още STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Започни нова игра след {DATE_SHORT} или използвай NewGRF , който показва ранни превозни средства + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Влака не може да пропусне сигнала при опасност... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Не може да обърне посоката на влак... diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index e40ab9c7e5..5da45529ba 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -5287,6 +5287,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Canvia l STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Encara no hi ha vehicles disponibles STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Inicieu una partida nova després de {DATE_SHORT} o useu un NewGRF que proporcioni vehicles primerencs. + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}No pots fer que un tren passi d'una senyal amb perill... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}No es pot invertir la direcció del tren... diff --git a/src/lang/chuvash.txt b/src/lang/chuvash.txt index 36c2e5f642..1bd4cd3df0 100644 --- a/src/lang/chuvash.txt +++ b/src/lang/chuvash.txt @@ -1709,6 +1709,7 @@ STR_ERROR_OBJECT_IN_THE_WAY :{WHITE}Ҫул + # Specific vehicle errors diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index 00c09c6dc6..6435b15c58 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -4812,6 +4812,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Promijen STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Još nema dostupnih vozila STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Pokreni novu igru nakon {DATE_SHORT} ili upotrijebi NewGRF koji daje vrlo rana vozila + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nije moguće natjerati vlak da ignorira signale dok traje opasnost... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nije moguće promijeniti smjer vlaka... diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 7b83851a3c..47af6fe005 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -5376,6 +5376,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Zmeň na STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Zatím nejsou dostupná žádná vozidla STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Začít hru po {DATE_SHORT} nebo použít NewGRF, která zajistí dřívější vozidla + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nelze nechat vlak projet semafory v nebezpečí... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nelze obrátit vlak... diff --git a/src/lang/danish.txt b/src/lang/danish.txt index d0a9398d6b..ad5dad7ec9 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -5286,6 +5286,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Skift di STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Ingen køretøjer er tilgængelige endnu STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Start et nyt spil efter {DATE_SHORT} eller brug en NewGRF der giver tidlige køretøjer + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan ikke få toget til at passere signalet... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kan ikke vende retningen af toget... diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 25fb25b497..bea3abf06e 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -5286,6 +5286,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Pas je N STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Nog geen voertuigen beschikbaar STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE} Start een nieuw spel na {DATE_SHORT} of gebruik een NewGRF dat in vroege voertuigen voorziet + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan trein niet het sein laten passeren bij gevaar... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kan de richting van de trein niet omdraaien... diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index f71ba405c9..f432d6d71b 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -5286,6 +5286,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change y STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}No vehicles are available yet STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF which provides early vehicles + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Can't reverse direction of train... diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 9c28e0f7b0..f9ffd8aaf2 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -3488,6 +3488,9 @@ STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_ROAD_TYPE :Road type STR_NEWGRF_INSPECT_QUERY_CAPTION :{WHITE}NewGRF variable 60+x parameter (hexadecimal) # Sprite aligner window +STR_SPRITE_ALIGNER_CAPTION_NO_ACTION :{WHITE}Aligning sprite: ({STRING}:{NUM}) +STR_SPRITE_ALIGNER_CAPTION_ACTIONA :{WHITE}Aligning sprite: Action 0xA, {COMMA} ({STRING}:{NUM}) +STR_SPRITE_ALIGNER_CAPTION_ACTION5 :{WHITE}Aligning sprite: Action 0x5, type {HEX}, {COMMA} ({STRING}:{NUM}) STR_SPRITE_ALIGNER_NEXT_BUTTON :{BLACK}Next sprite STR_SPRITE_ALIGNER_NEXT_TOOLTIP :{BLACK}Proceed to the next normal sprite, skipping any pseudo/recolor/font sprites and wrapping around from the last sprite to the first STR_SPRITE_ALIGNER_GOTO_BUTTON :{BLACK}Go to sprite @@ -3496,6 +3499,7 @@ STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Previous STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Proceed to the previous normal sprite, skipping any pseudo/recolor/font sprites and wrapping around from the first sprite to the last STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Representation of the currently selected sprite. The alignment is ignored when drawing this sprite STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Move the sprite around, changing the X and Y offsets. Ctrl+Click to move the sprite eight units at a time +STR_SPRITE_ALIGNER_SPRITE :{STRING}:{NUM} ###length 2 STR_SPRITE_ALIGNER_CENTRE_OFFSET :{BLACK}Offset centered @@ -5282,6 +5286,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change y STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}No vehicles are available yet STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF that provides early vehicles + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Can't reverse direction of train... @@ -5832,6 +5837,7 @@ STR_JUST_DATE_ISO :{DATE_ISO} STR_JUST_STRING :{STRING} STR_JUST_STRING1 :{STRING} STR_JUST_STRING2 :{STRING} +STR_JUST_STRING4 :{STRING} STR_JUST_STRING_STRING :{STRING}{STRING} STR_JUST_RAW_STRING :{STRING} STR_JUST_BIG_RAW_STRING :{BIG_FONT}{STRING} diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt index a9c026defe..118a9baa90 100644 --- a/src/lang/esperanto.txt +++ b/src/lang/esperanto.txt @@ -5144,6 +5144,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Ŝanĝu STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Neniuj veturiloj dume haveblas STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Komencu novan ludon post {DATE_SHORT} aŭ uzu NewGRF-on kiu havebligas frutempajn veturilojn + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Ne povas igi vagonaron transiri signalon je danĝero... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Ne povas inversigi direkton de vagonaro... diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index efcdc634d5..ed67e64d0b 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -5334,6 +5334,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Muuda Ne STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Sõidukeid ei ole veel saadaval STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Alusta mängu pärast {DATE_SHORT} või kasuta NewGRF-i, milles on varasemaid sõidukeid + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Rongi ei saa ohu korral sundida signaale eirama... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Ei saa rongi ümber pöörata. diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt index 5de884b32e..5e6b384a67 100644 --- a/src/lang/faroese.txt +++ b/src/lang/faroese.txt @@ -4024,6 +4024,7 @@ STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... akfa + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kann ikki fáa tok at fara framvið jarnbreytatekin tá vandi er... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kann ikki venda toki vi... diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 9e618188f2..017948e152 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -5286,6 +5286,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Muuta Ne STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Kulkuneuvoja ei ole vielä saatavilla STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Aloita peli {DATE_SHORT} jälkeen tai käytä NewGRF:ää joka tarjoaa aikaisempia kulkuneuvoja + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Junaa ei voi pakottaa jatkamaan punaisen opastimen ohi... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Junan suuntaa ei voi kääntää... diff --git a/src/lang/french.txt b/src/lang/french.txt index 383c102faf..b67f2b1132 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -5287,6 +5287,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Modifier STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Il n'y a pas encore de véhicules disponibles STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Commencer un nouvelle partie après {DATE_SHORT} ou utiliser un NewGRF qui propose des véhicules plus tôt + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Impossible de forcer le train à avancer sous le danger... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Impossible de faire faire demi-tour... diff --git a/src/lang/frisian.txt b/src/lang/frisian.txt index 71055270df..e32bf24f5c 100644 --- a/src/lang/frisian.txt +++ b/src/lang/frisian.txt @@ -4205,6 +4205,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Feroarje STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Der binne noch gjin fiertugen beskikber STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Begjin in nij spul nei {DATE_SHORT} of brûk in NewGRF dy't earder fiertugen beskikber stelt + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kin trein gjin sein foarby ride litte at dizze gefaar oanjout... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kin rydrjochting fan de trein net oanpasse diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt index 11805cc18f..88cb7c19d8 100644 --- a/src/lang/gaelic.txt +++ b/src/lang/gaelic.txt @@ -4761,6 +4761,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Atharrai STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Chan eil carbad ri fhaighinn fhathast STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Tòisich geama ùr às dèidh {DATE_SHORT} no chleachd NewGRF a bheir carbadan tràtha dhut + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Chan urrainn dhut toirt air trèanaichean dol seachad air comharra fo chunnart... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Chan urrainn dhan trèana tilleadh... diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 15754aa2b0..7d04ac030f 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -5279,6 +5279,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Cambia a STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Aínda non hai vehículos dispoñíbeis STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Comezar unha partida nova a partires de {DATE_SHORT} ou empregar un NewGRF que proporcione vehículos antigos + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Non se pode facer que o tren rebase un sinal en perigo... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}No se pode cambia-lo sentido do tren... diff --git a/src/lang/german.txt b/src/lang/german.txt index 9b3bcd883e..16fb7581fc 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -5281,6 +5281,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Bitte di STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Noch keine Fahrzeuge verfügbar STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Ein neues Spiel nach {DATE_SHORT} beginnen oder ein NewGRF-Fahrzeugset mit früher verfügbaren Fahrzeugen verwenden + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Der Zug kann das Signal nicht gefahrlos passieren ... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Die Zugbewegung kann nicht umgekehrt werden ... diff --git a/src/lang/greek.txt b/src/lang/greek.txt index f14aadb289..ea3dad2136 100644 --- a/src/lang/greek.txt +++ b/src/lang/greek.txt @@ -5386,6 +5386,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Αλλά STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Κανένα όχημα δεν είναι διαθέσιμο ακόμη STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Ξεκινήστε ένα νέο παιχνίδι αργότερα από {DATE_SHORT} η χρησιμοποιήστε ένα NewGRF το οποίο προσφέρει νωρίτερα οχήματα + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Δεν μπορεί το τρένο να περάσει σήμα με κίνδυνο... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Δεν αντιστρέφεται η κατεύθυνση του τρένου... diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index bc66be2033..e92de862c5 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -4687,6 +4687,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}שנה STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}כלי תחבורה עדיין לא זמינים STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}התחל משחק חדש אחרי {DATE_SHORT} או השתמש ב-NewGRF המכיל כלי תחבורה קדומים + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}לא ניתן להכריח את הרכבת לעבור ברמזור בעת סכנה... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}לא ניתן להפוך את כיוון הנסיעה של הרכבת... diff --git a/src/lang/hindi.txt b/src/lang/hindi.txt index 30c1dabb8e..534b54a7cc 100644 --- a/src/lang/hindi.txt +++ b/src/lang/hindi.txt @@ -1574,6 +1574,7 @@ STR_ERROR_CAN_T_SELL_TRAIN :{WHITE}रे + # Specific vehicle errors STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}ट्रेन की दिशा उलट नहीं सकते... diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index 59203dde4b..a24baec0e5 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -5341,6 +5341,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Változt STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Még nincsenek elérhető járművek STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Indíts új játékot {DATE_SHORT} után, vagy használj olyan NewGRF-et, ami tartalmaz megfelelően korai járműveket! + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nem haladhatja meg a vonat a megállj jelzést... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nem fordíthatod meg a vonatot... diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt index 5ba52905e3..09d9780897 100644 --- a/src/lang/icelandic.txt +++ b/src/lang/icelandic.txt @@ -4255,6 +4255,7 @@ STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... öku STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}Engin farartæki verða í boði STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Breyta NewGRF stillingunum þínum + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Get ekki látið lest fara framhjá hættumerki... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Get ekki snúið lest við... diff --git a/src/lang/ido.txt b/src/lang/ido.txt index 0ba0d4e163..ac7b50ddad 100644 --- a/src/lang/ido.txt +++ b/src/lang/ido.txt @@ -1600,6 +1600,7 @@ STR_ERROR_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Tro mult + # Specific vehicle errors diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index 177b0d2eeb..99fb0fc61e 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -5161,6 +5161,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Tukarkan STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Belum ada kendaraan yang tersedia saat ini STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Mulai permainan baru setelah {DATE_SHORT} atau gunakan NewGRF yang menyediakan kendaraan awal + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Tidak dapat memaksa kereta melanggar sinyal pada saat bahaya... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Tidak dapat memutar balik arah kereta... diff --git a/src/lang/irish.txt b/src/lang/irish.txt index 90825adf64..d99a87a45b 100644 --- a/src/lang/irish.txt +++ b/src/lang/irish.txt @@ -4865,6 +4865,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Athraigh STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Níl aon fheithicil ar fáil fós STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Tosaigh cluiche nua ó {DATE_SHORT} ar aghaidh nó úsáid NewGRF lena gcuirtear feithiclí luath ar fáil + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Ní féidir iallach a chur ar thraein dul thar comhartha agus contúirt ann... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Ní féidir treo na traenach a aisiompú... diff --git a/src/lang/italian.txt b/src/lang/italian.txt index 436d86cdb8..05195c2e51 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -5319,6 +5319,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Cambiare STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Non sono ancora disponibili veicoli STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Iniziare una nuova partita dopo il {DATE_SHORT} o utilizzare un NewGRF che fornisca veicoli a partire da date antecedenti + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Impossibile far passare al treno un segnale di pericolo... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Impossibile invertire la direzione del treno... diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index 115fced9f5..f3e61dccff 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -4988,6 +4988,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}NewGRF STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}利用可能な輸送機器がありません STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}{DATE_SHORT}年以降に開始するか、これより早い時期に輸送機器が開発されるNewGRFを利用して下さい + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}赤信号を無視させることができません STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}列車を反転できません diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 60ef5f39ab..c4cfb0abfe 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -5283,6 +5283,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}NewGRF STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}사용할 수 있는 차량이 하나도 없습니다 STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}{DATE_SHORT}년 이후에 새로운 게임을 시작하거나 차량이 더 빨리 개발되는 NewGRF을 사용하십시오. + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}너무 위험해서 신호를 무시할 수 없습니다... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}열차를 회차시킬 수 없습니다... diff --git a/src/lang/latin.txt b/src/lang/latin.txt index 25bc4e2b3a..6bc1b21f6a 100644 --- a/src/lang/latin.txt +++ b/src/lang/latin.txt @@ -4752,6 +4752,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Muta con STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Nulla vehicula adhuc parabilia sunt STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Incipe ludum post {DATE_SHORT} sive eligere idoneum NewGRF quod vehicula antiqua parat + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Non licet tramen impellere post signale... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Non licet tramini cursum reflectere... diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index 9fb76b9052..6b759b0315 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -2578,6 +2578,7 @@ STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE} Jūsu s STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE} Jūsu servera nosaukums nav iestatīts. Nosaukumu var iestatīt vairākspēlētāju loga augšdaļā STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Klienta pārskats neatbilst servera pārskatam STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Nepareiza parole +STR_NETWORK_ERROR_NOT_ON_ALLOW_LIST :{WHITE}Jūs neesat atļauto klientu sarakstā STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Serveris ir pilns STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Šajā serverī jums ir aizliegums STR_NETWORK_ERROR_KICKED :{WHITE}Jūs esat izmests no šīs spēles @@ -5295,6 +5296,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Mainiet STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Transportlīdzekļi vēl nav pieejami STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Sākt jaunu spēli pēc {DATE_SHORT} vai izmantot NewGRF, kas nodrošina agrīnus transporta līdzekļus + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Vilciens nevar šķērsot signālu briesmās... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Vilcienu nevar apgriezt... diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt index 578359c1bb..798f207e21 100644 --- a/src/lang/lithuanian.txt +++ b/src/lang/lithuanian.txt @@ -5207,6 +5207,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Pakeiski STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Kol kas negalima įsigyti jokių transporto priemonių STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Pradėkite žaidimą vėliau, nei {DATE_SHORT}, arba įdiekite plėtinių, kurie leistų įsigyti transporto priemonių šiame ankstyvame laikotarpyje + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Neįmanoma priversti traukinio važiuoti nesaugiai... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Traukinio vaziavimo krypties pakeisti negalima... diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index ef41844276..f19ae7f54e 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -5277,6 +5277,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Änner d STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Nach keng Gefierer verfügbar STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}En neit Spill no {DATE_SHORT} ufenken oder benotz en NewGRF den al Gefierer erlaabt + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kann den Zuch net bei Gefor durch d'Signal schécken... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kann d'Richtung vum Zuch net änneren... diff --git a/src/lang/macedonian.txt b/src/lang/macedonian.txt index 44bd9b1723..4a0d5308d8 100644 --- a/src/lang/macedonian.txt +++ b/src/lang/macedonian.txt @@ -2117,6 +2117,7 @@ STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... во + # Specific vehicle errors diff --git a/src/lang/malay.txt b/src/lang/malay.txt index 51a7aee810..5266a35664 100644 --- a/src/lang/malay.txt +++ b/src/lang/malay.txt @@ -4161,6 +4161,7 @@ STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... kend STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Mulakan permainan baru selepas {DATE_SHORT} atau gunakan NewGRF yang digunakan kenderaan terdahulu + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Keretapi tidak boleh melanggar isyarat kerana terdapat kemungkinan bahaya... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Keretapi tidak boleh ditukar arah... diff --git a/src/lang/maltese.txt b/src/lang/maltese.txt index 4c41075122..da063b328a 100644 --- a/src/lang/maltese.txt +++ b/src/lang/maltese.txt @@ -1468,6 +1468,7 @@ STR_ERROR_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Hemm wis + # Specific vehicle errors STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Ma tistax tbiddel id-direzzjoni tal-ferrovija... diff --git a/src/lang/marathi.txt b/src/lang/marathi.txt index dac56fa193..112edf8266 100644 --- a/src/lang/marathi.txt +++ b/src/lang/marathi.txt @@ -1867,6 +1867,7 @@ STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}पू + # Specific vehicle errors diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 3953b8868c..64a30700d5 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -5288,6 +5288,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Endre di STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Ingen kjøretøyer er tilgjengelig ennå STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Starte et nytt spill etter {DATE_SHORT}, eller bruke en NewGRF som inneholder tidlige kjøretøy + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan ikke tvinge tog til å passere signal ved fare... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kan ikke reversere toget... diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt index ed09582836..43ad419318 100644 --- a/src/lang/norwegian_nynorsk.txt +++ b/src/lang/norwegian_nynorsk.txt @@ -4396,6 +4396,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Byt NewG STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Det finst ikkje nokon køyretøy enno STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Start spelet etter {DATE_SHORT} eller bruk ein GRF som har køyretøy frå tidlegare tider + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan ikkje tvinge tog til å passere signal ved fare... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kan ikkje snu toget... diff --git a/src/lang/persian.txt b/src/lang/persian.txt index f08def6a82..00c2596bc2 100644 --- a/src/lang/persian.txt +++ b/src/lang/persian.txt @@ -3748,6 +3748,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}بطور STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}تنظیمات مربوط به NewGRF را تغییر دهید STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}هنوز خودرویی در دسترس نیست + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}در هنگام خطر نمی توان علامت عبور قطار را داد STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}جهت قطار را نمی شود تغییر داد... diff --git a/src/lang/polish.txt b/src/lang/polish.txt index 3a0a8fd9fe..ae307a167f 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -5672,6 +5672,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Zmień k STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Obecnie żaden pojazd nie jest dostępny STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Zacznij grę po {DATE_SHORT} albo użyj zestawu NewGRF, który zawiera wczesne pojazdy + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nie można przepuścić pociągu za sygnał, niebezpieczeństwo... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nie można odwrócić kierunku jazdy pociągu... diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 31193cbcda..6c7e8b5904 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -5287,6 +5287,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Mudar a STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Nenhum veículo ainda disponível STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Começar um novo jogo depois de {DATE_SHORT} ou utilizar um NewGRF que forneça veículos iniciais + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Não é possível fazer o comboio passar o sinal com perigo... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Não é possível inverter a direcção do comboio... diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index ea9177a1dc..2d016ba1ad 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -5273,6 +5273,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Schimbă STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Niciun vehicul nu este disponibil încă STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Începe un joc nou după {DATE_SHORT} sau utilizează un NewGRF care oferă vehicule în avans + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nu se poate permite trenului să treacă în caz de pericol... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nu se poate schimba sensul de mers al trenului... diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 56dcbbf559..598bb83968 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -5473,6 +5473,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Изме STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Нет доступных транспортных средств STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Начните игру не ранее {DATE_SHORT} либо подключите NewGRF, добавляющий транспортные средства, использовавшиеся в это время. + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Невозможно игнорировать светофор. Опасно... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Невозможно развернуть поезд... diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt index 83b03e555c..6ca88c3f00 100644 --- a/src/lang/serbian.txt +++ b/src/lang/serbian.txt @@ -5380,6 +5380,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Promeni STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Nijedno vozilo još uvek nije dostupno STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Pokreni novu igru koja počinje posle {DATE_SHORT} ili koristi NewGRF koji omogućava ranija vozila + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nemoguć je prolaz voza na signal opasnosti... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}... vozilo je uništeno diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index c5c24441a1..4ca83af535 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -5283,6 +5283,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}请改 STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}暂时沒有可用的载具 STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}在{DATE_SHORT}后开始新游戏,或使用一款能提供早期载具的NewGRF + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}不能让列车冒险通过信号... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}不能命令列车调头... diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 058d87d45a..8ce5a9f166 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -5348,6 +5348,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Zmena va STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Zatiaľ nie sú dostupné žiadne vozidlá STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Začnite novú hru po {DATE_SHORT} alebo použite NewGRF, ktoré zabezpečí vozidlá v skoršom čase + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nemožno nechať vlak prejsť návestidlo ak hrozí nebezpečenstvo... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Nemožno otočiť vlak naopak... diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt index b8fa8435c9..c8149b0ebb 100644 --- a/src/lang/slovenian.txt +++ b/src/lang/slovenian.txt @@ -4645,6 +4645,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Zamenjaj STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Ni še vozil na razpolago. STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Začni novo igro po {DATE_SHORT} ali uporabi NewGRF, ki vsebuje zgodnja vozila + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Ni mogoče, da vlak v nevarnosti pelje mimo signalov... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Ni mogoče spremeniti smeri vlaka... diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index e4921fda2c..0624ce69bd 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -5287,6 +5287,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Es neces STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}En esta fecha no hay vehículos disponibles STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Comienza una nueva partida después de {DATE_SHORT} o usa un NewGRF que provea vehículos más antiguos + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}No se puede pasar la señal en peligro al tren... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}No se puede cambiar la dirección... diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 8b734a5842..1753a04fde 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -5157,6 +5157,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Se debe STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Todavía no hay vehículos disponibles STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Se debe empezar una nueva partida después de {DATE_SHORT} o usar un NewGRF que proporcione vehículos más antiguos + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}El tren no puede rebasar la señal si está en peligro... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}No se puede cambiar la dirección del tren... diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 41607130c9..823870fc23 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -5286,6 +5286,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Ändra d STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Inga fordon är tillgängliga än STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Starta ett nytt spel efter {DATE_SHORT} eller använd en NewGRF som erbjuder tidiga fordon + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan inte tillåta tåg att passera signal under fara... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Kan inte byta tågets riktning... diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt index 0556acd908..be2da27776 100644 --- a/src/lang/tamil.txt +++ b/src/lang/tamil.txt @@ -4871,6 +4871,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}தங STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}தற்போது எந்த வாகனங்களும் கிடையாது STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}{DATE_SHORT} இற்கு பிறகு புதிய ஆட்டம் ஒன்றினைத் தொடங்கு அல்லது NewGRF ஒன்றினைப் பயன்படுத்தி பிற்கால வாகனங்களைப் பயன்படுத்து + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}இரயில் சிக்னலைத் தாண்டிச் செல்ல முடியாது... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}இரயில் செல்லும் திசையினை திருப்ப முடியாது... diff --git a/src/lang/thai.txt b/src/lang/thai.txt index 421e65bb87..a9fd5a7a83 100644 --- a/src/lang/thai.txt +++ b/src/lang/thai.txt @@ -4601,6 +4601,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}เป STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}ยังไม่มียานพาหานะให้เลือก STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}เริ่มเกมหลังจาก {DATE_SHORT} หรือเลือกใช้งาน NewGRF ของยานพาหนะที่จัดเตรียมไว้ก่อนหน้านี้ + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}ไม่สามารถสั่งให้รถไฟวิ่งผ่านเสาอาณัติสัญญาณที่แสดงท่า "ห้าม"... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}ไม่สามารถกลับทิศขบวนรถไฟได้... diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index d0ee79f49f..27dd3f671c 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -5102,6 +5102,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}請修 STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}未有可用的車輛 STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}在{DATE_SHORT}後開始新遊戲,或使用提供早期車輛的NewGRF + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}無法讓列車通過險阻號誌... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}無法倒轉列車方向... diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index d4a3f1ce92..7945464b7c 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -5279,6 +5279,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Yeni New STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Henüz hiçbir araç kullanılabilir değil STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}{DATE_SHORT} sonra yeni bir oyun başlat veya erken araç sağlayan NewGRF kullan + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Tehlikedeki tren sinyali geçemez... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Tren çevrilemez... diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt index 7eadb93497..496e385fbc 100644 --- a/src/lang/ukrainian.txt +++ b/src/lang/ukrainian.txt @@ -5424,6 +5424,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Змін STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Жоден вид транспорту ще не став доступним STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Починайте нову гру після {DATE_SHORT} або використовуйте NewGRF, в якому транспорт з’являється раніше + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Неможливо проїхати сигнал - небезпечно... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Неможливо розвернути поїзд... diff --git a/src/lang/urdu.txt b/src/lang/urdu.txt index 06c6d24238..521bbd13c4 100644 --- a/src/lang/urdu.txt +++ b/src/lang/urdu.txt @@ -2880,6 +2880,7 @@ STR_ERROR_CAN_T_CHANGE_SERVICING :{WHITE}مرمت + # Specific vehicle errors diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index 62dd744acd..1c6cfb73e6 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -5280,6 +5280,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Thay đ STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Chưa có phương tiện nào có sẵn STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Bắt đầu một màn chơi mới sau {DATE_SHORT} hoặc sử dụng một NewGRF cung cấp sớm phương tiện + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Không thể để tàu hoả qua tín hiệu đèn khi nguy hiểm... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Không thể đổi hướng đoàn tàu... diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index 87979e7e4e..40e7dcc914 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -5280,6 +5280,7 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Newid ei STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Dim cerbydau ar gael eto STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Dechreuwch gêm newydd wedi {DATE_SHORT} neu defnyddiwch NewGRF sy'n darparu cerbydau cynnar + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Does dim modd gwneud i drên basio signal pan fo perygl... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Methu gwrthdroi'r trên... From b477a8458ceaf7f75b2c4c2665f96daeed75457f Mon Sep 17 00:00:00 2001 From: Paco Esteban Date: Wed, 17 Apr 2024 18:08:03 +0200 Subject: [PATCH 03/26] Codechange: Use arc4random_buf on random_func.cpp for OpenBSD --- src/core/random_func.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/random_func.cpp b/src/core/random_func.cpp index 971879dd38..355eeff616 100644 --- a/src/core/random_func.cpp +++ b/src/core/random_func.cpp @@ -97,7 +97,7 @@ void RandomBytesWithFallback(std::span buf) #if defined(_WIN32) auto res = BCryptGenRandom(nullptr, static_cast(buf.data()), static_cast(buf.size()), BCRYPT_USE_SYSTEM_PREFERRED_RNG); if (res >= 0) return; -#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) +#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) arc4random_buf(buf.data(), buf.size()); return; #elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))) From ef8eb66a2bb238c683dd358fca76d40250e13fb3 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 17 Apr 2024 18:54:50 +0100 Subject: [PATCH 04/26] Fix c38df2d58: Use VehicleID instead of pointer in map of vehicles to replace. (#12512) This affects the sort order, VehicleID is deterministic, Vehicle * is not. --- src/vehicle.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vehicle.cpp b/src/vehicle.cpp index c8fefff234..748ad84b7d 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -691,7 +691,7 @@ void ResetVehicleColourMap() * List of vehicles that should check for autoreplace this tick. * Mapping of vehicle -> leave depot immediately after autoreplace. */ -using AutoreplaceMap = std::map; +using AutoreplaceMap = std::map; static AutoreplaceMap _vehicles_to_autoreplace; void InitializeVehicles() @@ -921,7 +921,7 @@ Vehicle::~Vehicle() void VehicleEnteredDepotThisTick(Vehicle *v) { /* Vehicle should stop in the depot if it was in 'stopping' state */ - _vehicles_to_autoreplace[v] = !(v->vehstatus & VS_STOPPED); + _vehicles_to_autoreplace[v->index] = !(v->vehstatus & VS_STOPPED); /* We ALWAYS set the stopped state. Even when the vehicle does not plan on * stopping in the depot, so we stop it to ensure that it will not reserve @@ -1069,7 +1069,7 @@ void CallVehicleTicks() Backup cur_company(_current_company); for (auto &it : _vehicles_to_autoreplace) { - Vehicle *v = it.first; + Vehicle *v = Vehicle::Get(it.first); /* Autoreplace needs the current company set as the vehicle owner */ cur_company.Change(v->owner); @@ -1625,7 +1625,7 @@ void VehicleEnterDepot(Vehicle *v) cur_company.Restore(); if (cost.Failed()) { - _vehicles_to_autoreplace[v] = false; + _vehicles_to_autoreplace[v->index] = false; if (v->owner == _local_company) { /* Notify the user that we stopped the vehicle */ SetDParam(0, v->index); @@ -1647,7 +1647,7 @@ void VehicleEnterDepot(Vehicle *v) } if (v->current_order.GetDepotActionType() & ODATFB_HALT) { /* Vehicles are always stopped on entering depots. Do not restart this one. */ - _vehicles_to_autoreplace[v] = false; + _vehicles_to_autoreplace[v->index] = false; /* Invalidate last_loading_station. As the link from the station * before the stop to the station after the stop can't be predicted * we shouldn't construct it when the vehicle visits the next stop. */ From 0b9029b69c45553a9c8858b38cbd5764e8b0ea60 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 17 Apr 2024 02:14:25 +0100 Subject: [PATCH 05/26] Fix: Station/industry nearby list checks in CheckCaches --- src/openttd.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/openttd.cpp b/src/openttd.cpp index 898ea24832..4314f5a97d 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1362,7 +1362,10 @@ static void CheckCaches() for (Town *t : Town::Iterate()) old_town_stations_near.push_back(t->stations_near); std::vector old_industry_stations_near; - for (Industry *ind : Industry::Iterate()) old_industry_stations_near.push_back(ind->stations_near); + for (Industry *ind : Industry::Iterate()) old_industry_stations_near.push_back(ind->stations_near); + + std::vector old_station_industries_near; + for (Station *st : Station::Iterate()) old_station_industries_near.push_back(st->industries_near); for (Station *st : Station::Iterate()) { for (GoodsEntry &ge : st->goods) { @@ -1388,13 +1391,17 @@ static void CheckCaches() Debug(desync, 2, "docking tile mismatch: tile {}", tile); } } + } + + Station::RecomputeCatchmentForAll(); - /* Check industries_near */ - IndustryList industries_near = st->industries_near; - st->RecomputeCatchment(); - if (st->industries_near != industries_near) { + /* Check industries_near */ + i = 0; + for (Station *st : Station::Iterate()) { + if (st->industries_near != old_station_industries_near[i]) { Debug(desync, 2, "station industries near mismatch: station {}", st->index); } + i++; } /* Check stations_near */ From 824687d1f0e090474922e0c21bae26b88409f8e9 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Wed, 17 Apr 2024 14:42:49 -0400 Subject: [PATCH 06/26] Codefix: Don't mix signed and unsigned ints in unbunching calculations (#12514) --- src/vehicle.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 748ad84b7d..e441d3366d 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -2512,7 +2512,7 @@ void Vehicle::LeaveUnbunchingDepot() SetWindowDirty(WC_VEHICLE_TIMETABLE, this->index); /* Find the average travel time of vehicles that we share orders with. */ - uint num_vehicles = 0; + int num_vehicles = 0; TimerGameTick::Ticks total_travel_time = 0; Vehicle *u = this->FirstShared(); @@ -2525,10 +2525,10 @@ void Vehicle::LeaveUnbunchingDepot() } /* Make sure we cannot divide by 0. */ - num_vehicles = std::max(num_vehicles, 1u); + num_vehicles = std::max(num_vehicles, 1); /* Calculate the separation by finding the average travel time, then calculating equal separation (minimum 1 tick) between vehicles. */ - TimerGameTick::Ticks separation = std::max((total_travel_time / num_vehicles / num_vehicles), 1u); + TimerGameTick::Ticks separation = std::max((total_travel_time / num_vehicles / num_vehicles), 1); TimerGameTick::TickCounter next_departure = TimerGameTick::counter + separation; /* Set the departure time of all vehicles that we share orders with. */ From 5878d09ef268c3a3b82c02703e312d665541dcfb Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Wed, 17 Apr 2024 15:03:53 -0400 Subject: [PATCH 07/26] Fix: Smooth outliers in unbunching round trip calculations (#12513) --- src/vehicle.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vehicle.cpp b/src/vehicle.cpp index e441d3366d..12941e7e83 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1666,7 +1666,14 @@ void VehicleEnterDepot(Vehicle *v) /* If we've entered our unbunching depot, record the round trip duration. */ if (v->current_order.GetDepotActionType() & ODATFB_UNBUNCH && v->depot_unbunching_last_departure > 0) { - v->round_trip_time = (TimerGameTick::counter - v->depot_unbunching_last_departure); + TimerGameTick::Ticks measured_round_trip = TimerGameTick::counter - v->depot_unbunching_last_departure; + if (v->round_trip_time == 0) { + /* This might be our first round trip. */ + v->round_trip_time = measured_round_trip; + } else { + /* If we have a previous trip, smooth the effects of outlier trip calculations caused by jams or other interference. */ + v->round_trip_time = Clamp(measured_round_trip, (v->round_trip_time / 2), ClampTo(v->round_trip_time * 2)); + } } v->current_order.MakeDummy(); From a02da5476ee7d9abf8708de0649a2dc6c662a56a Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Wed, 17 Apr 2024 15:04:16 -0400 Subject: [PATCH 08/26] Fix: Don't show train waiting for unbunching as waiting for free path (#12515) --- src/vehicle_gui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 58ee59459e..6ec093a182 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -3118,12 +3118,12 @@ public: } else { // no train str = STR_VEHICLE_STATUS_STOPPED; } + } else if (v->IsInDepot() && v->IsWaitingForUnbunching()) { + str = STR_VEHICLE_STATUS_WAITING_UNBUNCHING; } else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING)) { str = STR_VEHICLE_STATUS_TRAIN_STUCK; } else if (v->type == VEH_AIRCRAFT && HasBit(Aircraft::From(v)->flags, VAF_DEST_TOO_FAR) && !v->current_order.IsType(OT_LOADING)) { str = STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR; - } else if (v->IsInDepot() && v->IsWaitingForUnbunching()) { - str = STR_VEHICLE_STATUS_WAITING_UNBUNCHING; } else { // vehicle is in a "normal" state, show current order if (mouse_over_start_stop) { if (v->vehstatus & VS_STOPPED) { From 1005c86c62f9bedc20102887bfc57131b26a6ed0 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 17 Apr 2024 21:49:55 +0200 Subject: [PATCH 09/26] Codechange: record cache warnings with a "warning" prefix (#12518) --- src/network/network.cpp | 3 ++- src/newgrf_storage.cpp | 2 +- src/openttd.cpp | 24 ++++++++++++------------ src/pathfinder/yapf/yapf_rail.cpp | 8 ++++---- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 2b0a79ba16..f97a6c47b0 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1210,7 +1210,8 @@ void NetworkGameLoop() assert(ret == 4); check_sync_state = true; } else if (strncmp(p, "msg: ", 5) == 0 || strncmp(p, "client: ", 8) == 0 || - strncmp(p, "load: ", 6) == 0 || strncmp(p, "save: ", 6) == 0) { + strncmp(p, "load: ", 6) == 0 || strncmp(p, "save: ", 6) == 0 || + strncmp(p, "warning: ", 9) == 0) { /* A message that is not very important to the log playback, but part of the log. */ #ifndef DEBUG_FAILED_DUMP_COMMANDS } else if (strncmp(p, "cmdf: ", 6) == 0) { diff --git a/src/newgrf_storage.cpp b/src/newgrf_storage.cpp index b071c3c743..ff309a66df 100644 --- a/src/newgrf_storage.cpp +++ b/src/newgrf_storage.cpp @@ -91,7 +91,7 @@ void AddChangedPersistentStorage(BasePersistentStorageArray *storage) /* Discard all temporary changes */ for (auto &it : *_changed_storage_arrays) { - Debug(desync, 1, "Discarding persistent storage changes: Feature {}, GrfID {:08X}, Tile {}", it->feature, BSWAP32(it->grfid), it->tile); + Debug(desync, 2, "warning: discarding persistent storage changes: Feature {}, GrfID {:08X}, Tile {}", it->feature, BSWAP32(it->grfid), it->tile); it->ClearChanges(); } _changed_storage_arrays->clear(); diff --git a/src/openttd.cpp b/src/openttd.cpp index 4314f5a97d..fc6e60c4b1 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1248,7 +1248,7 @@ static void CheckCaches() uint i = 0; for (Town *t : Town::Iterate()) { if (MemCmpT(old_town_caches.data() + i, &t->cache) != 0) { - Debug(desync, 2, "town cache mismatch: town {}", t->index); + Debug(desync, 2, "warning: town cache mismatch: town {}", t->index); } i++; } @@ -1262,7 +1262,7 @@ static void CheckCaches() i = 0; for (const Company *c : Company::Iterate()) { if (MemCmpT(old_infrastructure.data() + i, &c->infrastructure) != 0) { - Debug(desync, 2, "infrastructure cache mismatch: company {}", c->index); + Debug(desync, 2, "warning: infrastructure cache mismatch: company {}", c->index); } i++; } @@ -1318,23 +1318,23 @@ static void CheckCaches() for (const Vehicle *u = v; u != nullptr; u = u->Next()) { FillNewGRFVehicleCache(u); if (memcmp(&grf_cache[length], &u->grf_cache, sizeof(NewGRFCache)) != 0) { - Debug(desync, 2, "newgrf cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length); + Debug(desync, 2, "warning: newgrf cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length); } if (memcmp(&veh_cache[length], &u->vcache, sizeof(VehicleCache)) != 0) { - Debug(desync, 2, "vehicle cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length); + Debug(desync, 2, "warning: vehicle cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length); } switch (u->type) { case VEH_TRAIN: if (memcmp(&gro_cache[length], &Train::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) { - Debug(desync, 2, "train ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length); + Debug(desync, 2, "warning: train ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length); } if (memcmp(&tra_cache[length], &Train::From(u)->tcache, sizeof(TrainCache)) != 0) { - Debug(desync, 2, "train cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length); + Debug(desync, 2, "warning: train cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length); } break; case VEH_ROAD: if (memcmp(&gro_cache[length], &RoadVehicle::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) { - Debug(desync, 2, "road vehicle ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length); + Debug(desync, 2, "warning: road vehicle ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length); } break; default: @@ -1384,11 +1384,11 @@ static void CheckCaches() } UpdateStationDockingTiles(st); if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) { - Debug(desync, 2, "station docking mismatch: station {}, company {}", st->index, st->owner); + Debug(desync, 2, "warning: station docking mismatch: station {}, company {}", st->index, st->owner); } for (TileIndex tile : ta) { if (docking_tiles[tile] != IsDockingTile(tile)) { - Debug(desync, 2, "docking tile mismatch: tile {}", tile); + Debug(desync, 2, "warning: docking tile mismatch: tile {}", tile); } } } @@ -1399,7 +1399,7 @@ static void CheckCaches() i = 0; for (Station *st : Station::Iterate()) { if (st->industries_near != old_station_industries_near[i]) { - Debug(desync, 2, "station industries near mismatch: station {}", st->index); + Debug(desync, 2, "warning: station industries near mismatch: station {}", st->index); } i++; } @@ -1408,14 +1408,14 @@ static void CheckCaches() i = 0; for (Town *t : Town::Iterate()) { if (t->stations_near != old_town_stations_near[i]) { - Debug(desync, 2, "town stations near mismatch: town {}", t->index); + Debug(desync, 2, "warning: town stations near mismatch: town {}", t->index); } i++; } i = 0; for (Industry *ind : Industry::Iterate()) { if (ind->stations_near != old_industry_stations_near[i]) { - Debug(desync, 2, "industry stations near mismatch: industry {}", ind->index); + Debug(desync, 2, "warning: industry stations near mismatch: industry {}", ind->index); } i++; } diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index e024cee323..9580086799 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -241,7 +241,7 @@ public: pf2.DisableCache(true); FindDepotData result2 = pf2.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_penalty, reverse_penalty); if (result1.tile != result2.tile || (result1.reverse != result2.reverse)) { - Debug(desync, 2, "CACHE ERROR: FindNearestDepotTwoWay() = [{}, {}]", + Debug(desync, 2, "warning: FindNearestDepotTwoWay cache mismatch: {} vs {}", result1.tile != INVALID_TILE ? "T" : "F", result2.tile != INVALID_TILE ? "T" : "F"); DumpState(pf1, pf2); @@ -325,7 +325,7 @@ public: pf2.DisableCache(true); result1 = pf2.FindNearestSafeTile(v, t1, td, override_railtype, false); if (result1 != result2) { - Debug(desync, 2, "CACHE ERROR: FindSafeTile() = [{}, {}]", result2 ? "T" : "F", result1 ? "T" : "F"); + Debug(desync, 2, "warning: FindSafeTile cache mismatch: {} vs {}", result2 ? "T" : "F", result1 ? "T" : "F"); DumpState(pf1, pf2); } } @@ -409,7 +409,7 @@ public: pf2.DisableCache(true); Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest); if (result1 != result2) { - Debug(desync, 2, "CACHE ERROR: ChooseRailTrack() = [{}, {}]", result1, result2); + Debug(desync, 2, "warning: ChooseRailTrack cache mismatch: {} vs {}", result1, result2); DumpState(pf1, pf2); } } @@ -476,7 +476,7 @@ public: pf2.DisableCache(true); bool result2 = pf2.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty); if (result1 != result2) { - Debug(desync, 2, "CACHE ERROR: CheckReverseTrain() = [{}, {}]", result1 ? "T" : "F", result2 ? "T" : "F"); + Debug(desync, 2, "warning: CheckReverseTrain cache mismatch: {} vs {}", result1 ? "T" : "F", result2 ? "T" : "F"); DumpState(pf1, pf2); } } From a09749f6a69fbf83a8b38f778058b43af4c7f41f Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 17 Apr 2024 21:51:36 +0200 Subject: [PATCH 10/26] Codefix: don't send desync=0 log messages to commands.log (#12517) They are only used during replay, and you want to see those in the console; not in the log. --- src/debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug.cpp b/src/debug.cpp index 02150379f7..d12265a099 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -110,7 +110,7 @@ void DumpDebugFacilityNames(std::back_insert_iterator &output_itera */ void DebugPrint(const char *category, int level, const std::string &message) { - if (strcmp(category, "desync") == 0) { + if (strcmp(category, "desync") == 0 && level != 0) { static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR); if (f == nullptr) return; From a0636d82006b22cc8d89cc127c78280216c485d2 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 17 Apr 2024 22:01:58 +0200 Subject: [PATCH 11/26] Codechange: use infinite-fast-forward when rerunning command-log (#12519) --- src/network/network.cpp | 10 ++++++++-- src/network/network_internal.h | 13 ------------- src/video/dedicated_v.cpp | 1 - src/video/video_driver.hpp | 7 +++++++ 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index f97a6c47b0..15f77a84d2 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -37,6 +37,9 @@ #include "../gfx_func.h" #include "../error.h" #include "../misc_cmd.h" +#ifdef DEBUG_DUMP_COMMANDS +# include "../fileio_func.h" +#endif #include #include #include @@ -44,8 +47,11 @@ #include "../safeguards.h" #ifdef DEBUG_DUMP_COMMANDS -#include "../fileio_func.h" -/** When running the server till the wait point, run as fast as we can! */ +/** Helper variable to make the dedicated server go fast until the (first) join. + * Used to load the desync debug logs, i.e. for reproducing a desync. + * There's basically no need to ever enable this, unless you really know what + * you are doing, i.e. debugging a desync. + * See docs/desync.txt for details. */ bool _ddc_fastforward = true; #endif /* DEBUG_DUMP_COMMANDS */ diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 66dea11be4..35adc68983 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -37,19 +37,6 @@ #define NETWORK_SEND_DOUBLE_SEED #endif /* RANDOM_DEBUG */ -/** - * Helper variable to make the dedicated server go fast until the (first) join. - * Used to load the desync debug logs, i.e. for reproducing a desync. - * There's basically no need to ever enable this, unless you really know what - * you are doing, i.e. debugging a desync. - * See docs/desync.txt for details. - */ -#ifdef DEBUG_DUMP_COMMANDS -extern bool _ddc_fastforward; -#else -#define _ddc_fastforward (false) -#endif /* DEBUG_DUMP_COMMANDS */ - typedef class ServerNetworkGameSocketHandler NetworkClientSocket; /** Status of the clients during joining. */ diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index c0c0fa2278..c620f44110 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -219,7 +219,6 @@ void VideoDriver_Dedicated::MainLoop() if (!_dedicated_forks) DedicatedHandleKeyInput(); this->DrainCommandQueue(); - ChangeGameSpeed(_ddc_fastforward); this->Tick(); this->SleepTillNextTick(); } diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index 874198d465..72731f0113 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -16,6 +16,7 @@ #include "../gfx_func.h" #include "../settings_type.h" #include "../zoom_type.h" +#include "../network/network_func.h" #include #include #include @@ -311,6 +312,12 @@ protected: std::chrono::steady_clock::duration GetGameInterval() { +#ifdef DEBUG_DUMP_COMMANDS + /* When replaying, run as fast as we can. */ + extern bool _ddc_fastforward; + if (_ddc_fastforward) return std::chrono::microseconds(0); +#endif /* DEBUG_DUMP_COMMANDS */ + /* If we are paused, run on normal speed. */ if (_pause_mode) return std::chrono::milliseconds(MILLISECONDS_PER_TICK); /* Infinite speed, as quickly as you can. */ From 07b162ffc417962a826b81000c50504f580e9e12 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 17 Apr 2024 22:05:45 +0200 Subject: [PATCH 12/26] Codechange: skip all commands of the past during desync replay (#12520) --- src/network/network.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/network/network.cpp b/src/network/network.cpp index 15f77a84d2..3cd1529bdb 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1157,6 +1157,16 @@ void NetworkGameLoop() } } + /* Skip all entries in the command-log till we caught up with the current game again. */ + if (TimerGameEconomy::date > next_date || (TimerGameEconomy::date == next_date && TimerGameEconomy::date_fract > next_date_fract)) { + Debug(desync, 0, "Skipping to next command at {:08x}:{:02x}", next_date, next_date_fract); + if (cp != nullptr) { + delete cp; + cp = nullptr; + } + check_sync_state = false; + } + if (cp != nullptr || check_sync_state) break; char buff[4096]; From f7bd08001546a078ec6df014ccb77610bf8bc7eb Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Wed, 17 Apr 2024 22:36:08 +0200 Subject: [PATCH 13/26] Codechange: improve desync documentation (#12521) --- docs/desync.md | 31 +++++++++++++++---------------- src/network/network.cpp | 2 +- src/network/network_func.h | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/desync.md b/docs/desync.md index 20003c9810..afbebb11c5 100644 --- a/docs/desync.md +++ b/docs/desync.md @@ -195,10 +195,11 @@ Last updated: 2014-02-23 'src/network/network_func.h'. (DEBUG_FAILED_DUMP_COMMANDS is explained later) - Put the 'commands-out.log' into the root save folder, and rename - it to 'commands.log'. - - Run 'openttd -D -d desync=3 -g startsavegame.sav'. - This replays the server log and creates new 'commands-out.log' - and 'dmp_cmds_*.sav' in your autosave folder. + it to 'commands.log'. Strip everything and including the "newgame" + entry from the log. + - Run 'openttd -D -d desync=0 -g startsavegame.sav'. + This replays the server log. Use "-d desync=3" to also create a + new 'commands-out.log' and 'dmp_cmds_*.sav' in your autosave folder. ## 3.2) Evaluation of the replay @@ -226,7 +227,7 @@ Last updated: 2014-02-23 savegames with your own ones from the replay. You can also comment/disable the 'NOT_REACHED' mentioned above, to get another 'dmp_cmds_*.sav' from the replay after the mismatch has already been detected. - See Section 3.2 on how to compare savegames. + See Section 3.3 on how to compare savegames. If the saves differ you have located the Desync between the last dmp_cmds that match and the first one that does not. The difference of the saves may point you in the direction of what causes it. @@ -252,16 +253,14 @@ Last updated: 2014-02-23 are replayed. Their internal state will thus not change in the replay and will differ. - To compare savegame more semantically, there exist some ugly hackish - tools at: - http://devs.openttd.org/~frosch/texts/zpipe.c - http://devs.openttd.org/~frosch/texts/printhunk.c + To compare savegame more semantically, easiest is to first export them + to a JSON format with for example: - The first one decompresses OpenTTD savegames. The second one creates - a textual representation of an uncompressed savegame, by parsing hunks - and arrays and such. With both tools you need to be a bit careful - since they work on stdin and stdout, which may not deal well with - binary data. + https://github.com/TrueBrain/OpenTTD-savegame-reader - If you have the textual representation of the savegames, you can - compare them with regular diff tools. + By running: + + python -m savegame_reader --export-json dmp_cmds_NNN.sav | jq . > NNN.json + + Now you can use any (JSON) diff tool to compare the two savegames in a + somewhat human readable way. diff --git a/src/network/network.cpp b/src/network/network.cpp index 3cd1529bdb..5eb64da827 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -51,7 +51,7 @@ * Used to load the desync debug logs, i.e. for reproducing a desync. * There's basically no need to ever enable this, unless you really know what * you are doing, i.e. debugging a desync. - * See docs/desync.txt for details. */ + * See docs/desync.md for details. */ bool _ddc_fastforward = true; #endif /* DEBUG_DUMP_COMMANDS */ diff --git a/src/network/network_func.h b/src/network/network_func.h index 66b4660169..4a31943e63 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -12,7 +12,7 @@ /** * Uncomment the following define to enable command replaying. - * See docs/desync.txt for details. + * See docs/desync.md for details. */ // #define DEBUG_DUMP_COMMANDS // #define DEBUG_FAILED_DUMP_COMMANDS From 83d99ec11d30cf4784eedeeeb088b4fb35b76555 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 17 Apr 2024 21:38:11 +0100 Subject: [PATCH 14/26] Fix #12506: Update station/industry nearby lists in BuildOilRig (#12511) --- src/station_cmd.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index c1c81f893e..62ef3128b3 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -4336,6 +4336,19 @@ void BuildOilRig(TileIndex tile) st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE); st->UpdateVirtCoord(); + + /* An industry tile has now been replaced with a station tile, this may change the overlap between station catchments and industry tiles. + * Recalculate the station catchment for all stations currently in the industry's nearby list. + * Clear the industry's station nearby list first because Station::RecomputeCatchment cannot remove nearby industries in this case. */ + if (_settings_game.station.serve_neutral_industries) { + StationList nearby = std::move(st->industry->stations_near); + st->industry->stations_near.clear(); + for (Station *near : nearby) { + near->RecomputeCatchment(true); + UpdateStationAcceptance(near, true); + } + } + st->RecomputeCatchment(); UpdateStationAcceptance(st, false); } From 6458980413da684afb77f6b5157b323e657a54bf Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 17 Apr 2024 21:55:19 +0100 Subject: [PATCH 15/26] Change: Draw group hierarchy tree lines. (#12522) --- src/group_gui.cpp | 37 ++++++++++++++++++++++++++++++++----- src/group_gui.h | 5 +++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 40924c18d8..2fe19d2c50 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -118,7 +118,7 @@ static constexpr NWidgetPart _nested_group_widgets[] = { * @param parent Current tree parent (set by self with recursion). * @param indent Current tree indentation level (set by self with recursion). */ -static void GuiGroupListAddChildren(GUIGroupList &dst, const GUIGroupList &src, bool fold, GroupID parent, int indent) +static void GuiGroupListAddChildren(GUIGroupList &dst, const GUIGroupList &src, bool fold, GroupID parent = INVALID_GROUP, uint8_t indent = 0) { for (const auto &item : src) { if (item.group->parent != parent) continue; @@ -134,6 +134,16 @@ static void GuiGroupListAddChildren(GUIGroupList &dst, const GUIGroupList &src, GuiGroupListAddChildren(dst, src, fold, item.group->index, indent + 1); } } + + if (indent > 0 || dst.empty()) return; + + /* Hierarchy is complete, traverse in reverse to find where indentation levels continue. */ + uint16_t level_mask = 0; + for (auto it = std::rbegin(dst); std::next(it) != std::rend(dst); ++it) { + auto next_it = std::next(it); + SB(level_mask, it->indent, 1, it->indent <= next_it->indent); + next_it->level_mask = level_mask; + } } /** @@ -274,7 +284,7 @@ private: * @param protection Whether autoreplace protection is set. * @param has_children Whether the group has children and should have a fold / unfold button. */ - void DrawGroupInfo(int y, int left, int right, GroupID g_id, int indent = 0, bool protection = false, bool has_children = false) const + void DrawGroupInfo(int y, int left, int right, GroupID g_id, uint16_t level_mask = 0, uint8_t indent = 0, bool protection = false, bool has_children = false) const { /* Highlight the group if a vehicle is dragged over it */ if (g_id == this->group_over) { @@ -288,10 +298,27 @@ private: const GroupStatistics &stats = GroupStatistics::Get(this->vli.company, g_id, this->vli.vtype); bool rtl = _current_text_dir == TD_RTL; + const int offset = (rtl ? -(int)this->column_size[VGC_FOLD].width : (int)this->column_size[VGC_FOLD].width) / 2; + const int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent; + const int linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL); + + if (indent > 0) { + /* Draw tree continuation lines. */ + int tx = (rtl ? right - WidgetDimensions::scaled.framerect.right : left + WidgetDimensions::scaled.framerect.left) + offset; + for (uint lvl = 1; lvl <= indent; ++lvl) { + if (HasBit(level_mask, lvl)) GfxDrawLine(tx, y, tx, y + this->tiny_step_height - 1, linecolour, WidgetDimensions::scaled.fullbevel.top); + if (lvl < indent) tx += level_width; + } + /* Draw our node in the tree. */ + int ycentre = y + this->tiny_step_height / 2 - 1; + if (!HasBit(level_mask, indent)) GfxDrawLine(tx, y, tx, ycentre, linecolour, WidgetDimensions::scaled.fullbevel.top); + GfxDrawLine(tx, ycentre, tx + offset - (rtl ? -1 : 1), ycentre, linecolour, WidgetDimensions::scaled.fullbevel.top); + } + /* draw fold / unfold button */ int x = rtl ? right - WidgetDimensions::scaled.framerect.right - this->column_size[VGC_FOLD].width + 1 : left + WidgetDimensions::scaled.framerect.left; if (has_children) { - DrawSprite(Group::Get(g_id)->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, rtl ? x - indent : x + indent, y + (this->tiny_step_height - this->column_size[VGC_FOLD].height) / 2); + DrawSprite(Group::Get(g_id)->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, x + indent * level_width, y + (this->tiny_step_height - this->column_size[VGC_FOLD].height) / 2); } /* draw group name */ @@ -305,7 +332,7 @@ private: str = STR_GROUP_NAME; } x = rtl ? x - WidgetDimensions::scaled.hsep_normal - this->column_size[VGC_NAME].width : x + WidgetDimensions::scaled.hsep_normal + this->column_size[VGC_FOLD].width; - DrawString(x + (rtl ? 0 : indent), x + this->column_size[VGC_NAME].width - 1 - (rtl ? indent : 0), y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour); + DrawString(x + (rtl ? 0 : indent * WidgetDimensions::scaled.hsep_indent), x + this->column_size[VGC_NAME].width - 1 - (rtl ? indent * WidgetDimensions::scaled.hsep_indent : 0), y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour); /* draw autoreplace protection */ x = rtl ? x - WidgetDimensions::scaled.hsep_wide - this->column_size[VGC_PROTECT].width : x + WidgetDimensions::scaled.hsep_wide + this->column_size[VGC_NAME].width; @@ -624,7 +651,7 @@ public: assert(g->owner == this->owner); - DrawGroupInfo(y1, r.left, r.right, g->index, it->indent * WidgetDimensions::scaled.hsep_indent, HasBit(g->flags, GroupFlags::GF_REPLACE_PROTECTION), g->folded || (std::next(it) != std::end(this->groups) && std::next(it)->indent > it->indent)); + DrawGroupInfo(y1, r.left, r.right, g->index, it->level_mask, it->indent, HasBit(g->flags, GroupFlags::GF_REPLACE_PROTECTION), g->folded || (std::next(it) != std::end(this->groups) && std::next(it)->indent > it->indent)); y1 += this->tiny_step_height; } diff --git a/src/group_gui.h b/src/group_gui.h index ec5f790d84..d2fb2f71a0 100644 --- a/src/group_gui.h +++ b/src/group_gui.h @@ -19,9 +19,10 @@ void DeleteGroupHighlightOfVehicle(const Vehicle *v); struct GUIGroupListItem { const Group *group; - int8_t indent; ///< Display indentation level. + uint8_t indent; ///< Display indentation level. + uint16_t level_mask; ///< Bitmask of indentation continuation. - constexpr GUIGroupListItem(const Group *group, int8_t indent) : group(group), indent(indent) {} + constexpr GUIGroupListItem(const Group *group, int8_t indent) : group(group), indent(indent), level_mask(0) {} }; using GUIGroupList = GUIList; From 5a523cf212f24677dea0630f4119c8b8e2369d80 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Apr 2024 00:04:45 +0100 Subject: [PATCH 16/26] Codechange: Simplify FioCreateDirectory. `std::filesystem` provides `create_directories()` as a cross-platform way to create a directory tree. --- src/fileio.cpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 79f16392ab..bcd8a530e0 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -348,24 +348,9 @@ FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory s */ void FioCreateDirectory(const std::string &name) { - auto p = name.find_last_of(PATHSEPCHAR); - if (p != std::string::npos) { - std::string dirname = name.substr(0, p); - DIR *dir = ttd_opendir(dirname.c_str()); - if (dir == nullptr) { - FioCreateDirectory(dirname); // Try creating the parent directory, if we couldn't open it - } else { - closedir(dir); - } - } - - /* Ignore directory creation errors; they'll surface later on, and most - * of the time they are 'directory already exists' errors anyhow. */ -#if defined(_WIN32) - CreateDirectory(OTTD2FS(name).c_str(), nullptr); -#else - mkdir(OTTD2FS(name).c_str(), 0755); -#endif + /* Ignore directory creation errors; they'll surface later on. */ + std::error_code error_code; + std::filesystem::create_directories(OTTD2FS(name), error_code); } /** From d7c547d0db4276e412e18e5610f0d45ae9a2859c Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Apr 2024 00:04:46 +0100 Subject: [PATCH 17/26] Codechange: Use directory_iterator to list directories in file list windows. This replaces use of custom ttd_opendir. Files are listed separately using ScanPath as that handles downloaded content. --- src/fileio.cpp | 2 -- src/fios.cpp | 59 ++++++++++++++++------------------------ src/os/unix/unix.cpp | 13 ++------- src/os/windows/win32.cpp | 26 +++++------------- 4 files changed, 33 insertions(+), 67 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index bcd8a530e0..285d7e471f 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -70,8 +70,6 @@ TarFileList _tar_filelist[NUM_SUBDIRS]; typedef std::map TarLinkList; static TarLinkList _tar_linklist[NUM_SUBDIRS]; ///< List of directory links -extern bool FiosIsValidFile(const std::string &path, const struct dirent *ent, struct stat *sb); - /** * Checks whether the given search path is a valid search path * @param sp the search path to check diff --git a/src/fios.cpp b/src/fios.cpp index 91f622f058..dd98cb6699 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -33,8 +33,7 @@ SortingBits _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING; /* OS-specific functions are taken from their respective files (win32/unix .c) */ extern bool FiosIsRoot(const std::string &path); -extern bool FiosIsValidFile(const std::string &path, const struct dirent *ent, struct stat *sb); -extern bool FiosIsHiddenFile(const struct dirent *ent); +extern bool FiosIsHiddenFile(const std::filesystem::path &path); extern void FiosGetDrives(FileList &file_list); /* get the name of an oldstyle savegame */ @@ -322,48 +321,38 @@ bool FiosFileScanner::AddFile(const std::string &filename, size_t, const std::st */ static void FiosGetFileList(SaveLoadOperation fop, bool show_dirs, FiosGetTypeAndNameProc *callback_proc, Subdirectory subdir, FileList &file_list) { - struct stat sb; - struct dirent *dirent; - DIR *dir; - FiosItem *fios; size_t sort_start; file_list.clear(); assert(_fios_path != nullptr); - /* A parent directory link exists if we are not in the root directory */ - if (show_dirs && !FiosIsRoot(*_fios_path)) { - fios = &file_list.emplace_back(); - fios->type = FIOS_TYPE_PARENT; - fios->mtime = 0; - fios->name = ".."; - SetDParamStr(0, ".."); - fios->title = GetString(STR_SAVELOAD_PARENT_DIRECTORY); - } + if (show_dirs) { + /* A parent directory link exists if we are not in the root directory */ + if (!FiosIsRoot(*_fios_path)) { + FiosItem &fios = file_list.emplace_back(); + fios.type = FIOS_TYPE_PARENT; + fios.mtime = 0; + fios.name = ".."; + SetDParamStr(0, ".."); + fios.title = GetString(STR_SAVELOAD_PARENT_DIRECTORY); + } - /* Show subdirectories */ - if (show_dirs && (dir = ttd_opendir(_fios_path->c_str())) != nullptr) { - while ((dirent = readdir(dir)) != nullptr) { - std::string d_name = FS2OTTD(dirent->d_name); - - /* found file must be directory, but not '.' or '..' */ - if (FiosIsValidFile(*_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) && - (!FiosIsHiddenFile(dirent) || StrStartsWithIgnoreCase(PERSONAL_DIR, d_name)) && - d_name != "." && d_name != "..") { - fios = &file_list.emplace_back(); - fios->type = FIOS_TYPE_DIR; - fios->mtime = 0; - fios->name = d_name; - SetDParamStr(0, fios->name + PATHSEP); - fios->title = GetString(STR_SAVELOAD_DIRECTORY); - } + /* Show subdirectories */ + std::error_code error_code; + for (const auto &dir_entry : std::filesystem::directory_iterator(OTTD2FS(*_fios_path), error_code)) { + if (!dir_entry.is_directory()) continue; + if (FiosIsHiddenFile(dir_entry) && dir_entry.path().filename() != PERSONAL_DIR) continue; + + FiosItem &fios = file_list.emplace_back(); + fios.type = FIOS_TYPE_DIR; + fios.mtime = 0; + fios.name = FS2OTTD(dir_entry.path().filename()); + SetDParamStr(0, fios.name + PATHSEP); + fios.title = GetString(STR_SAVELOAD_DIRECTORY); } - closedir(dir); - } - /* Sort the subdirs always by name, ascending, remember user-sorting order */ - if (show_dirs) { + /* Sort the subdirs always by name, ascending, remember user-sorting order */ SortingBits order = _savegame_sort_order; _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING; std::sort(file_list.begin(), file_list.end()); diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 2583be3347..b406cbc007 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -78,18 +78,9 @@ std::optional FiosGetDiskFreeSpace(const std::string &path) return std::nullopt; } -bool FiosIsValidFile(const std::string &path, const struct dirent *ent, struct stat *sb) +bool FiosIsHiddenFile(const std::filesystem::path &path) { - assert(path.back() == PATHSEPCHAR); - if (path.size() > 2) assert(path[path.size() - 2] != PATHSEPCHAR); - std::string filename = fmt::format("{}{}", path, ent->d_name); - - return stat(filename.c_str(), sb) == 0; -} - -bool FiosIsHiddenFile(const struct dirent *ent) -{ - return ent->d_name[0] == '.'; + return path.filename().string().starts_with("."); } #ifdef WITH_ICONV diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 18655c3d42..b956027d52 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -192,27 +192,15 @@ void FiosGetDrives(FileList &file_list) } } -bool FiosIsValidFile(const std::string &, const struct dirent *ent, struct stat *sb) +bool FiosIsHiddenFile(const std::filesystem::path &path) { - /* hectonanoseconds between Windows and POSIX epoch */ - static const int64_t posix_epoch_hns = 0x019DB1DED53E8000LL; - const WIN32_FIND_DATA *fd = &ent->dir->fd; - - sb->st_size = ((uint64_t) fd->nFileSizeHigh << 32) + fd->nFileSizeLow; - /* UTC FILETIME to seconds-since-1970 UTC - * we just have to subtract POSIX epoch and scale down to units of seconds. - * http://www.gamedev.net/community/forums/topic.asp?topic_id=294070&whichpage=1� - * XXX - not entirely correct, since filetimes on FAT aren't UTC but local, - * this won't entirely be correct, but we use the time only for comparison. */ - sb->st_mtime = (time_t)((*(const uint64_t*)&fd->ftLastWriteTime - posix_epoch_hns) / 1E7); - sb->st_mode = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG; - - return true; -} + UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // Disable 'no-disk' message box. -bool FiosIsHiddenFile(const struct dirent *ent) -{ - return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0; + DWORD attributes = GetFileAttributes(path.c_str()); + + SetErrorMode(sem); // Restore previous setting. + + return (attributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0; } std::optional FiosGetDiskFreeSpace(const std::string &path) From 42523379d983a693f8a358f79229951563057997 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Apr 2024 00:04:46 +0100 Subject: [PATCH 18/26] Codechange: Use directory_iterator in ScanPath. Replaces use of custom ttd_opendir. --- src/fileio.cpp | 58 +++++++++++++++++++---------------------------- src/fileio_func.h | 4 ++-- src/fios.cpp | 4 ++-- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 285d7e471f..803baa60f2 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -1134,12 +1134,13 @@ std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, * @param filename The filename to look in for the extension. * @return True iff the extension is nullptr, or the filename ends with it. */ -static bool MatchesExtension(const char *extension, const char *filename) +static bool MatchesExtension(std::string_view extension, const std::string &filename) { - if (extension == nullptr) return true; + if (extension.empty()) return true; + if (filename.length() < extension.length()) return false; - const char *ext = strrchr(filename, extension[0]); - return ext != nullptr && StrEqualsIgnoreCase(ext, extension); + std::string_view filename_sv = filename; // String view to avoid making another copy of the substring. + return StrCompareIgnoreCase(extension, filename_sv.substr(filename_sv.length() - extension.length())) == 0; } /** @@ -1151,36 +1152,24 @@ static bool MatchesExtension(const char *extension, const char *filename) * @param basepath_length from where in the path are we 'based' on the search path * @param recursive whether to recursively search the sub directories */ -static uint ScanPath(FileScanner *fs, const char *extension, const char *path, size_t basepath_length, bool recursive) +static uint ScanPath(FileScanner *fs, std::string_view extension, const std::filesystem::path &path, size_t basepath_length, bool recursive) { uint num = 0; - struct stat sb; - struct dirent *dirent; - DIR *dir; - if (path == nullptr || (dir = ttd_opendir(path)) == nullptr) return 0; - - while ((dirent = readdir(dir)) != nullptr) { - std::string d_name = FS2OTTD(dirent->d_name); - - if (!FiosIsValidFile(path, dirent, &sb)) continue; - - std::string filename(path); - filename += d_name; - - if (S_ISDIR(sb.st_mode)) { - /* Directory */ + std::error_code error_code; + for (const auto &dir_entry : std::filesystem::directory_iterator(path, error_code)) { + if (dir_entry.is_directory()) { if (!recursive) continue; - if (d_name == "." || d_name == "..") continue; - AppendPathSeparator(filename); - num += ScanPath(fs, extension, filename.c_str(), basepath_length, recursive); - } else if (S_ISREG(sb.st_mode)) { - /* File */ - if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, basepath_length, {})) num++; + num += ScanPath(fs, extension, dir_entry.path(), basepath_length, recursive); + } else if (dir_entry.is_regular_file()) { + std::string file = FS2OTTD(dir_entry.path()); + if (!MatchesExtension(extension, file)) continue; + if (fs->AddFile(file, basepath_length, {})) num++; } } - - closedir(dir); + if (error_code) { + Debug(misc, 9, "Unable to read directory {}: {}", path.string(), error_code.message()); + } return num; } @@ -1191,12 +1180,11 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s * @param extension the extension of files to search for. * @param tar the tar to search in. */ -static uint ScanTar(FileScanner *fs, const char *extension, const TarFileList::value_type &tar) +static uint ScanTar(FileScanner *fs, std::string_view extension, const TarFileList::value_type &tar) { uint num = 0; - const auto &filename = tar.first; - if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, 0, tar.second.tar_filename)) num++; + if (MatchesExtension(extension, tar.first) && fs->AddFile(tar.first, 0, tar.second.tar_filename)) num++; return num; } @@ -1210,7 +1198,7 @@ static uint ScanTar(FileScanner *fs, const char *extension, const TarFileList::v * @return the number of found files, i.e. the number of times that * AddFile returned true. */ -uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool recursive) +uint FileScanner::Scan(std::string_view extension, Subdirectory sd, bool tars, bool recursive) { this->subdir = sd; @@ -1221,7 +1209,7 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; std::string path = FioGetDirectory(sp, sd); - num += ScanPath(this, extension, path.c_str(), path.size(), recursive); + num += ScanPath(this, extension, OTTD2FS(path), path.size(), recursive); } if (tars && sd != NO_DIRECTORY) { @@ -1252,9 +1240,9 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r * @return the number of found files, i.e. the number of times that * AddFile returned true. */ -uint FileScanner::Scan(const char *extension, const std::string &directory, bool recursive) +uint FileScanner::Scan(const std::string_view extension, const std::string &directory, bool recursive) { std::string path(directory); AppendPathSeparator(path); - return ScanPath(this, extension, path.c_str(), path.size(), recursive); + return ScanPath(this, extension, OTTD2FS(path), path.size(), recursive); } diff --git a/src/fileio_func.h b/src/fileio_func.h index 2a13a454d4..9e85f1f8c0 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -42,8 +42,8 @@ public: /** Destruct the proper one... */ virtual ~FileScanner() = default; - uint Scan(const char *extension, Subdirectory sd, bool tars = true, bool recursive = true); - uint Scan(const char *extension, const std::string &directory, bool recursive = true); + uint Scan(std::string_view extension, Subdirectory sd, bool tars = true, bool recursive = true); + uint Scan(std::string_view extension, const std::string &directory, bool recursive = true); /** * Add a file with the given filename. diff --git a/src/fios.cpp b/src/fios.cpp index dd98cb6699..f5523c85aa 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -365,9 +365,9 @@ static void FiosGetFileList(SaveLoadOperation fop, bool show_dirs, FiosGetTypeAn /* Show files */ FiosFileScanner scanner(fop, callback_proc, file_list); if (subdir == NO_DIRECTORY) { - scanner.Scan(nullptr, *_fios_path, false); + scanner.Scan({}, *_fios_path, false); } else { - scanner.Scan(nullptr, subdir, true, true); + scanner.Scan({}, subdir, true, true); } std::sort(file_list.begin() + sort_start, file_list.end()); From 63ce81570ce2f6ed4be53ca73bd0fbf8c358088b Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Apr 2024 00:04:47 +0100 Subject: [PATCH 19/26] Remove: Custom opendir implementation for Windows no longer needed. std::filesystem::directory_iterator is now used instead. --- src/fileio_func.h | 34 ------------ src/os/windows/win32.cpp | 112 --------------------------------------- 2 files changed, 146 deletions(-) diff --git a/src/fileio_func.h b/src/fileio_func.h index 9e85f1f8c0..eaa6f76164 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -81,40 +81,6 @@ public: DECLARE_ENUM_AS_BIT_SET(TarScanner::Mode) -/* Implementation of opendir/readdir/closedir for Windows */ -#if defined(_WIN32) -struct DIR; - -struct dirent { // XXX - only d_name implemented - wchar_t *d_name; // name of found file - /* little hack which will point to parent DIR struct which will - * save us a call to GetFileAttributes if we want information - * about the file (for example in function fio_bla) */ - DIR *dir; -}; - -DIR *opendir(const wchar_t *path); -struct dirent *readdir(DIR *d); -int closedir(DIR *d); -#else -/* Use system-supplied opendir/readdir/closedir functions */ -# include -# include -#endif /* defined(_WIN32) */ - -/** - * A wrapper around opendir() which will convert the string from - * OPENTTD encoding to that of the filesystem. For all purposes this - * function behaves the same as the original opendir function - * @param path string to open directory of - * @return DIR pointer - */ -inline DIR *ttd_opendir(const char *path) -{ - return opendir(OTTD2FS(path).c_str()); -} - - /** Auto-close a file upon scope exit. */ class FileCloser { FILE *f; diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index b956027d52..c011e830f6 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -58,118 +58,6 @@ void OSOpenBrowser(const std::string &url) ShellExecute(GetActiveWindow(), L"open", OTTD2FS(url).c_str(), nullptr, nullptr, SW_SHOWNORMAL); } -/* Code below for windows version of opendir/readdir/closedir copied and - * modified from Jan Wassenberg's GPL implementation posted over at - * http://www.gamedev.net/community/forums/topic.asp?topic_id=364584&whichpage=1� */ - -struct DIR { - HANDLE hFind; - /* the dirent returned by readdir. - * note: having only one global instance is not possible because - * multiple independent opendir/readdir sequences must be supported. */ - dirent ent; - WIN32_FIND_DATA fd; - /* since opendir calls FindFirstFile, we need a means of telling the - * first call to readdir that we already have a file. - * that's the case iff this is true */ - bool at_first_entry; -}; - -/* suballocator - satisfies most requests with a reusable static instance. - * this avoids hundreds of alloc/free which would fragment the heap. - * To guarantee concurrency, we fall back to malloc if the instance is - * already in use (it's important to avoid surprises since this is such a - * low-level routine). */ -static DIR _global_dir; -static LONG _global_dir_is_in_use = false; - -static inline DIR *dir_calloc() -{ - DIR *d; - - if (InterlockedExchange(&_global_dir_is_in_use, true) == (LONG)true) { - d = CallocT(1); - } else { - d = &_global_dir; - memset(d, 0, sizeof(*d)); - } - return d; -} - -static inline void dir_free(DIR *d) -{ - if (d == &_global_dir) { - _global_dir_is_in_use = (LONG)false; - } else { - free(d); - } -} - -DIR *opendir(const wchar_t *path) -{ - DIR *d; - UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box - DWORD fa = GetFileAttributes(path); - - if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) { - d = dir_calloc(); - if (d != nullptr) { - std::wstring search_path = path; - bool slash = path[wcslen(path) - 1] == '\\'; - - /* build search path for FindFirstFile, try not to append additional slashes - * as it throws Win9x off its groove for root directories */ - if (!slash) search_path += L"\\"; - search_path += L"*"; - d->hFind = FindFirstFile(search_path.c_str(), &d->fd); - - if (d->hFind != INVALID_HANDLE_VALUE || - GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty - d->ent.dir = d; - d->at_first_entry = true; - } else { - dir_free(d); - d = nullptr; - } - } else { - errno = ENOMEM; - } - } else { - /* path not found or not a directory */ - d = nullptr; - errno = ENOENT; - } - - SetErrorMode(sem); // restore previous setting - return d; -} - -struct dirent *readdir(DIR *d) -{ - DWORD prev_err = GetLastError(); // avoid polluting last error - - if (d->at_first_entry) { - /* the directory was empty when opened */ - if (d->hFind == INVALID_HANDLE_VALUE) return nullptr; - d->at_first_entry = false; - } else if (!FindNextFile(d->hFind, &d->fd)) { // determine cause and bail - if (GetLastError() == ERROR_NO_MORE_FILES) SetLastError(prev_err); - return nullptr; - } - - /* This entry has passed all checks; return information about it. - * (note: d_name is a pointer; see struct dirent definition) */ - d->ent.d_name = d->fd.cFileName; - return &d->ent; -} - -int closedir(DIR *d) -{ - FindClose(d->hFind); - dir_free(d); - return 0; -} - bool FiosIsRoot(const std::string &file) { return file.size() == 3; // C:\... From c355e98c5899a12648e38e7fdeebbdfd2621ef52 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 18 Apr 2024 04:40:27 +0000 Subject: [PATCH 20/26] Update: Translations from eints english (au): 4 changes by krysclarke russian: 4 changes by Ln-Wolf finnish: 7 changes by hpiirai portuguese: 4 changes by azulcosta portuguese (brazilian): 5 changes by pasantoro polish: 4 changes by pAter-exe --- src/lang/brazilian_portuguese.txt | 6 +++++- src/lang/english_AU.txt | 4 ++++ src/lang/finnish.txt | 10 +++++++--- src/lang/polish.txt | 4 ++++ src/lang/portuguese.txt | 4 ++++ src/lang/russian.txt | 4 ++++ 6 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 860a5f0184..be2b27f66b 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -5282,11 +5282,15 @@ STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... veí STR_ERROR_CAN_T_CLONE_VEHICLE_LIST :{WHITE}... nem todos os veículos são idênticos -STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}Não haverá veículos disponíveis +STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}Nenhum veículo estará disponível STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Modifique a sua configuração de NewGRF STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Não existem veículos disponíveis ainda STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Inicie um novo jogo depois de {DATE_SHORT} ou utilize um NewGRF que forneça veículos iniciais +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}Nenhum tipo de estrada urbana está disponível +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Modifique a sua configuração de NewGRF +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}Não existem tipos de estrada urbana disponíveis ainda +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Inicie um novo jogo depois de {DATE_SHORT} ou utilize um NewGRF que forneça estradas urbanas iniciais # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Não é possível fazer o trem passar o sinal em perigo... diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index f432d6d71b..e3782bcd19 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -5286,6 +5286,10 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change y STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}No vehicles are available yet STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF which provides early vehicles +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}No town-buildable road types are available +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change your NewGRF configuration +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}No town-buildable road types are available yet +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF that provides early town-buildable road types # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger... diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 017948e152..14a5098396 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -1311,7 +1311,7 @@ STR_CONFIG_SETTING_RECESSIONS :Lamat: {STRING} STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Mikäli käytössä, taloudellinen lama voi ilmaantua ajoittain. Laman aikana kaikki tuotanto on huomattavasti alhaisempaa (palautuu normaalille tasolle laman päätyttyä) STR_CONFIG_SETTING_TRAIN_REVERSING :Estä junien kääntyminen asemilla: {STRING} -STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :Mikäli käytössä, junat eivät käänny läpiajettavilla asemilla vaikka kääntymisen jälkeen saatavilla olisi lyhempi reitti +STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :Mikäli käytössä, junat eivät käänny läpiajettavilla asemilla vaikka kääntymisen jälkeen tarjolla olisi lyhempi reitti STR_CONFIG_SETTING_DISASTERS :Onnettomuudet: {STRING} STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Ottaa käyttöön onnettomuudet jotka saattavat ajoittain estää tai tuhota liikennettä tai infrastruktuuria @@ -5281,11 +5281,15 @@ STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... kulk STR_ERROR_CAN_T_CLONE_VEHICLE_LIST :{WHITE}… kaikki kulkuneuvot eivät ole identtisiä -STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}Yhtään kulkuneuvoa ei ole saatavilla +STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL :{WHITE}Yhtään kulkuneuvoa ei ole käytettävissä STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Muuta NewGRF-asetuksiasi STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Kulkuneuvoja ei ole vielä saatavilla -STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Aloita peli {DATE_SHORT} jälkeen tai käytä NewGRF:ää joka tarjoaa aikaisempia kulkuneuvoja +STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Aloita uusi peli {DATE_SHORT} jälkeen tai käytä NewGRF:ää, joka tarjoaa varhaisia kulkuneuvoja +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}Yhtään kunnan rakennettavissa olevaa tietyyppiä ei ole käytettävissä +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Muuta NewGRF-asetuksia +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}Kunnan rakennettavissa olevia tietyyppejä ei ole vielä saatavilla +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Aloita uusi peli {DATE_SHORT} jälkeen tai käytä NewGRF:ää, joka tarjoaa varhaisia kunnan rakennettavissa olevia tietyyppejä # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Junaa ei voi pakottaa jatkamaan punaisen opastimen ohi... diff --git a/src/lang/polish.txt b/src/lang/polish.txt index ae307a167f..ee5ab860d3 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -5672,6 +5672,10 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Zmień k STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Obecnie żaden pojazd nie jest dostępny STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Zacznij grę po {DATE_SHORT} albo użyj zestawu NewGRF, który zawiera wczesne pojazdy +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}Brak dostępnych typów dróg miejskich +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Zmień konfigurację NewGRF +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}Brak jeszcze dostępnych typów dróg miejskich +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Rozpocznij nową grę po {DATE_SHORT} roku lub użyj NewGRF, który umożliwia wczesne budowanie dróg miejskich # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nie można przepuścić pociągu za sygnał, niebezpieczeństwo... diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 6c7e8b5904..74c418193a 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -5287,6 +5287,10 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Mudar a STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Nenhum veículo ainda disponível STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Começar um novo jogo depois de {DATE_SHORT} ou utilizar um NewGRF que forneça veículos iniciais +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}Não está disponível nenhum tipo de estrada edificável para localidades +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Mudar a sua configuração NewGRF +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}Ainda não estão disponíveis tipos de estradas edificáveis para localidades +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Começar um novo jogo depois de {DATE_SHORT} ou usar um NewGRF que forneça antecipadamente tipos de estradas edificáveis em localidades # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Não é possível fazer o comboio passar o sinal com perigo... diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 598bb83968..5fbcbcba24 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -5473,6 +5473,10 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Изме STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Нет доступных транспортных средств STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Начните игру не ранее {DATE_SHORT} либо подключите NewGRF, добавляющий транспортные средства, использовавшиеся в это время. +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}Отсутствуют типы дорог, которые могла бы прокладывать городская администрация +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Измените конфигурацию установленных модулей NewGRF +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}Пока что отсутствуют типы дорог, которые могла бы прокладывать городская администрация +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Установите дату начала игры не ранее {DATE_SHORT} или установите модуль NewGRF, добавляющий типы дорог, которые будут доступны администрациям городов на выбранную вами дату # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Невозможно игнорировать светофор. Опасно... From 715f8c0218b10700a9d41c2ad54c8b0f1776e4f3 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 18 Apr 2024 18:41:36 +0200 Subject: [PATCH 21/26] Codefix: cast to "CommandCallback *" in a way cast-function-type-mismatch doesn't mind (#12529) --- src/command_func.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/command_func.h b/src/command_func.h index ddf68aaf11..69cb9ebcac 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -250,7 +250,7 @@ public: template static Tret Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple args) { - return Execute(err_message, reinterpret_cast(callback), my_cmd, estimate_only, false, location, std::move(args)); + return Execute(err_message, reinterpret_cast(reinterpret_cast(callback)), my_cmd, estimate_only, false, location, std::move(args)); } protected: @@ -301,7 +301,7 @@ protected: /* Only set client IDs when the command does not come from the network. */ if (!network_command && GetCommandFlags() & CMD_CLIENT_ID) SetClientIds(args, std::index_sequence_for{}); - Tret res = Execute(err_message, reinterpret_cast(callback), my_cmd, estimate_only, network_command, tile, args); + Tret res = Execute(err_message, reinterpret_cast(reinterpret_cast(callback)), my_cmd, estimate_only, network_command, tile, args); InternalPostResult(ExtractCommandCost(res), tile, estimate_only, only_sending, err_message, my_cmd); if (!estimate_only && !only_sending && callback != nullptr) { From 78b83190ccf71b85b7d087aaa95aba1166dfc3c9 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Thu, 18 Apr 2024 12:45:00 -0400 Subject: [PATCH 22/26] Fix: Mark vehicle status bars dirty when a vehicle leaves unbunching depot (#12516) --- src/vehicle.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 12941e7e83..2e1b82b172 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -2545,6 +2545,7 @@ void Vehicle::LeaveUnbunchingDepot() if (u->vehstatus & (VS_STOPPED | VS_CRASHED)) continue; u->depot_unbunching_next_departure = next_departure; + SetWindowDirty(WC_VEHICLE_VIEW, u->index); } } From 4170c9923a64868098c03d7d45477d088786d83e Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Apr 2024 17:45:41 +0100 Subject: [PATCH 23/26] Fix: Inconsistent space between console history and current line. (#12528) --- src/console_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/console_gui.cpp b/src/console_gui.cpp index 6dc0393e66..496d945934 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -196,7 +196,7 @@ struct IConsoleWindow : Window const int right = this->width - WidgetDimensions::scaled.frametext.right; GfxFillRect(0, 0, this->width - 1, this->height - 1, PC_BLACK); - int ypos = this->height - this->line_height; + int ypos = this->height - this->line_height - WidgetDimensions::scaled.hsep_normal; for (size_t line_index = IConsoleWindow::scroll; line_index < _iconsole_buffer.size(); line_index++) { const IConsoleLine &print = _iconsole_buffer[line_index]; SetDParamStr(0, print.buffer); From 08d05bf4c0530f00d0b46312436781be40f3ae3e Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 18 Apr 2024 19:12:52 +0200 Subject: [PATCH 24/26] Doc: update release documentation with the latest (#12525) --- docs/releasing_openttd.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/releasing_openttd.md b/docs/releasing_openttd.md index acb3ad9bc7..08c379dd81 100644 --- a/docs/releasing_openttd.md +++ b/docs/releasing_openttd.md @@ -29,20 +29,25 @@ This guide is for OpenTTD developers/maintainers, to release a new version of Op 1. Go to https://github.com/OpenTTD/website/new/main/_posts and write a new announcement post. See a [previous example](https://github.com/OpenTTD/website/pull/238) for a template. 2. Create a new branch for this post and open a PR for it. -3. Write announcement text for socials like Forum/Discord/Twitter/Reddit and include it in the PR. +3. Write announcement text for the store pages and socials like TT-Forums / Discord / Twitter / Reddit / Fosstodon / etc., and include it in the PR. 4. Create a Steam news image for that post and include it in the PR. -5. Check the website post (preview link via checks page) and make corrections. We usually just use the GitHub web interface for this and squash the result later. +5. Check the website post ("View Deployment" link) and make corrections. We usually just use the GitHub web interface for this and squash the result later. 6. Get this PR approved, but do not merge yet. ## Step 3: Make the actual OpenTTD release -1. Go to https://github.com/OpenTTD/OpenTTD/releases/new and create a new tag matching the release number. For the body of the release, see any older release. "Set as a pre-release" for a beta or RC, set as latest for a real release. -2. Merge website PR. -3. Wait for the OpenTTD release checks to be complete. -4. Check that website links to the new release are working and correct, using the [staging website](https://www-staging.openttd.org/). -5. If this is a full release, ask orudge to update the Microsoft Store and TrueBrain to move the release from the "testing" to "default" branch on Steam. +1. Go to https://github.com/OpenTTD/OpenTTD/releases/new and create a new tag matching the release number. For the body of the release, copy in the changelog. "Set as a pre-release" for a beta or RC. +2. Wait for the OpenTTD release workflow to be complete. +3. Merge the website PR. This will publish the release post. +4. If this is a full release: + * for `Steam`: under Steamworks -> SteamPipe -> Builds, set the "testing" branch live on the "default" branch. This will request 2FA validation. + * for `GOG`: under Builds, "Publish" the freshly uploaded builds to `Master`, `GOG-use only` and `Testing`. + * for `Microsoft Store`: ask orudge to publish the new release. + +Access to `Steam`, `GOG` and/or `Microsoft Store` requires a developer account on that platform. +You will need access to the shared keystore in order to create such an account. +For help and/or access to either or both, please contact TrueBrain. ## Step 4: Tell the world -1. Tag and create a website release to trigger the actions that update the website. -2. After the website is live, make announcements on social media. You may need to coordinate with other developers who can make posts on Twitter, Reddit, Steam, and GOG. +1. Make announcements on social media and store pages. You may need to coordinate with other developers who can make posts on TT-Forums, Twitter, Reddit, Fosstodon, Discord, Steam, GOG, Microsoft Store, etc. From 04a3bf76e840cdf4b1dc79479b62b4d626c4bee1 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 18 Apr 2024 19:37:33 +0200 Subject: [PATCH 25/26] Codechange: upgrade Emscripten to 3.1.57 (#12526) This also upgrades liblzma to 5.4.6, and uses the new ports.contrib system Emscripten 3.1.56 introduced. --- .github/workflows/ci-emscripten.yml | 9 +- .github/workflows/preview-build.yml | 9 +- os/emscripten/Dockerfile | 5 +- os/emscripten/README.md | 4 +- os/emscripten/cmake/FindLibLZMA.cmake | 8 +- os/emscripten/emsdk-liblzma.patch | 198 -------------------------- os/emscripten/ports/liblzma.py | 139 ++++++++++++++++++ 7 files changed, 155 insertions(+), 217 deletions(-) delete mode 100644 os/emscripten/emsdk-liblzma.patch create mode 100644 os/emscripten/ports/liblzma.py diff --git a/.github/workflows/ci-emscripten.yml b/.github/workflows/ci-emscripten.yml index e1814ed79b..8c50713b9e 100644 --- a/.github/workflows/ci-emscripten.yml +++ b/.github/workflows/ci-emscripten.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-20.04 container: # If you change this version, change the number in the cache step too. - image: emscripten/emsdk:3.1.42 + image: emscripten/emsdk:3.1.57 steps: - name: Checkout @@ -23,12 +23,11 @@ jobs: uses: actions/cache@v4 with: path: /emsdk/upstream/emscripten/cache - key: 3.1.42-${{ runner.os }} + key: 3.1.57-${{ runner.os }} - - name: Patch Emscripten to support LZMA + - name: Add liblzma support run: | - cd /emsdk/upstream/emscripten - patch -p1 < ${GITHUB_WORKSPACE}/os/emscripten/emsdk-liblzma.patch + cp ${GITHUB_WORKSPACE}/os/emscripten/ports/liblzma.py /emsdk/upstream/emscripten/tools/ports/contrib/ - name: Build (host tools) run: | diff --git a/.github/workflows/preview-build.yml b/.github/workflows/preview-build.yml index 0bb79ed4b9..9cf6e9573c 100644 --- a/.github/workflows/preview-build.yml +++ b/.github/workflows/preview-build.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest container: # If you change this version, change the number in the cache step too. - image: emscripten/emsdk:3.1.42 + image: emscripten/emsdk:3.1.57 steps: - name: Checkout @@ -38,12 +38,11 @@ jobs: uses: actions/cache@v4 with: path: /emsdk/upstream/emscripten/cache - key: 3.1.42-${{ runner.os }} + key: 3.1.57-${{ runner.os }} - - name: Patch Emscripten to support LZMA + - name: Add liblzma support run: | - cd /emsdk/upstream/emscripten - patch -p1 < ${GITHUB_WORKSPACE}/os/emscripten/emsdk-liblzma.patch + cp ${GITHUB_WORKSPACE}/os/emscripten/ports/liblzma.py /emsdk/upstream/emscripten/tools/ports/contrib/ - name: Build (host tools) run: | diff --git a/os/emscripten/Dockerfile b/os/emscripten/Dockerfile index 178f56500b..543bf6b2de 100644 --- a/os/emscripten/Dockerfile +++ b/os/emscripten/Dockerfile @@ -1,4 +1,3 @@ -FROM emscripten/emsdk:3.1.42 +FROM emscripten/emsdk:3.1.57 -COPY emsdk-liblzma.patch / -RUN cd /emsdk/upstream/emscripten && patch -p1 < /emsdk-liblzma.patch +COPY ports/liblzma.py /emsdk/upstream/emscripten/tools/ports/contrib/liblzma.py diff --git a/os/emscripten/README.md b/os/emscripten/README.md index 9184b0144e..cdc038ade3 100644 --- a/os/emscripten/README.md +++ b/os/emscripten/README.md @@ -2,8 +2,8 @@ Please use docker with the supplied `Dockerfile` to build for emscripten. It takes care of a few things: -- Use a version of emscripten we know works -- Patch in LibLZMA support (as this is not supported by upstream) +- Use a version of emscripten we know works. +- Add LibLZMA library under contrib ports. First, build the docker image by navigating in the folder this `README.md` is in, and executing: ``` diff --git a/os/emscripten/cmake/FindLibLZMA.cmake b/os/emscripten/cmake/FindLibLZMA.cmake index cd6b44ad3d..0880d62f70 100644 --- a/os/emscripten/cmake/FindLibLZMA.cmake +++ b/os/emscripten/cmake/FindLibLZMA.cmake @@ -1,7 +1,7 @@ # LibLZMA is a custom addition to the emscripten SDK, so it is possible # someone patched their SDK. Test out if the SDK supports LibLZMA. include(CheckCXXSourceCompiles) -set(CMAKE_REQUIRED_FLAGS "-sUSE_LIBLZMA=1") +set(CMAKE_REQUIRED_FLAGS "--use-port=contrib.liblzma") check_cxx_source_compiles(" #include @@ -12,9 +12,9 @@ check_cxx_source_compiles(" if (LIBLZMA_FOUND) add_library(LibLZMA::LibLZMA INTERFACE IMPORTED) set_target_properties(LibLZMA::LibLZMA PROPERTIES - INTERFACE_COMPILE_OPTIONS "-sUSE_LIBLZMA=1" - INTERFACE_LINK_LIBRARIES "-sUSE_LIBLZMA=1" + INTERFACE_COMPILE_OPTIONS "--use-port=contrib.liblzma" + INTERFACE_LINK_LIBRARIES "--use-port=contrib.liblzma" ) else() - message(WARNING "You are using an emscripten SDK without LibLZMA support. Many savegames won't be able to load in OpenTTD. Please apply 'emsdk-liblzma.patch' to your local emsdk installation.") + message(WARNING "You are using an emscripten SDK without LibLZMA support. Many savegames won't be able to load in OpenTTD. Please copy liblzma.py to your ports/contrib folder in your local emsdk installation.") endif() diff --git a/os/emscripten/emsdk-liblzma.patch b/os/emscripten/emsdk-liblzma.patch deleted file mode 100644 index 7bfdd47de2..0000000000 --- a/os/emscripten/emsdk-liblzma.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 84d0e9112d5c87a714abd21ec8547921f46f37b5 Mon Sep 17 00:00:00 2001 -From: milek7 -Date: Tue, 8 Dec 2020 01:03:31 +0100 -Subject: [PATCH] Add liblzma port - ---- - src/settings.js | 4 ++ - tools/ports/liblzma.py | 151 +++++++++++++++++++++++++++++++++++++++++ - tools/settings.py | 1 + - 3 files changed, 156 insertions(+) - create mode 100644 tools/ports/liblzma.py - -diff --git a/src/settings.js b/src/settings.js -index f93140d..7b6bec9 100644 ---- a/src/settings.js -+++ b/src/settings.js -@@ -1451,6 +1451,10 @@ var USE_GIFLIB = false; - // [compile+link] - var USE_LIBJPEG = false; - -+// 1 = use liblzma from emscripten-ports -+// [compile+link] -+var USE_LIBLZMA = false; -+ - // 1 = use libpng from emscripten-ports - // [compile+link] - var USE_LIBPNG = false; -diff --git a/tools/ports/liblzma.py b/tools/ports/liblzma.py -new file mode 100644 -index 0000000..6872a8b ---- /dev/null -+++ b/tools/ports/liblzma.py -@@ -0,0 +1,151 @@ -+# Copyright 2020 The Emscripten Authors. All rights reserved. -+# Emscripten is available under two separate licenses, the MIT license and the -+# University of Illinois/NCSA Open Source License. Both these licenses can be -+# found in the LICENSE file. -+ -+import os -+import shutil -+import logging -+from pathlib import Path -+ -+VERSION = '5.4.2' -+HASH = '149f980338bea3d66de1ff5994b2b236ae1773135eda68b62b009df0c9dcdf5467f8cb2c06da95a71b6556d60bd3d21f475feced34d5dfdb80ee95416a2f9737' -+ -+ -+def needed(settings): -+ return settings.USE_LIBLZMA -+ -+ -+def get(ports, settings, shared): -+ ports.fetch_project('liblzma', f'https://tukaani.org/xz/xz-{VERSION}.tar.gz', sha512hash=HASH) -+ -+ def create(final): -+ logging.info('building port: liblzma') -+ -+ ports.clear_project_build('liblzma') -+ -+ source_path = os.path.join(ports.get_dir(), 'liblzma', f'xz-{VERSION}', 'src', 'liblzma') -+ ports.write_file(os.path.join(source_path, 'config.h'), config_h) -+ ports.install_headers(os.path.join(source_path, 'api'), pattern='lzma.h') -+ ports.install_headers(os.path.join(source_path, 'api', 'lzma'), pattern='*.h', target='lzma') -+ -+ build_flags = ['-DHAVE_CONFIG_H', '-DTUKLIB_SYMBOL_PREFIX=lzma_', '-fvisibility=hidden'] -+ exclude_files = ['crc32_small.c', 'crc64_small.c', 'crc32_tablegen.c', 'crc64_tablegen.c', 'price_tablegen.c', 'fastpos_tablegen.c', -+ 'tuklib_exit.c', 'tuklib_mbstr_fw.c', 'tuklib_mbstr_width.c', 'tuklib_open_stdxxx.c', 'tuklib_progname.c'] -+ include_dirs_rel = ['../common', 'api', 'check', 'common', 'delta', 'lz', 'lzma', 'rangecoder', 'simple'] -+ -+ include_dirs = [os.path.join(source_path, p) for p in include_dirs_rel] -+ ports.build_port(source_path, final, 'liblzma', flags=build_flags, exclude_files=exclude_files, includes=include_dirs) -+ -+ return [shared.cache.get_lib('liblzma.a', create, what='port')] -+ -+ -+def clear(ports, settings, shared): -+ shared.cache.erase_lib('liblzma.a') -+ -+ -+def process_args(ports): -+ return [] -+ -+ -+def show(): -+ return 'liblzma (USE_LIBLZMA=1; public domain)' -+ -+ -+config_h = ''' -+#define ASSUME_RAM 128 -+#define ENABLE_NLS 1 -+#define HAVE_CHECK_CRC32 1 -+#define HAVE_CHECK_CRC64 1 -+#define HAVE_CHECK_SHA256 1 -+#define HAVE_CLOCK_GETTIME 1 -+#define HAVE_DCGETTEXT 1 -+#define HAVE_DECL_CLOCK_MONOTONIC 1 -+#define HAVE_DECL_PROGRAM_INVOCATION_NAME 1 -+#define HAVE_DECODERS 1 -+#define HAVE_DECODER_ARM 1 -+#define HAVE_DECODER_ARMTHUMB 1 -+#define HAVE_DECODER_DELTA 1 -+#define HAVE_DECODER_IA64 1 -+#define HAVE_DECODER_LZMA1 1 -+#define HAVE_DECODER_LZMA2 1 -+#define HAVE_DECODER_POWERPC 1 -+#define HAVE_DECODER_SPARC 1 -+#define HAVE_DECODER_X86 1 -+#define HAVE_DLFCN_H 1 -+#define HAVE_ENCODERS 1 -+#define HAVE_ENCODER_ARM 1 -+#define HAVE_ENCODER_ARMTHUMB 1 -+#define HAVE_ENCODER_DELTA 1 -+#define HAVE_ENCODER_IA64 1 -+#define HAVE_ENCODER_LZMA1 1 -+#define HAVE_ENCODER_LZMA2 1 -+#define HAVE_ENCODER_POWERPC 1 -+#define HAVE_ENCODER_SPARC 1 -+#define HAVE_ENCODER_X86 1 -+#define HAVE_FCNTL_H 1 -+#define HAVE_FUTIMENS 1 -+#define HAVE_GETOPT_H 1 -+#define HAVE_GETOPT_LONG 1 -+#define HAVE_GETTEXT 1 -+#define HAVE_IMMINTRIN_H 1 -+#define HAVE_INTTYPES_H 1 -+#define HAVE_LIMITS_H 1 -+#define HAVE_MBRTOWC 1 -+#define HAVE_MEMORY_H 1 -+#define HAVE_MF_BT2 1 -+#define HAVE_MF_BT3 1 -+#define HAVE_MF_BT4 1 -+#define HAVE_MF_HC3 1 -+#define HAVE_MF_HC4 1 -+#define HAVE_OPTRESET 1 -+#define HAVE_POSIX_FADVISE 1 -+#define HAVE_PTHREAD_CONDATTR_SETCLOCK 1 -+#define HAVE_PTHREAD_PRIO_INHERIT 1 -+#define HAVE_STDBOOL_H 1 -+#define HAVE_STDINT_H 1 -+#define HAVE_STDLIB_H 1 -+#define HAVE_STRINGS_H 1 -+#define HAVE_STRING_H 1 -+#define HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC 1 -+#define HAVE_SYS_PARAM_H 1 -+#define HAVE_SYS_STAT_H 1 -+#define HAVE_SYS_TIME_H 1 -+#define HAVE_SYS_TYPES_H 1 -+#define HAVE_UINTPTR_T 1 -+#define HAVE_UNISTD_H 1 -+#define HAVE_VISIBILITY 1 -+#define HAVE_WCWIDTH 1 -+#define HAVE__BOOL 1 -+#define HAVE___BUILTIN_ASSUME_ALIGNED 1 -+#define HAVE___BUILTIN_BSWAPXX 1 -+#define MYTHREAD_POSIX 1 -+#define NDEBUG 1 -+#define PACKAGE "xz" -+#define PACKAGE_BUGREPORT "lasse.collin@tukaani.org" -+#define PACKAGE_NAME "XZ Utils" -+#define PACKAGE_STRING "XZ Utils 5.4.0" -+#define PACKAGE_TARNAME "xz" -+#define PACKAGE_VERSION "5.4.0" -+#define SIZEOF_SIZE_T 4 -+#define STDC_HEADERS 1 -+#define TUKLIB_CPUCORES_SYSCONF 1 -+#define TUKLIB_FAST_UNALIGNED_ACCESS 1 -+#define TUKLIB_PHYSMEM_SYSCONF 1 -+#ifndef _ALL_SOURCE -+# define _ALL_SOURCE 1 -+#endif -+#ifndef _GNU_SOURCE -+# define _GNU_SOURCE 1 -+#endif -+#ifndef _POSIX_PTHREAD_SEMANTICS -+# define _POSIX_PTHREAD_SEMANTICS 1 -+#endif -+#ifndef _TANDEM_SOURCE -+# define _TANDEM_SOURCE 1 -+#endif -+#ifndef __EXTENSIONS__ -+# define __EXTENSIONS__ 1 -+#endif -+#define VERSION "5.4.0" -+''' -diff --git a/tools/settings.py b/tools/settings.py -index 10d6ca0..827e4a9 100644 ---- a/tools/settings.py -+++ b/tools/settings.py -@@ -40,6 +40,7 @@ PORTS_SETTINGS = { - 'USE_SDL_NET', - 'USE_SDL_GFX', - 'USE_LIBJPEG', -+ 'USE_LIBLZMA', - 'USE_OGG', - 'USE_REGAL', - 'USE_BOOST_HEADERS', --- -2.34.1 diff --git a/os/emscripten/ports/liblzma.py b/os/emscripten/ports/liblzma.py new file mode 100644 index 0000000000..0adf0e5697 --- /dev/null +++ b/os/emscripten/ports/liblzma.py @@ -0,0 +1,139 @@ +import os +import logging + +VERSION = '5.4.6' +HASH = '495cc890d25c075c927c907b77e60d86dd8a4c377cea5b1172c8e916984149a7bb5fb32db25091f7219346b83155b47e4bc0404cc8529d992014cd7ed0c278b7' + +URL = 'https://github.com/tukaani-project/xz' +DESCRIPTION = 'liblzma provides a general-purpose data-compression library.' +LICENSE = 'LGPL-2.1' + +def get(ports, settings, shared): + ports.fetch_project('contrib.liblzma', f'https://github.com/tukaani-project/xz/releases/download/v{VERSION}/xz-{VERSION}.tar.xz', sha512hash=HASH) + + def create(final): + logging.info('building port: contrib.liblzma') + + ports.clear_project_build('contrib.liblzma') + + source_path = os.path.join(ports.get_dir(), 'contrib.liblzma', f'xz-{VERSION}', 'src', 'liblzma') + ports.write_file(os.path.join(source_path, 'config.h'), config_h) + ports.install_headers(os.path.join(source_path, 'api'), pattern='lzma.h') + ports.install_headers(os.path.join(source_path, 'api', 'lzma'), pattern='*.h', target='lzma') + + build_flags = ['-DHAVE_CONFIG_H', '-DTUKLIB_SYMBOL_PREFIX=lzma_', '-fvisibility=hidden'] + exclude_files = ['crc32_small.c', 'crc64_small.c', 'crc32_tablegen.c', 'crc64_tablegen.c', 'price_tablegen.c', 'fastpos_tablegen.c', + 'tuklib_exit.c', 'tuklib_mbstr_fw.c', 'tuklib_mbstr_width.c', 'tuklib_open_stdxxx.c', 'tuklib_progname.c'] + include_dirs_rel = ['../common', 'api', 'check', 'common', 'delta', 'lz', 'lzma', 'rangecoder', 'simple'] + + include_dirs = [os.path.join(source_path, p) for p in include_dirs_rel] + ports.build_port(source_path, final, 'contrib.liblzma', flags=build_flags, exclude_files=exclude_files, includes=include_dirs) + + return [shared.cache.get_lib('liblzma.a', create, what='port')] + + +def clear(ports, settings, shared): + shared.cache.erase_lib('liblzma.a') + + +def process_args(ports): + return [] + + +config_h = ''' +#define ASSUME_RAM 128 +#define ENABLE_NLS 1 +#define HAVE_CHECK_CRC32 1 +#define HAVE_CHECK_CRC64 1 +#define HAVE_CHECK_SHA256 1 +#define HAVE_CLOCK_GETTIME 1 +#define HAVE_DCGETTEXT 1 +#define HAVE_DECL_CLOCK_MONOTONIC 1 +#define HAVE_DECL_PROGRAM_INVOCATION_NAME 1 +#define HAVE_DECODERS 1 +#define HAVE_DECODER_ARM 1 +#define HAVE_DECODER_ARMTHUMB 1 +#define HAVE_DECODER_DELTA 1 +#define HAVE_DECODER_IA64 1 +#define HAVE_DECODER_LZMA1 1 +#define HAVE_DECODER_LZMA2 1 +#define HAVE_DECODER_POWERPC 1 +#define HAVE_DECODER_SPARC 1 +#define HAVE_DECODER_X86 1 +#define HAVE_DLFCN_H 1 +#define HAVE_ENCODERS 1 +#define HAVE_ENCODER_ARM 1 +#define HAVE_ENCODER_ARMTHUMB 1 +#define HAVE_ENCODER_DELTA 1 +#define HAVE_ENCODER_IA64 1 +#define HAVE_ENCODER_LZMA1 1 +#define HAVE_ENCODER_LZMA2 1 +#define HAVE_ENCODER_POWERPC 1 +#define HAVE_ENCODER_SPARC 1 +#define HAVE_ENCODER_X86 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FUTIMENS 1 +#define HAVE_GETOPT_H 1 +#define HAVE_GETOPT_LONG 1 +#define HAVE_GETTEXT 1 +#define HAVE_IMMINTRIN_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_MBRTOWC 1 +#define HAVE_MEMORY_H 1 +#define HAVE_MF_BT2 1 +#define HAVE_MF_BT3 1 +#define HAVE_MF_BT4 1 +#define HAVE_MF_HC3 1 +#define HAVE_MF_HC4 1 +#define HAVE_OPTRESET 1 +#define HAVE_POSIX_FADVISE 1 +#define HAVE_PTHREAD_CONDATTR_SETCLOCK 1 +#define HAVE_PTHREAD_PRIO_INHERIT 1 +#define HAVE_STDBOOL_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_UINTPTR_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_VISIBILITY 1 +#define HAVE_WCWIDTH 1 +#define HAVE__BOOL 1 +#define HAVE___BUILTIN_ASSUME_ALIGNED 1 +#define HAVE___BUILTIN_BSWAPXX 1 +#define MYTHREAD_POSIX 1 +#define NDEBUG 1 +#define PACKAGE "xz" +#define PACKAGE_BUGREPORT "lasse.collin@tukaani.org" +#define PACKAGE_NAME "XZ Utils" +#define PACKAGE_STRING "XZ Utils 5.4.0" +#define PACKAGE_TARNAME "xz" +#define PACKAGE_VERSION "5.4.0" +#define SIZEOF_SIZE_T 4 +#define STDC_HEADERS 1 +#define TUKLIB_CPUCORES_SYSCONF 1 +#define TUKLIB_FAST_UNALIGNED_ACCESS 1 +#define TUKLIB_PHYSMEM_SYSCONF 1 +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +#define VERSION "5.4.0" +''' From 45886e50b21fd1dee461e910267781e264574790 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Apr 2024 18:54:10 +0100 Subject: [PATCH 26/26] Codechange: Unify where rail station tile flags are set. (#12531) This avoids repeating the logic in three places. --- src/saveload/afterload.cpp | 14 +------------- src/station_cmd.cpp | 31 ++++++++++++++++++++----------- src/station_func.h | 1 + src/waypoint_cmd.cpp | 11 +---------- 4 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 75f062fc4b..88dee51b9c 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2878,19 +2878,7 @@ bool AfterLoadGame() /* Station blocked, wires and pylon flags need to be stored in the map. This is effectively cached data, so no * version check is necessary. This is done here as the SLV_182 check below needs the blocked status. */ for (auto t : Map::Iterate()) { - if (HasStationTileRail(t)) { - StationGfx gfx = GetStationGfx(t); - const StationSpec *statspec = GetStationSpec(t); - - bool blocked = statspec != nullptr && HasBit(statspec->blocked, gfx); - /* Default stations do not draw pylons under roofs (gfx >= 4) */ - bool pylons = statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4; - bool wires = statspec == nullptr || !HasBit(statspec->wires, gfx); - - SetStationTileBlocked(t, blocked); - SetStationTileHavePylons(t, pylons); - SetStationTileHaveWires(t, wires); - } + if (HasStationTileRail(t)) SetRailStationTileFlags(t, GetStationSpec(t)); } } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 62ef3128b3..aece206dfc 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1294,6 +1294,24 @@ static CommandCost CalculateRailStationCost(TileArea tile_area, DoCommandFlag fl return cost; } +/** + * Set rail station tile flags for the given tile. + * @param tile Tile to set flags on. + * @param statspec Statspec of the tile. + */ +void SetRailStationTileFlags(TileIndex tile, const StationSpec *statspec) +{ + const StationGfx gfx = GetStationGfx(tile); + bool blocked = statspec != nullptr && HasBit(statspec->blocked, gfx); + /* Default stations do not draw pylons under roofs (gfx >= 4) */ + bool pylons = statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4; + bool wires = statspec == nullptr || !HasBit(statspec->wires, gfx); + + SetStationTileBlocked(tile, blocked); + SetStationTileHavePylons(tile, pylons); + SetStationTileHaveWires(tile, wires); +} + /** * Build rail station * @param flags operation to perform @@ -1456,18 +1474,9 @@ CommandCost CmdBuildRailStation(DoCommandFlag flags, TileIndex tile_org, RailTyp TriggerStationAnimation(st, tile, SAT_BUILT); } - /* Should be the same as layout but axis component could be wrong... */ - StationGfx gfx = GetStationGfx(tile); - bool blocked = statspec != nullptr && HasBit(statspec->blocked, gfx); - /* Default stations do not draw pylons under roofs (gfx >= 4) */ - bool pylons = statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4; - bool wires = statspec == nullptr || !HasBit(statspec->wires, gfx); - - SetStationTileBlocked(tile, blocked); - SetStationTileHavePylons(tile, pylons); - SetStationTileHaveWires(tile, wires); + SetRailStationTileFlags(tile, statspec); - if (!blocked) c->infrastructure.rail[rt]++; + if (!IsStationTileBlocked(tile)) c->infrastructure.rail[rt]++; c->infrastructure.station++; tile += tile_delta; diff --git a/src/station_func.h b/src/station_func.h index b71130f5d8..ab24b6cc9f 100644 --- a/src/station_func.h +++ b/src/station_func.h @@ -33,6 +33,7 @@ void UpdateStationAcceptance(Station *st, bool show_msg); CargoTypes GetAcceptanceMask(const Station *st); CargoTypes GetEmptyMask(const Station *st); +void SetRailStationTileFlags(TileIndex tile, const StationSpec *statspec); const DrawTileSprites *GetStationTileLayout(StationType st, uint8_t gfx); void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image); diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 2bf7ce5e52..0ffffcfc09 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -276,16 +276,7 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlag flags, TileIndex start_tile, Axis MakeRailWaypoint(tile, wp->owner, wp->index, axis, layout[i], GetRailType(tile)); SetCustomStationSpecIndex(tile, map_spec_index); - /* Should be the same as layout but axis component could be wrong... */ - StationGfx gfx = GetStationGfx(tile); - bool blocked = spec != nullptr && HasBit(spec->blocked, gfx); - /* Default stations do not draw pylons under roofs (gfx >= 4) */ - bool pylons = spec != nullptr ? HasBit(spec->pylons, gfx) : gfx < 4; - bool wires = spec == nullptr || !HasBit(spec->wires, gfx); - - SetStationTileBlocked(tile, blocked); - SetStationTileHavePylons(tile, pylons); - SetStationTileHaveWires(tile, wires); + SetRailStationTileFlags(tile, spec); SetRailStationReservation(tile, reserved); MarkTileDirtyByTile(tile);