From b7a5d8e296dc0a4e2459078394e1597f12c0d5cb Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 24 Jan 2023 22:50:53 +0100 Subject: [PATCH 01/10] Codechange: add annotation to selectively force inlining in debug build --- src/core/bitmath_func.hpp | 4 +-- src/core/strong_typedef_type.hpp | 24 ++++++++++++----- src/map_func.h | 16 ++++++------ src/pathfinder/follow_track.hpp | 8 +++--- src/rail_map.h | 10 +++---- src/road_map.h | 10 +++---- src/stdafx.h | 45 ++++++++++++++++++++++++++++++++ src/tile_map.h | 6 ++--- src/tile_type.h | 12 ++++++++- src/vehicle_base.h | 4 +-- 10 files changed, 102 insertions(+), 37 deletions(-) diff --git a/src/core/bitmath_func.hpp b/src/core/bitmath_func.hpp index 979d9b73b7..745a32afc4 100644 --- a/src/core/bitmath_func.hpp +++ b/src/core/bitmath_func.hpp @@ -29,7 +29,7 @@ * @return The selected bits, aligned to a LSB. */ template -static inline uint GB(const T x, const uint8 s, const uint8 n) +debug_inline static uint GB(const T x, const uint8 s, const uint8 n) { return (x >> s) & (((T)1U << n) - 1); } @@ -100,7 +100,7 @@ static inline T AB(T &x, const uint8 s, const uint8 n, const U i) * @return True if the bit is set, false else. */ template -static inline bool HasBit(const T x, const uint8 y) +debug_inline static bool HasBit(const T x, const uint8 y) { return (x & ((T)1U << y)) != 0; } diff --git a/src/core/strong_typedef_type.hpp b/src/core/strong_typedef_type.hpp index b5df28b2fb..179d2b3a0d 100644 --- a/src/core/strong_typedef_type.hpp +++ b/src/core/strong_typedef_type.hpp @@ -29,15 +29,15 @@ struct StrongTypedef : StrongTypedefBase { T value{}; ///< Backing storage field. - constexpr StrongTypedef() = default; - constexpr StrongTypedef(const StrongTypedef &o) = default; - constexpr StrongTypedef(StrongTypedef &&o) = default; + debug_inline constexpr StrongTypedef() = default; + debug_inline constexpr StrongTypedef(const StrongTypedef &o) = default; + debug_inline constexpr StrongTypedef(StrongTypedef &&o) = default; - constexpr StrongTypedef(const T &value) : value(value) {} + debug_inline constexpr StrongTypedef(const T &value) : value(value) {} - constexpr Tthis &operator =(const StrongTypedef &rhs) { this->value = rhs.value; return static_cast(*this); } - constexpr Tthis &operator =(StrongTypedef &&rhs) { this->value = std::move(rhs.value); return static_cast(*this); } - constexpr Tthis &operator =(const T &rhs) { this->value = rhs; return static_cast(*this); } + debug_inline constexpr Tthis &operator =(const StrongTypedef &rhs) { this->value = rhs.value; return static_cast(*this); } + debug_inline constexpr Tthis &operator =(StrongTypedef &&rhs) { this->value = std::move(rhs.value); return static_cast(*this); } + debug_inline constexpr Tthis &operator =(const T &rhs) { this->value = rhs; return static_cast(*this); } explicit constexpr operator T() const { return this->value; } @@ -56,6 +56,16 @@ template struct StrongIntegralTypedef : StrongTypedef { using StrongTypedef::StrongTypedef; + debug_inline constexpr StrongIntegralTypedef() = default; + debug_inline constexpr StrongIntegralTypedef(const StrongIntegralTypedef &o) = default; + debug_inline constexpr StrongIntegralTypedef(StrongIntegralTypedef &&o) = default; + + debug_inline constexpr StrongIntegralTypedef(const T &value) : StrongTypedef(value) {} + + debug_inline constexpr Tthis &operator =(const StrongIntegralTypedef &rhs) { this->value = rhs.value; return static_cast(*this); } + debug_inline constexpr Tthis &operator =(StrongIntegralTypedef &&rhs) { this->value = std::move(rhs.value); return static_cast(*this); } + debug_inline constexpr Tthis &operator =(const T &rhs) { this->value = rhs; return static_cast(*this); } + constexpr Tthis &operator ++() { this->value++; return static_cast(*this); } constexpr Tthis &operator --() { this->value--; return static_cast(*this); } constexpr Tthis operator ++(int) { auto res = static_cast(*this); this->value++; return res; } diff --git a/src/map_func.h b/src/map_func.h index f5279fe5b7..3ebfb349c6 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -51,7 +51,7 @@ public: * @note try to avoid using this one * @return 2^"return value" == Map::SizeX() */ - static inline uint LogX() + debug_inline static uint LogX() { return Map::log_x; } @@ -70,7 +70,7 @@ public: * Get the size of the map along the X * @return the number of tiles along the X of the map */ - static inline uint SizeX() + debug_inline static uint SizeX() { return Map::size_x; } @@ -88,7 +88,7 @@ public: * Get the size of the map * @return the number of tiles of the map */ - static inline uint Size() + debug_inline static uint Size() { return Map::size; } @@ -97,7 +97,7 @@ public: * Gets the maximum X coordinate within the map, including MP_VOID * @return the maximum X coordinate */ - static inline uint MaxX() + debug_inline static uint MaxX() { return Map::SizeX() - 1; } @@ -179,7 +179,7 @@ typedef int32 TileIndexDiff; * @param y The y coordinate of the tile * @return The TileIndex calculated by the coordinate */ -static inline TileIndex TileXY(uint x, uint y) +debug_inline static TileIndex TileXY(uint x, uint y) { return (y << Map::LogX()) + x; } @@ -210,7 +210,7 @@ static inline TileIndexDiff TileDiffXY(int x, int y) * @param y The virtual y coordinate of the tile. * @return The TileIndex calculated by the coordinate. */ -static inline TileIndex TileVirtXY(uint x, uint y) +debug_inline static TileIndex TileVirtXY(uint x, uint y) { return (y >> 4 << Map::LogX()) + (x >> 4); } @@ -221,7 +221,7 @@ static inline TileIndex TileVirtXY(uint x, uint y) * @param tile the tile to get the X component of * @return the X component */ -static inline uint TileX(TileIndex tile) +debug_inline static uint TileX(TileIndex tile) { return tile.value & Map::MaxX(); } @@ -231,7 +231,7 @@ static inline uint TileX(TileIndex tile) * @param tile the tile to get the Y component of * @return the Y component */ -static inline uint TileY(TileIndex tile) +debug_inline static uint TileY(TileIndex tile) { return tile.value >> Map::LogX(); } diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index ed5f181437..d50ae13d26 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -86,11 +86,11 @@ struct CFollowTrackT m_railtypes = railtype_override; } - inline static TransportType TT() { return Ttr_type_; } - inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; } - inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; } + debug_inline static TransportType TT() { return Ttr_type_; } + debug_inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; } + debug_inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; } inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(m_veh)->roadtype); } - inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; } + debug_inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; } inline static bool Allow90degTurns() { return T90deg_turns_allowed_; } inline static bool DoTrackMasking() { return Tmask_reserved_tracks; } diff --git a/src/rail_map.h b/src/rail_map.h index bd1d3c7492..5717da3613 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -33,7 +33,7 @@ enum RailTileType { * @pre IsTileType(t, MP_RAILWAY) * @return the RailTileType */ -static inline RailTileType GetRailTileType(TileIndex t) +debug_inline static RailTileType GetRailTileType(TileIndex t) { assert(IsTileType(t, MP_RAILWAY)); return (RailTileType)GB(_m[t].m5, 6, 2); @@ -46,7 +46,7 @@ static inline RailTileType GetRailTileType(TileIndex t) * @pre IsTileType(t, MP_RAILWAY) * @return true if and only if the tile is normal rail (with or without signals) */ -static inline bool IsPlainRail(TileIndex t) +debug_inline static bool IsPlainRail(TileIndex t) { RailTileType rtt = GetRailTileType(t); return rtt == RAIL_TILE_NORMAL || rtt == RAIL_TILE_SIGNALS; @@ -57,7 +57,7 @@ static inline bool IsPlainRail(TileIndex t) * @param t the tile to get the information from * @return true if and only if the tile is normal rail (with or without signals) */ -static inline bool IsPlainRailTile(TileIndex t) +debug_inline static bool IsPlainRailTile(TileIndex t) { return IsTileType(t, MP_RAILWAY) && IsPlainRail(t); } @@ -92,7 +92,7 @@ static inline void SetHasSignals(TileIndex tile, bool signals) * @pre IsTileType(t, MP_RAILWAY) * @return true if and only if the tile is a rail depot */ -static inline bool IsRailDepot(TileIndex t) +debug_inline static bool IsRailDepot(TileIndex t) { return GetRailTileType(t) == RAIL_TILE_DEPOT; } @@ -102,7 +102,7 @@ static inline bool IsRailDepot(TileIndex t) * @param t the tile to get the information from * @return true if and only if the tile is a rail depot */ -static inline bool IsRailDepotTile(TileIndex t) +debug_inline static bool IsRailDepotTile(TileIndex t) { return IsTileType(t, MP_RAILWAY) && IsRailDepot(t); } diff --git a/src/road_map.h b/src/road_map.h index 6be02e42f6..3114bcc18a 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -49,7 +49,7 @@ static inline bool MayHaveRoad(TileIndex t) * @pre IsTileType(t, MP_ROAD) * @return The road tile type. */ -static inline RoadTileType GetRoadTileType(TileIndex t) +debug_inline static RoadTileType GetRoadTileType(TileIndex t) { assert(IsTileType(t, MP_ROAD)); return (RoadTileType)GB(_m[t].m5, 6, 2); @@ -61,7 +61,7 @@ static inline RoadTileType GetRoadTileType(TileIndex t) * @pre IsTileType(t, MP_ROAD) * @return True if normal road. */ -static inline bool IsNormalRoad(TileIndex t) +debug_inline static bool IsNormalRoad(TileIndex t) { return GetRoadTileType(t) == ROAD_TILE_NORMAL; } @@ -71,7 +71,7 @@ static inline bool IsNormalRoad(TileIndex t) * @param t Tile to query. * @return True if normal road tile. */ -static inline bool IsNormalRoadTile(TileIndex t) +debug_inline static bool IsNormalRoadTile(TileIndex t) { return IsTileType(t, MP_ROAD) && IsNormalRoad(t); } @@ -103,7 +103,7 @@ static inline bool IsLevelCrossingTile(TileIndex t) * @pre IsTileType(t, MP_ROAD) * @return True if road depot. */ -static inline bool IsRoadDepot(TileIndex t) +debug_inline static bool IsRoadDepot(TileIndex t) { return GetRoadTileType(t) == ROAD_TILE_DEPOT; } @@ -113,7 +113,7 @@ static inline bool IsRoadDepot(TileIndex t) * @param t Tile to query. * @return True if road depot tile. */ -static inline bool IsRoadDepotTile(TileIndex t) +debug_inline static bool IsRoadDepotTile(TileIndex t) { return IsTileType(t, MP_ROAD) && IsRoadDepot(t); } diff --git a/src/stdafx.h b/src/stdafx.h index 395a3bf6e4..f62a83e83c 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -323,6 +323,51 @@ # define PRINTF_SIZEX "%zX" #endif +/* + * When making a (pure) debug build, the compiler will by default disable + * inlining of functions. This has a detremental effect on the performance of + * debug builds, especially when more and more trivial (wrapper) functions get + * added to the code base. + * Take for example the savegame called "Wentbourne", when running this game + * for 100 ticks with the null video driver a number of fairly trivial + * functions show up on top. The most common one is the implicit conversion + * operator of TileIndex to unsigned int, which takes up over 5% of the total + * run time and functionally does absolutely nothing. The remaining functions + * for the top 5 are GB, GetTileType, Map::Size and IsTileType to a total of + * about 12.5% of the game's total run time. + * It is possible to still force inlining in the most commonly used compilers, + * but that is at the cost of some problems with debugging due to the forced + * inlining. However, the performance benefit can be enormous; when forcing + * inlining for the previously mentioned top 5, the debug build ran about 15% + * quicker. + * The following debug_inline annotation may be added to functions comply + * with the following preconditions: + * 1: the function takes more than 0.5% of a profiled debug runtime + * 2: the function does not modify the game state + * 3: the function does not contain selection or iteration statements, + * i.e. no if, switch, for, do, while, etcetera. + * 4: the function is one line of code, excluding assertions. + * 5: the function is defined in a header file. + * The debug_inline annotation must be placed in front of the function, i.e. + * before the optional static or constexpr modifier. + */ +#if !defined(_DEBUG) || defined(NO_DEBUG_INLINE) +/* + * Do not force inlining when not in debug. This way we do not work against + * any carefully designed compiler optimizations. + */ +#define debug_inline inline +#elif defined(__clang__) || defined(__GNUC__) +#define debug_inline [[gnu::always_inline]] inline +#else +/* + * MSVC explicitly disables inlining, even forced inlining, in debug builds + * so __forceinline makes no difference compared to inline. Other unknown + * compilers can also just fallback to a normal inline. + */ +#define debug_inline inline +#endif + typedef unsigned char byte; /* This is already defined in unix, but not in QNX Neutrino (6.x) or Cygwin. */ diff --git a/src/tile_map.h b/src/tile_map.h index b02b957fa2..fb27154ab6 100644 --- a/src/tile_map.h +++ b/src/tile_map.h @@ -26,7 +26,7 @@ * @return the height of the tile * @pre tile < Map::Size() */ -static inline uint TileHeight(TileIndex tile) +debug_inline static uint TileHeight(TileIndex tile) { assert(tile < Map::Size()); return _m[tile].height; @@ -93,7 +93,7 @@ static inline uint TilePixelHeightOutsideMap(int x, int y) * @return The tiletype of the tile * @pre tile < Map::Size() */ -static inline TileType GetTileType(TileIndex tile) +debug_inline static TileType GetTileType(TileIndex tile) { assert(tile < Map::Size()); return (TileType)GB(_m[tile].type, 4, 4); @@ -147,7 +147,7 @@ static inline void SetTileType(TileIndex tile, TileType type) * @param type The type to check against * @return true If the type matches against the type of the tile */ -static inline bool IsTileType(TileIndex tile, TileType type) +debug_inline static bool IsTileType(TileIndex tile, TileType type) { return GetTileType(tile) == type; } diff --git a/src/tile_type.h b/src/tile_type.h index 6b5514d90e..db7ece562c 100644 --- a/src/tile_type.h +++ b/src/tile_type.h @@ -85,8 +85,18 @@ enum TropicZone { struct TileIndex : StrongIntegralTypedef { using StrongIntegralTypedef::StrongIntegralTypedef; + debug_inline constexpr TileIndex() = default; + debug_inline constexpr TileIndex(const TileIndex &o) = default; + debug_inline constexpr TileIndex(TileIndex &&o) = default; + + debug_inline constexpr TileIndex(const uint32 &value) : StrongIntegralTypedef(value) {} + + debug_inline constexpr TileIndex &operator =(const TileIndex &rhs) { this->value = rhs.value; return *this; } + debug_inline constexpr TileIndex &operator =(TileIndex &&rhs) { this->value = std::move(rhs.value); return *this; } + debug_inline constexpr TileIndex &operator =(const uint32 &rhs) { this->value = rhs; return *this; } + /** Implicit conversion to the base type for e.g. array indexing. */ - constexpr operator uint32() const { return this->value; } + debug_inline constexpr operator uint32() const { return this->value; } /* Import operators from the base class into our overload set. */ using StrongIntegralTypedef::operator ==; diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 60c36761bf..5d2ebba7fa 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -512,7 +512,7 @@ public: * Check if the vehicle is a ground vehicle. * @return True iff the vehicle is a train or a road vehicle. */ - inline bool IsGroundVehicle() const + debug_inline bool IsGroundVehicle() const { return this->type == VEH_TRAIN || this->type == VEH_ROAD; } @@ -924,7 +924,7 @@ public: * Check if the vehicle is a front engine. * @return Returns true if the vehicle is a front engine. */ - inline bool IsFrontEngine() const + debug_inline bool IsFrontEngine() const { return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_FRONT); } From f001e84e5e598a2b3bf3b539e1edc61cf5c95ab2 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 26 Jan 2023 19:21:36 +0100 Subject: [PATCH 02/10] Codechange: use RAII to automatically restore _cur_dpi after use --- src/core/backup_type.hpp | 42 +++++++++++++++++++ src/dock_gui.cpp | 4 +- src/industry_gui.cpp | 7 +--- src/misc_gui.cpp | 5 +-- src/newgrf_debug_gui.cpp | 7 +--- src/object_gui.cpp | 8 +--- src/rail_gui.cpp | 20 +++------ src/road_gui.cpp | 8 +--- src/roadveh_gui.cpp | 8 ++-- src/screenshot.cpp | 8 ++-- src/smallmap_gui.cpp | 8 +--- src/statusbar_gui.cpp | 5 +-- src/story_gui.cpp | 6 +-- src/textfile_gui.cpp | 6 +-- src/train_gui.cpp | 89 ++++++++++++++++++++-------------------- src/viewport.cpp | 11 ++--- src/widget.cpp | 12 ++---- src/window.cpp | 4 +- 18 files changed, 122 insertions(+), 136 deletions(-) diff --git a/src/core/backup_type.hpp b/src/core/backup_type.hpp index fc67b73ad9..62e6d31329 100644 --- a/src/core/backup_type.hpp +++ b/src/core/backup_type.hpp @@ -144,4 +144,46 @@ private: const int line; }; +/** + * Class to backup a specific variable and restore it upon destruction of this object to prevent + * stack values going out of scope before resetting the global to its original value. Contrary to + * #Backup this restores the variable automatically and there is no manual option to restore. + */ +template +struct AutoRestoreBackup { + /* + * There is explicitly no only original constructor version, as that would make it possible + * for the new value to go out of scope before this object goes out of scope, thus defeating + * the whole goal and reason for existing of this object. + */ + + /** + * Backup variable and switch to new value. + * @param original Variable to backup. + * @param new_value New value for variable. + */ + AutoRestoreBackup(T &original, T new_value) : original(original), original_value(original) + { + original = new_value; + } + + /** + * Restore the variable upon object destruction. + */ + ~AutoRestoreBackup() + { + this->original = this->original_value; + } + +private: + T &original; + T original_value; + + /* Prevent copy, assignment and allocation on stack. */ + AutoRestoreBackup(const AutoRestoreBackup&) = delete; + AutoRestoreBackup& operator=(AutoRestoreBackup&) = delete; + static void *operator new(std::size_t) = delete; + static void *operator new[](std::size_t) = delete; +}; + #endif /* BACKUP_TYPE_HPP */ diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index c8f0ad46a3..2477450fa3 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -547,15 +547,13 @@ public: Axis axis = widget == WID_BDD_X ? AXIS_X : AXIS_Y; if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(96)) / 2; int y = (r.Height() - ScaleSpriteTrad(64)) / 2; int x1 = ScaleSpriteTrad(63); int x2 = ScaleSpriteTrad(31); DrawShipDepotSprite(x + (axis == AXIS_X ? x1 : x2), y + ScaleSpriteTrad(17), axis, DEPOT_PART_NORTH); DrawShipDepotSprite(x + (axis == AXIS_X ? x2 : x1), y + ScaleSpriteTrad(33), axis, DEPOT_PART_SOUTH); - _cur_dpi = old_dpi; } break; } diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 61c99e1e40..f670443bcd 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2920,10 +2920,9 @@ struct IndustryCargoesWindow : public Window { if (widget != WID_IC_PANEL) return; Rect ir = r.Shrink(WidgetDimensions::scaled.framerect); - DrawPixelInfo tmp_dpi, *old_dpi; + DrawPixelInfo tmp_dpi; if (!FillDrawPixelInfo(&tmp_dpi, ir.left, ir.top, ir.Width(), ir.Height())) return; - old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int left_pos = ir.left; if (this->ind_cargo >= NUM_INDUSTRYTYPES) left_pos += (CargoesField::industry_width + CargoesField::cargo_field_width) / 2; @@ -2952,8 +2951,6 @@ struct IndustryCargoesWindow : public Window { vpos += row_height; if (vpos >= height) break; } - - _cur_dpi = old_dpi; } /** diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 352cbf7c2a..d1bca7d1b2 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -820,8 +820,7 @@ void QueryString::DrawEditBox(const Window *w, int wid) const DrawPixelInfo dpi; if (!FillDrawPixelInfo(&dpi, fr.left, fr.top, fr.Width(), fr.Height())) return; - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &dpi); /* We will take the current widget length as maximum width, with a small * space reserved at the end for the caret to show */ @@ -839,8 +838,6 @@ void QueryString::DrawEditBox(const Window *w, int wid) const int caret_width = GetStringBoundingBox("_").width; DrawString(tb->caretxoffs + delta, tb->caretxoffs + delta + caret_width, 0, "_", TC_WHITE); } - - _cur_dpi = old_dpi; } /** diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 8d13892d30..7c619e78c8 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include +#include "core/backup_type.hpp" #include "window_gui.h" #include "window_func.h" #include "random_access_file_type.h" @@ -895,17 +896,13 @@ struct SpriteAlignerWindow : Window { DrawPixelInfo new_dpi; if (!FillDrawPixelInfo(&new_dpi, ir.left, ir.top, ir.Width(), ir.Height())) break; - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &new_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &new_dpi); DrawSprite(this->current_sprite, PAL_NONE, x, y, nullptr, ZOOM_LVL_GUI); if (this->crosshair) { GfxDrawLine(x, 0, x, ir.Height() - 1, PC_WHITE, 1, 1); GfxDrawLine(0, y, ir.Width() - 1, y, PC_WHITE, 1, 1); } - - _cur_dpi = old_dpi; - break; } diff --git a/src/object_gui.cpp b/src/object_gui.cpp index 784e74607c..f45f2ae426 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -363,8 +363,7 @@ public: DrawPixelInfo tmp_dpi; /* Set up a clipping area for the preview. */ if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); if (spec->grf_prop.grffile == nullptr) { extern const DrawTileSprites _objects[]; const DrawTileSprites *dts = &_objects[spec->grf_prop.local_id]; @@ -372,7 +371,6 @@ public: } else { DrawNewObjectTileInGUI(r.Width() / 2 - 1, (r.Height() + matrix_height / 2) / 2 - this->object_margin - ScaleSpriteTrad(TILE_PIXELS), spec, GB(widget, 16, 16)); } - _cur_dpi = old_dpi; } break; } @@ -390,8 +388,7 @@ public: DrawPixelInfo tmp_dpi; /* Set up a clipping area for the preview. */ if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); if (spec->grf_prop.grffile == nullptr) { extern const DrawTileSprites _objects[]; const DrawTileSprites *dts = &_objects[spec->grf_prop.local_id]; @@ -400,7 +397,6 @@ public: DrawNewObjectTileInGUI(r.Width() / 2 - 1, r.Height() - this->object_margin - ScaleSpriteTrad(TILE_PIXELS), spec, std::min(_selected_object_view, spec->views - 1)); } - _cur_dpi = old_dpi; } break; } diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index f0039753b7..f8bc5360aa 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -1255,28 +1255,24 @@ public: case WID_BRAS_PLATFORM_DIR_X: /* Set up a clipping area for the '/' station preview */ if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31); int y = (r.Height() + ScaleSpriteTrad(58)) / 2 - ScaleSpriteTrad(31); if (!DrawStationTile(x, y, _cur_railtype, AXIS_X, _railstation.station_class, _railstation.station_type)) { StationPickerDrawSprite(x, y, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 2); } - _cur_dpi = old_dpi; } break; case WID_BRAS_PLATFORM_DIR_Y: /* Set up a clipping area for the '\' station preview */ if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31); int y = (r.Height() + ScaleSpriteTrad(58)) / 2 - ScaleSpriteTrad(31); if (!DrawStationTile(x, y, _cur_railtype, AXIS_Y, _railstation.station_class, _railstation.station_type)) { StationPickerDrawSprite(x, y, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 3); } - _cur_dpi = old_dpi; } break; @@ -1306,14 +1302,12 @@ public: /* Set up a clipping area for the station preview. */ if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31); int y = (r.Height() + ScaleSpriteTrad(58)) / 2 - ScaleSpriteTrad(31); if (!DrawStationTile(x, y, _cur_railtype, _railstation.orientation, _railstation.station_class, type)) { StationPickerDrawSprite(x, y, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 2 + _railstation.orientation); } - _cur_dpi = old_dpi; } break; } @@ -1940,12 +1934,10 @@ struct BuildRailDepotWindow : public PickerWindowBase { DrawPixelInfo tmp_dpi; if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31); int y = (r.Height() + ScaleSpriteTrad(48)) / 2 - ScaleSpriteTrad(31); DrawTrainDepotSprite(x, y, widget - WID_BRAD_DEPOT_NE + DIAGDIR_NE, _cur_railtype); - _cur_dpi = old_dpi; } } @@ -2052,12 +2044,10 @@ struct BuildRailWaypointWindow : PickerWindowBase { DrawPixelInfo tmp_dpi; if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31); int y = (r.Height() + ScaleSpriteTrad(58)) / 2 - ScaleSpriteTrad(31); DrawWaypointSprite(x, y, type, _cur_railtype); - _cur_dpi = old_dpi; } if (!IsStationAvailable(statspec)) { diff --git a/src/road_gui.cpp b/src/road_gui.cpp index ca3d91f183..b933db981d 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -984,12 +984,10 @@ struct BuildRoadDepotWindow : public PickerWindowBase { DrawPixelInfo tmp_dpi; if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31); int y = (r.Height() + ScaleSpriteTrad(48)) / 2 - ScaleSpriteTrad(31); DrawRoadDepotSprite(x, y, (DiagDirection)(widget - WID_BROD_DEPOT_NE + DIAGDIR_NE), _cur_roadtype); - _cur_dpi = old_dpi; } } @@ -1119,12 +1117,10 @@ struct BuildRoadStationWindow : public PickerWindowBase { DrawPixelInfo tmp_dpi; if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int x = (r.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31); int y = (r.Height() + ScaleSpriteTrad(48)) / 2 - ScaleSpriteTrad(31); StationPickerDrawSprite(x, y, st, INVALID_RAILTYPE, _cur_roadtype, widget - WID_BROS_STATION_NE); - _cur_dpi = old_dpi; } } diff --git a/src/roadveh_gui.cpp b/src/roadveh_gui.cpp index 8b3ee04775..da9200954e 100644 --- a/src/roadveh_gui.cpp +++ b/src/roadveh_gui.cpp @@ -8,6 +8,7 @@ /** @file roadveh_gui.cpp GUI for road vehicles. */ #include "stdafx.h" +#include "core/backup_type.hpp" #include "roadveh.h" #include "window_gui.h" #include "strings_func.h" @@ -130,13 +131,12 @@ void DrawRoadVehImage(const Vehicle *v, const Rect &r, VehicleID selection, Engi Direction dir = rtl ? DIR_E : DIR_W; const RoadVehicle *u = RoadVehicle::From(v); - DrawPixelInfo tmp_dpi, *old_dpi; + DrawPixelInfo tmp_dpi; int max_width = r.Width(); if (!FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) return; - old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); int px = rtl ? max_width + skip : -skip; int y = r.Height() / 2; @@ -155,8 +155,6 @@ void DrawRoadVehImage(const Vehicle *v, const Rect &r, VehicleID selection, Engi px += rtl ? -width : width; } - _cur_dpi = old_dpi; - if (v->index == selection) { int height = ScaleSpriteTrad(12); Rect hr = {(rtl ? px : 0), 0, (rtl ? max_width : px) - 1, height - 1}; diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 54cd4f990a..aed36ee7cb 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -8,6 +8,7 @@ /** @file screenshot.cpp The creation of screenshots! */ #include "stdafx.h" +#include "core/backup_type.hpp" #include "fileio_func.h" #include "viewport_func.h" #include "gfx_func.h" @@ -617,7 +618,7 @@ static void CurrentScreenCallback(void *userdata, void *buf, uint y, uint pitch, static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, uint n) { Viewport *vp = (Viewport *)userdata; - DrawPixelInfo dpi, *old_dpi; + DrawPixelInfo dpi; int wx, left; /* We are no longer rendering to the screen */ @@ -630,8 +631,7 @@ static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, ui _screen.pitch = pitch; _screen_disable_anim = true; - old_dpi = _cur_dpi; - _cur_dpi = &dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &dpi); dpi.dst_ptr = buf; dpi.height = n; @@ -655,8 +655,6 @@ static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, ui ); } - _cur_dpi = old_dpi; - /* Switch back to rendering to the screen */ _screen = old_screen; _screen_disable_anim = old_disable_anim; diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index ef1f14a711..7514fdbe99 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -8,6 +8,7 @@ /** @file smallmap_gui.cpp GUI that shows a small map of the world with metadata like owner or height. */ #include "stdafx.h" +#include "core/backup_type.hpp" #include "clear_map.h" #include "industry.h" #include "station_map.h" @@ -973,10 +974,7 @@ void SmallMapWindow::DrawMapIndicators() const void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi) const { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - DrawPixelInfo *old_dpi; - - old_dpi = _cur_dpi; - _cur_dpi = dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, dpi); /* Clear it */ GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, PC_BLACK); @@ -1027,8 +1025,6 @@ void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi) const /* Draw map indicators */ this->DrawMapIndicators(); - - _cur_dpi = old_dpi; } /** diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp index 5f53e731bc..69a71b75f7 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -8,6 +8,7 @@ /** @file statusbar_gui.cpp The GUI for the bottom status bar. */ #include "stdafx.h" +#include "core/backup_type.hpp" #include "date_func.h" #include "gfx_func.h" #include "news_func.h" @@ -68,10 +69,8 @@ static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left int width = GetStringBoundingBox(buffer).width; int pos = (_current_text_dir == TD_RTL) ? (scroll_pos - width) : (right - scroll_pos - left); - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); DrawString(pos, INT16_MAX, 0, buffer, TC_LIGHT_BLUE, SA_LEFT | SA_FORCE); - _cur_dpi = old_dpi; return (_current_text_dir == TD_RTL) ? (pos < right - left) : (pos + width > 0); } diff --git a/src/story_gui.cpp b/src/story_gui.cpp index bc62aff730..ac4ab8519f 100644 --- a/src/story_gui.cpp +++ b/src/story_gui.cpp @@ -698,8 +698,7 @@ public: DrawPixelInfo tmp_dpi; if (!FillDrawPixelInfo(&tmp_dpi, fr.left, fr.top, fr.Width(), fr.Height())) return; - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); /* Draw content (now coordinates given to Draw** are local to the new clipping region). */ fr = fr.Translate(-fr.left, -fr.top); @@ -758,9 +757,6 @@ public: default: NOT_REACHED(); } } - - /* Restore clipping region. */ - _cur_dpi = old_dpi; } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index e490491f50..021d7326d5 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -8,6 +8,7 @@ /** @file textfile_gui.cpp Implementation of textfile window. */ #include "stdafx.h" +#include "core/backup_type.hpp" #include "fileio_func.h" #include "fontcache.h" #include "gfx_type.h" @@ -152,8 +153,7 @@ void TextfileWindow::SetupScrollbars(bool force_reflow) DrawPixelInfo new_dpi; if (!FillDrawPixelInfo(&new_dpi, fr.left, fr.top, fr.Width(), fr.Height())) return; - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &new_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &new_dpi); /* Draw content (now coordinates given to DrawString* are local to the new clipping region). */ fr = fr.Translate(-fr.left, -fr.top); @@ -172,8 +172,6 @@ void TextfileWindow::SetupScrollbars(bool force_reflow) DrawString(-this->hscroll->GetPosition(), fr.right, y_offset, line.text, TC_BLACK, SA_TOP | SA_LEFT, false, FS_MONO); } } - - _cur_dpi = old_dpi; } /* virtual */ void TextfileWindow::OnResize() diff --git a/src/train_gui.cpp b/src/train_gui.cpp index 369da11c36..835fa24356 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -96,7 +96,7 @@ void DrawTrainImage(const Train *v, const Rect &r, VehicleID selection, EngineIm bool rtl = _current_text_dir == TD_RTL; Direction dir = rtl ? DIR_E : DIR_W; - DrawPixelInfo tmp_dpi, *old_dpi; + DrawPixelInfo tmp_dpi; /* Position of highlight box */ int highlight_l = 0; int highlight_r = 0; @@ -104,56 +104,55 @@ void DrawTrainImage(const Train *v, const Rect &r, VehicleID selection, EngineIm if (!FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.Width(), r.Height())) return; - old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + { + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); - int px = rtl ? max_width + skip : -skip; - int y = r.Height() / 2; - bool sel_articulated = false; - bool dragging = (drag_dest != INVALID_VEHICLE); - bool drag_at_end_of_train = (drag_dest == v->index); // Head index is used to mark dragging at end of train. - for (; v != nullptr && (rtl ? px > 0 : px < max_width); v = v->Next()) { - if (dragging && !drag_at_end_of_train && drag_dest == v->index) { - /* Highlight the drag-and-drop destination inside the train. */ - int drag_hlight_width = HighlightDragPosition(px, max_width, y, selection, _cursor.vehchain); - px += rtl ? -drag_hlight_width : drag_hlight_width; - } - - Point offset; - int width = Train::From(v)->GetDisplayImageWidth(&offset); - - if (rtl ? px + width > 0 : px - width < max_width) { - PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v); - VehicleSpriteSeq seq; - v->GetImage(dir, image_type, &seq); - seq.Draw(px + (rtl ? -offset.x : offset.x), y + offset.y, pal, (v->vehstatus & VS_CRASHED) != 0); - } - - if (!v->IsArticulatedPart()) sel_articulated = false; - - if (v->index == selection) { - /* Set the highlight position */ - highlight_l = rtl ? px - width : px; - highlight_r = rtl ? px - 1 : px + width - 1; - sel_articulated = true; - } else if ((_cursor.vehchain && highlight_r != 0) || sel_articulated) { - if (rtl) { - highlight_l -= width; - } else { - highlight_r += width; + int px = rtl ? max_width + skip : -skip; + int y = r.Height() / 2; + bool sel_articulated = false; + bool dragging = (drag_dest != INVALID_VEHICLE); + bool drag_at_end_of_train = (drag_dest == v->index); // Head index is used to mark dragging at end of train. + for (; v != nullptr && (rtl ? px > 0 : px < max_width); v = v->Next()) { + if (dragging && !drag_at_end_of_train && drag_dest == v->index) { + /* Highlight the drag-and-drop destination inside the train. */ + int drag_hlight_width = HighlightDragPosition(px, max_width, y, selection, _cursor.vehchain); + px += rtl ? -drag_hlight_width : drag_hlight_width; } + + Point offset; + int width = Train::From(v)->GetDisplayImageWidth(&offset); + + if (rtl ? px + width > 0 : px - width < max_width) { + PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v); + VehicleSpriteSeq seq; + v->GetImage(dir, image_type, &seq); + seq.Draw(px + (rtl ? -offset.x : offset.x), y + offset.y, pal, (v->vehstatus & VS_CRASHED) != 0); + } + + if (!v->IsArticulatedPart()) sel_articulated = false; + + if (v->index == selection) { + /* Set the highlight position */ + highlight_l = rtl ? px - width : px; + highlight_r = rtl ? px - 1 : px + width - 1; + sel_articulated = true; + } else if ((_cursor.vehchain && highlight_r != 0) || sel_articulated) { + if (rtl) { + highlight_l -= width; + } else { + highlight_r += width; + } + } + + px += rtl ? -width : width; } - px += rtl ? -width : width; + if (dragging && drag_at_end_of_train) { + /* Highlight the drag-and-drop destination at the end of the train. */ + HighlightDragPosition(px, max_width, y, selection, _cursor.vehchain); + } } - if (dragging && drag_at_end_of_train) { - /* Highlight the drag-and-drop destination at the end of the train. */ - HighlightDragPosition(px, max_width, y, selection, _cursor.vehchain); - } - - _cur_dpi = old_dpi; - if (highlight_l != highlight_r) { /* Draw the highlight. Now done after drawing all the engines, as * the next engine after the highlight could overlap it. */ diff --git a/src/viewport.cpp b/src/viewport.cpp index 3823b63e38..af3b26ba99 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -61,6 +61,7 @@ */ #include "stdafx.h" +#include "core/backup_type.hpp" #include "landscape.h" #include "viewport_func.h" #include "station_base.h" @@ -1726,9 +1727,6 @@ static void ViewportDrawStrings(ZoomLevel zoom, const StringSpriteToDrawVector * void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom) { - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &_vd.dpi; - _vd.dpi.zoom = vp->zoom; int mask = ScaleByZoom(-1, vp->zoom); @@ -1738,13 +1736,14 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom _vd.dpi.height = (bottom - top) & mask; _vd.dpi.left = left & mask; _vd.dpi.top = top & mask; - _vd.dpi.pitch = old_dpi->pitch; + _vd.dpi.pitch = _cur_dpi->pitch; _vd.last_child = nullptr; int x = UnScaleByZoom(_vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left; int y = UnScaleByZoom(_vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top; - _vd.dpi.dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(old_dpi->dst_ptr, x - old_dpi->left, y - old_dpi->top); + _vd.dpi.dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(_cur_dpi->dst_ptr, x - _cur_dpi->left, y - _cur_dpi->top); + AutoRestoreBackup dpi_backup(_cur_dpi, &_vd.dpi); ViewportAddLandscape(); ViewportAddVehicles(&_vd.dpi); @@ -1786,8 +1785,6 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom ViewportDrawStrings(zoom, &_vd.string_sprites_to_draw); } - _cur_dpi = old_dpi; - _vd.string_sprites_to_draw.clear(); _vd.tile_sprites_to_draw.clear(); _vd.parent_sprites_to_draw.clear(); diff --git a/src/widget.cpp b/src/widget.cpp index da85271fd6..08aafb910f 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -8,6 +8,7 @@ /** @file widget.cpp Handling of the default/simple widgets. */ #include "stdafx.h" +#include "core/backup_type.hpp" #include "company_func.h" #include "window_gui.h" #include "viewport_func.h" @@ -2009,8 +2010,7 @@ NWidgetCore *NWidgetMatrix::GetWidgetFromPos(int x, int y) bool rtl = _current_text_dir == TD_RTL; DrawPixelInfo tmp_dpi; if (!FillDrawPixelInfo(&tmp_dpi, this->pos_x + (rtl ? this->pip_post : this->pip_pre), this->pos_y + this->pip_pre, this->current_x - this->pip_pre - this->pip_post, this->current_y - this->pip_pre - this->pip_post)) return; - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &tmp_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); /* Get the appropriate offsets so we can draw the right widgets. */ NWidgetCore *child = dynamic_cast(this->head); @@ -2043,9 +2043,6 @@ NWidgetCore *NWidgetMatrix::GetWidgetFromPos(int x, int y) child->Draw(w); } } - - /* Restore the clipping area. */ - _cur_dpi = old_dpi; } /** @@ -2847,8 +2844,7 @@ void NWidgetLeaf::Draw(const Window *w) new_dpi.left += this->pos_x; new_dpi.top += this->pos_y; - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &new_dpi; + AutoRestoreBackup dpi_backup(_cur_dpi, &new_dpi); Rect r = this->GetCurrentRect(); @@ -2962,8 +2958,6 @@ void NWidgetLeaf::Draw(const Window *w) if (this->IsDisabled()) { GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[this->colour & 0xF][2], FILLRECT_CHECKER); } - - _cur_dpi = old_dpi; } /** diff --git a/src/window.cpp b/src/window.cpp index 736b2c443f..ec255f0f25 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -980,9 +980,8 @@ static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bo */ void DrawOverlappedWindowForAll(int left, int top, int right, int bottom) { - DrawPixelInfo *old_dpi = _cur_dpi; DrawPixelInfo bk; - _cur_dpi = &bk; + AutoRestoreBackup dpi_backup(_cur_dpi, &bk); for (Window *w : Window::IterateFromBack()) { if (MayBeShown(w) && @@ -994,7 +993,6 @@ void DrawOverlappedWindowForAll(int left, int top, int right, int bottom) DrawOverlappedWindow(w, std::max(left, w->left), std::max(top, w->top), std::min(right, w->left + w->width), std::min(bottom, w->top + w->height)); } } - _cur_dpi = old_dpi; } /** From 9fd88af5371317e4a0095c9ba4775123936de73e Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 28 Jan 2023 13:08:35 +0100 Subject: [PATCH 03/10] Remove: [Actions] Ubuntu/Debian release binaries (instead, use the Generic) --- .github/workflows/release.yml | 105 +--------------------------------- 1 file changed, 1 insertion(+), 104 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 939649a14c..94eb6a8018 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -361,108 +361,6 @@ jobs: path: build/bundles retention-days: 5 - linux-distro: - name: Linux (Distros) - needs: source - - if: needs.source.outputs.is_tag == 'true' - - strategy: - fail-fast: false - matrix: - include: - - container_image: "ubuntu:20.04" - bundle_name: "focal" - compiler: "g++" - - container_image: "ubuntu:22.04" - bundle_name: "jammy" - compiler: "g++" - - container_image: "debian:bullseye" - bundle_name: "bullseye" - compiler: "g++" - - runs-on: ubuntu-20.04 - container: - image: ${{ matrix.container_image }} - - steps: - - name: Download source - uses: actions/download-artifact@v3 - with: - name: internal-source - - - name: Unpack source - run: | - tar -xf source.tar.gz --strip-components=1 - - - name: Install dependencies - run: | - echo "::group::Update apt" - apt-get update - echo "::endgroup::" - - echo "::group::Install dependencies" - apt-get install -y --no-install-recommends \ - cmake \ - debhelper \ - ${{ matrix.compiler }} \ - git \ - make \ - openssl \ - libfontconfig-dev \ - libfluidsynth-dev \ - libicu-dev \ - liblzma-dev \ - liblzo2-dev \ - libsdl2-dev \ - lsb-release \ - zlib1g-dev \ - # EOF - echo "::endgroup::" - env: - DEBIAN_FRONTEND: noninteractive - - - name: Install GCC problem matcher - uses: ammaraskar/gcc-problem-matcher@master - - - name: Build - run: | - mkdir -p build - cd build - - echo "::group::CMake" - CXX=${{ matrix.compiler }} cmake ${GITHUB_WORKSPACE} \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DCMAKE_INSTALL_PREFIX=/usr \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - echo "Running on $(nproc) cores" - # Ubuntu 18.04 cmake does not support -j so we pass the option to the native tool - cmake --build . -- -j $(nproc) - echo "::endgroup::" - - - name: Create bundles - run: | - cd ${GITHUB_WORKSPACE}/build - echo "::group::Run CPack" - cpack - echo "::endgroup::" - - echo "::group::Cleanup" - # Remove the sha256 files CPack generates; we will do this ourself at - # the end of this workflow. - rm -f bundles/*.sha256 - echo "::endgroup::" - - - name: Store bundles - uses: actions/upload-artifact@v3 - with: - name: openttd-linux-${{ matrix.bundle_name }} - path: build/bundles - retention-days: 5 - macos: name: MacOS needs: source @@ -1036,7 +934,6 @@ jobs: - source - docs - linux - - linux-distro - macos - windows @@ -1045,7 +942,7 @@ jobs: # "always()" is important here, it is the keyword to use to stop skipping # this job if any dependency is skipped. It looks a bit silly, but it is # how GitHub Actions work ;) - if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && needs.linux.result == 'success' && (needs.linux-distro.result == 'success' || needs.linux-distro.result == 'skipped') && needs.macos.result == 'success' && needs.windows.result == 'success' + if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && needs.linux.result == 'success' && needs.macos.result == 'success' && needs.windows.result == 'success' runs-on: ubuntu-20.04 From 425ba826766bc0b12573223a3df171980ce909d4 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 28 Jan 2023 13:32:30 +0100 Subject: [PATCH 04/10] Change: [Actions] split GitHub workflows into several smaller ones --- .github/workflows/release-docs.yml | 85 ++ .github/workflows/release-linux.yml | 100 ++ .github/workflows/release-macos.yml | 195 ++++ .github/workflows/release-source.yml | 186 ++++ .github/workflows/release-windows-store.yml | 184 ++++ .github/workflows/release-windows.yml | 201 ++++ .github/workflows/release.yml | 1022 +------------------ .github/workflows/upload-aws.yml | 61 ++ .github/workflows/upload-steam.yml | 82 ++ 9 files changed, 1123 insertions(+), 993 deletions(-) create mode 100644 .github/workflows/release-docs.yml create mode 100644 .github/workflows/release-linux.yml create mode 100644 .github/workflows/release-macos.yml create mode 100644 .github/workflows/release-source.yml create mode 100644 .github/workflows/release-windows-store.yml create mode 100644 .github/workflows/release-windows.yml create mode 100644 .github/workflows/upload-aws.yml create mode 100644 .github/workflows/upload-steam.yml diff --git a/.github/workflows/release-docs.yml b/.github/workflows/release-docs.yml new file mode 100644 index 0000000000..759f33035c --- /dev/null +++ b/.github/workflows/release-docs.yml @@ -0,0 +1,85 @@ +name: Release (Docs) + +on: + workflow_call: + inputs: + version: + required: true + type: string + +jobs: + docs: + name: Docs + + runs-on: ubuntu-20.04 + + steps: + - name: Download source + uses: actions/download-artifact@v3 + with: + name: internal-source + + - name: Unpack source + run: | + tar -xf source.tar.gz --strip-components=1 + + - name: Install dependencies + run: | + echo "::group::Update apt" + sudo apt-get update + echo "::endgroup::" + + echo "::group::Install dependencies" + sudo apt-get install -y --no-install-recommends \ + doxygen \ + # EOF + echo "::endgroup::" + env: + DEBIAN_FRONTEND: noninteractive + + - name: Build + run: | + mkdir -p ${GITHUB_WORKSPACE}/build + cd ${GITHUB_WORKSPACE}/build + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DOPTION_DOCS_ONLY=ON \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + cmake --build . --target docs + echo "::endgroup::" + + - name: Create bundles + run: | + BASENAME=openttd-${{ inputs.version }} + + cd ${GITHUB_WORKSPACE}/build + + mv docs/source ${BASENAME}-docs + mv docs/ai-api ${BASENAME}-docs-ai + mv docs/gs-api ${BASENAME}-docs-gs + + mkdir -p bundles + + echo "::group::Create docs bundle" + tar --xz -cf bundles/${BASENAME}-docs.tar.xz ${BASENAME}-docs + echo "::endgroup::" + + echo "::group::Create AI API docs bundle" + tar --xz -cf bundles/${BASENAME}-docs-ai.tar.xz ${BASENAME}-docs-ai + echo "::endgroup::" + + echo "::group::Create GameScript API docs bundle" + tar --xz -cf bundles/${BASENAME}-docs-gs.tar.xz ${BASENAME}-docs-gs + echo "::endgroup::" + + - name: Store bundles + uses: actions/upload-artifact@v3 + with: + name: openttd-docs + path: build/bundles/*.tar.xz + retention-days: 5 diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml new file mode 100644 index 0000000000..c0cd7babe4 --- /dev/null +++ b/.github/workflows/release-linux.yml @@ -0,0 +1,100 @@ +name: Release (Linux) + +on: + workflow_call: + +jobs: + linux: + name: Linux (Generic) + + runs-on: ubuntu-20.04 + container: + # manylinux2014 is based on CentOS 7, but already has a lot of things + # installed and preconfigured. It makes it easier to build OpenTTD. + image: quay.io/pypa/manylinux2014_x86_64 + + steps: + - name: Download source + uses: actions/download-artifact@v3 + with: + name: internal-source + + - name: Unpack source + run: | + tar -xf source.tar.gz --strip-components=1 + + - name: Install dependencies + run: | + echo "::group::Install dependencies" + yum install -y \ + fontconfig-devel \ + freetype-devel \ + libicu-devel \ + libpng-devel \ + lzo-devel \ + SDL2-devel \ + wget \ + xz-devel \ + zlib-devel \ + # EOF + echo "::endgroup::" + + # The yum variant of fluidsynth depends on all possible audio drivers, + # like jack, ALSA, pulseaudio, etc. This is not really useful for us, + # as we route the output of fluidsynth back via our sound driver, and + # as such do not use these audio driver outputs at all. So instead, + # we compile fluidsynth ourselves, with as little dependencies as + # possible. This currently means it picks up SDL2, but this is fine, + # as we need SDL2 anyway. + echo "::group::Install fluidsynth" + wget https://github.com/FluidSynth/fluidsynth/archive/v2.1.6.tar.gz + tar xf v2.1.6.tar.gz + ( + cd fluidsynth-2.1.6 + mkdir build + cd build + cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr + cmake --build . -j $(nproc) + cmake --install . + ) + echo "::endgroup::" + + - name: Install GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@master + + - name: Build + run: | + mkdir -p build + cd build + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DOPTION_PACKAGE_DEPENDENCIES=ON \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(nproc) cores" + cmake --build . -j $(nproc) + echo "::endgroup::" + + - name: Create bundles + run: | + cd ${GITHUB_WORKSPACE}/build + echo "::group::Run CPack" + cpack + echo "::endgroup::" + + echo "::group::Cleanup" + # Remove the sha256 files CPack generates; we will do this ourself at + # the end of this workflow. + rm -f bundles/*.sha256 + echo "::endgroup::" + + - name: Store bundles + uses: actions/upload-artifact@v3 + with: + name: openttd-linux-generic + path: build/bundles + retention-days: 5 diff --git a/.github/workflows/release-macos.yml b/.github/workflows/release-macos.yml new file mode 100644 index 0000000000..50df24c7ca --- /dev/null +++ b/.github/workflows/release-macos.yml @@ -0,0 +1,195 @@ +name: Release (MacOS) + +on: + workflow_call: + +jobs: + macos: + name: MacOS + + runs-on: macos-11 + env: + MACOSX_DEPLOYMENT_TARGET: 10.13 + + steps: + - name: Download source + uses: actions/download-artifact@v3 + with: + name: internal-source + + - name: Unpack source + run: | + tar -xf source.tar.gz --strip-components=1 + + - name: Install dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 + run: | + brew install pandoc + + - name: Prepare cache key + id: key + run: | + echo "image=$ImageOS-$ImageVersion" >> $GITHUB_OUTPUT + + - name: Enable vcpkg cache + uses: actions/cache@v3 + with: + path: /usr/local/share/vcpkg/installed + key: ${{ steps.key.outputs.image }}-vcpkg-release-0 # Increase the number whenever dependencies are modified + restore-keys: | + ${{ steps.key.outputs.image }}-vcpkg-release + ${{ steps.key.outputs.image }}-vcpkg-x64 + + - name: Prepare vcpkg + run: | + vcpkg install \ + liblzma:x64-osx \ + liblzma:arm64-osx \ + libpng:x64-osx \ + libpng:arm64-osx \ + lzo:x64-osx \ + lzo:arm64-osx \ + zlib:x64-osx \ + zlib:arm64-osx \ + # EOF + + - name: Install GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@master + + - name: Build tools + run: | + mkdir build-host + cd build-host + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DOPTION_TOOLS_ONLY=ON \ + # EOF + echo "::endgroup::" + + echo "::group::Build tools" + echo "Running on $(sysctl -n hw.logicalcpu) cores" + cmake --build . -j $(sysctl -n hw.logicalcpu) --target tools + echo "::endgroup::" + + - name: Import code signing certificates + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + # If this is run on a fork, there may not be a certificate set up - continue in this case + continue-on-error: true + + - name: Build arm64 + run: | + mkdir build-arm64 + cd build-arm64 + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -DCMAKE_OSX_ARCHITECTURES=arm64 \ + -DVCPKG_TARGET_TRIPLET=arm64-osx \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(sysctl -n hw.logicalcpu) cores" + cmake --build . -j $(sysctl -n hw.logicalcpu) + echo "::endgroup::" + + - name: Build x64 + run: | + mkdir build-x64 + cd build-x64 + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -DCMAKE_OSX_ARCHITECTURES=x86_64 \ + -DVCPKG_TARGET_TRIPLET=x64-osx \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCPACK_BUNDLE_APPLE_CERT_APP=${{ secrets.APPLE_DEVELOPER_CERTIFICATE_ID }} \ + "-DCPACK_BUNDLE_APPLE_CODESIGN_PARAMETER=--deep -f --options runtime" \ + -DAPPLE_UNIVERSAL_PACKAGE=1 \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(sysctl -n hw.logicalcpu) cores" + cmake --build . -j $(sysctl -n hw.logicalcpu) + echo "::endgroup::" + + - name: Create bundles + run: | + cd build-x64 + + echo "::group::Create universal binary" + # Combine the `openttd` binaries from each build into a single file + lipo -create -output openttd-universal ../build-*/openttd + mv openttd-universal openttd + echo "::endgroup::" + + echo "::group::Run CPack" + cpack + echo "::endgroup::" + + echo "::group::Cleanup" + # Remove the sha256 files CPack generates; we will do this ourself at + # the end of this workflow. + rm -f bundles/*.sha256 + echo "::endgroup::" + + - name: Install gon + env: + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 + run: | + brew tap mitchellh/gon + brew install mitchellh/gon/gon + + - name: Notarize + env: + AC_USERNAME: ${{ secrets.APPLE_DEVELOPER_APP_USERNAME }} + AC_PASSWORD: ${{ secrets.APPLE_DEVELOPER_APP_PASSWORD }} + run: | + cd build-x64 + ../os/macosx/notarize.sh + + - name: Build zip + run: | + cd build-x64 + + pushd _CPack_Packages/*/Bundle/openttd-*/ + + # Remove the Applications symlink from the staging folder + rm -f Applications + + # Remove the original dmg built by CPack to avoid a conflict when resolving + # the zip_filename variable below + rm -f ../*.dmg + + zip_filename=(../openttd-*) + + # Package up the existing, notarised .app into a zip file + zip -r -9 ${zip_filename}.zip OpenTTD.app + + popd + + # Now move it into place to be uploaded + mv _CPack_Packages/*/Bundle/openttd-*.zip bundles/ + + - name: Store bundles + uses: actions/upload-artifact@v3 + with: + name: openttd-macos-universal + path: build-x64/bundles + retention-days: 5 diff --git a/.github/workflows/release-source.yml b/.github/workflows/release-source.yml new file mode 100644 index 0000000000..2213efed25 --- /dev/null +++ b/.github/workflows/release-source.yml @@ -0,0 +1,186 @@ +name: Release (Source) + +on: + workflow_call: + outputs: + version: + value: ${{ jobs.source.outputs.version }} + is_tag: + value: ${{ jobs.source.outputs.is_tag }} + trigger_type: + value: ${{ jobs.source.outputs.trigger_type }} + folder: + value: ${{ jobs.source.outputs.folder }} + +jobs: + source: + name: Source + + runs-on: ubuntu-20.04 + + outputs: + version: ${{ steps.metadata.outputs.version }} + is_tag: ${{ steps.metadata.outputs.is_tag }} + trigger_type: ${{ steps.metadata.outputs.trigger_type }} + folder: ${{ steps.metadata.outputs.folder }} + + steps: + - name: Checkout (Release) + if: github.event_name == 'release' + uses: actions/checkout@v3 + with: + # We generate a changelog; for this we need the full git log. + fetch-depth: 0 + + - name: Checkout (Manual) + if: github.event_name == 'workflow_dispatch' + uses: actions/checkout@v3 + with: + ref: ${{ github.event.inputs.ref }} + # We generate a changelog; for this we need the full git log. + fetch-depth: 0 + + - name: Checkout (Trigger) + if: github.event_name == 'repository_dispatch' + uses: actions/checkout@v3 + with: + ref: ${{ github.event.client_payload.ref }} + # We generate a changelog; for this we need the full git log. + fetch-depth: 0 + + - name: Check valid branch name + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + REF="${{ github.event.inputs.ref }}" + elif [ "${{ github.event_name }}" = "repository_dispatch" ]; then + REF="${{ github.event.client_payload.ref }}" + else + REF="${{ github.ref }}" + fi + + # Check if we are a tag. + if [ -n "$(git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || false)" ]; then + exit 0 + fi + + # Check if the checkout caused the branch to be named. + if [ "$(git rev-parse --abbrev-ref HEAD)" != "HEAD" ]; then + exit 0 + fi + + # Check if this was a pull request. + if [ -n "$(echo ${REF} | grep '^refs/pull/[0-9]*')" ]; then + PULL=$(echo ${REF} | cut -d/ -f3) + git checkout -b pr${PULL} + fi + + # Are we still in a detached state? Error out. + if [ "$(git rev-parse --abbrev-ref HEAD)" == "HEAD" ]; then + echo "The 'ref' given resulted in a checkout of a detached HEAD." + echo "We cannot detect the version for these checkout accurate." + echo "" + echo "If you want to build a Pull Request, make sure you use 'refs/pull/NNN/head'." + echo "" + echo "Cancelling build, as without a version we cannot store the artifacts." + exit 1 + fi + + - name: Generate metadata + id: metadata + run: | + echo "::group::Prepare metadata files" + cmake -DGENERATE_OTTDREV=1 -P cmake/scripts/FindVersion.cmake + ./.github/changelog.sh > .changelog + TZ='UTC' date +"%Y-%m-%d %H:%M UTC" > .release_date + cat .ottdrev | cut -f 1 -d$'\t' > .version + + if [ $(cat .ottdrev | cut -f 5 -d$'\t') = '1' ]; then + # Assume that all tags are always releases. Why else make a tag? + IS_TAG="true" + + FOLDER="${{ env.FOLDER_RELEASES }}" + TRIGGER_TYPE="new-tag" + else + IS_TAG="false" + + BRANCH=$(git symbolic-ref -q HEAD | sed 's@.*/@@') + if [ -z "${BRANCH}" ]; then + echo "Internal error: branch name is empty." + echo "An earlier step should have prevented this from happening." + echo "Cancelling build, as without a branch name we cannot store the artifacts" + exit 1 + fi + + if [ "${BRANCH}" = "${{ env.NIGHTLIES_BRANCH }}" ]; then + # The "master" branch is special, and we call a nightly. + FOLDER="${{ env.FOLDER_NIGHTLIES }}/$(date +%Y)" + TRIGGER_TYPE="new-master" + else + # All other branches, which can be builds of Pull Requests, are + # put in their own folder. + FOLDER="${{ env.FOLDER_BRANCHES }}/${BRANCH}" + TRIGGER_TYPE="new-branch" + fi + fi + + mkdir -p build/bundles + cp .changelog build/bundles/changelog.txt + cp .release_date build/bundles/released.txt + cp README.md build/bundles/README.md + echo "::endgroup::" + + echo "Release Date: $(cat .release_date)" + echo "Revision: $(cat .ottdrev)" + echo "Version: $(cat .version)" + echo "Is tag: ${IS_TAG}" + echo "Folder on CDN: ${FOLDER}" + echo "Workflow trigger: ${TRIGGER_TYPE}" + + echo "version=$(cat .version)" >> $GITHUB_OUTPUT + echo "is_tag=${IS_TAG}" >> $GITHUB_OUTPUT + echo "folder=${FOLDER}" >> $GITHUB_OUTPUT + echo "trigger_type=${TRIGGER_TYPE}" >> $GITHUB_OUTPUT + env: + NIGHTLIES_BRANCH: master + FOLDER_RELEASES: openttd-releases + FOLDER_NIGHTLIES: openttd-nightlies + FOLDER_BRANCHES: openttd-branches + + - name: Remove VCS information + run: | + rm -rf .git + + - name: Create bundles + run: | + FOLDER_NAME=openttd-${{ steps.metadata.outputs.version }} + + # Rename the folder to openttd-NNN + mkdir ${FOLDER_NAME} + find . -maxdepth 1 -not -name . -not -name build -not -name ${FOLDER_NAME} -exec mv {} ${FOLDER_NAME}/ \; + + echo "::group::Create tarball (xz) bundle" + tar --xz -cvf build/bundles/${FOLDER_NAME}-source.tar.xz ${FOLDER_NAME} + echo "::endgroup::" + + # This tarball is only to be used within this workflow. + echo "::group::Create tarball (gz) bundle" + tar --gzip -cvf source.tar.gz ${FOLDER_NAME} + echo "::endgroup::" + + echo "::group::Create zip bundle" + zip -9 -r build/bundles/${FOLDER_NAME}-source.zip ${FOLDER_NAME} + echo "::endgroup::" + + - name: Store bundles + uses: actions/upload-artifact@v3 + with: + name: openttd-source + path: build/bundles/* + retention-days: 5 + + - name: Store source (for other jobs) + uses: actions/upload-artifact@v3 + with: + name: internal-source + path: source.tar.gz + retention-days: 1 diff --git a/.github/workflows/release-windows-store.yml b/.github/workflows/release-windows-store.yml new file mode 100644 index 0000000000..c4753b5ff0 --- /dev/null +++ b/.github/workflows/release-windows-store.yml @@ -0,0 +1,184 @@ +name: Release (Windows Store) + +on: + workflow_call: + +jobs: + windows-store: + name: Windows Store + + runs-on: windows-latest + + steps: + - name: Download source + uses: actions/download-artifact@v3 + with: + name: internal-source + + - name: Unpack source + shell: bash + run: | + tar -xf source.tar.gz --strip-components=1 + + - name: Download x86 build + uses: actions/download-artifact@v3 + with: + name: openttd-windows-x86 + + - name: Download x64 build + uses: actions/download-artifact@v3 + with: + name: openttd-windows-x64 + + - name: Download arm64 build + uses: actions/download-artifact@v3 + with: + name: openttd-windows-arm64 + + - name: Unpack builds + shell: bash + run: | + mkdir builds + cd builds + + function extract { + mkdir $1 + + # Extract the zip version of the release + unzip ../openttd-*-windows-$2.zip -d $1 + + # Remove the extraneous directory + mv $1/openttd-*-windows-$2/* $1/ + rmdir $1/openttd-*-windows-$2 + + # Move the openttd.exe to the '{arch}-binaries' folder + mkdir $1-binaries + mv $1/openttd.exe $1-binaries/ + } + + extract x86 win32 + extract x64 win64 + extract arm64 arm64 + + # Use the "x86" folder as the source of the common binaries (lang files, etc) and remove the others + mv x86 common-binaries + rm -rf x64 arm64 + + - name: Install OpenGFX + shell: bash + run: | + mkdir -p builds/common-binaries/baseset + cd builds/common-binaries/baseset + + echo "::group::Download OpenGFX" + curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenGFX" + unzip opengfx-all.zip + tar xf opengfx-*.tar + echo "::endgroup::" + + rm -f opengfx-all.zip opengfx-*.tar + + - name: Install OpenMSX + shell: bash + run: | + mkdir -p builds/common-binaries/baseset + cd builds/common-binaries/baseset + + echo "::group::Download OpenMSX" + curl -L https://cdn.openttd.org/openmsx-releases/0.4.2/openmsx-0.4.2-all.zip -o openmsx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenGFX" + unzip openmsx-all.zip + tar xf openmsx-*.tar + echo "::endgroup::" + + rm -f openmsx-all.zip openmsx-*.tar + + - name: Install OpenSFX + shell: bash + run: | + mkdir -p builds/common-binaries/baseset/opensfx + cd builds/common-binaries/baseset/opensfx + + echo "::group::Download OpenSFX" + curl -L https://cdn.openttd.org/opensfx-releases/1.0.3/opensfx-1.0.3-all.zip -o opensfx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenSFX" + unzip opensfx-all.zip + tar xf opensfx-*.tar + echo "::endgroup::" + + rm -f opensfx-all.zip opensfx-*.tar + + - name: Generate signing certificate + shell: cmd + run: | + cd builds + + REM We need to provide a signed .appx to the Windows Store, so generate a certificate with password 'password' + call ..\os\windows\winstore\generate-key.bat "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" password cert.pfx + + - name: Generate assets + shell: cmd + run: | + cd os\windows\winstore + call generate-assets.bat + + - name: Prepare manifests + shell: cmd + run: | + cd builds + mkdir manifests + + REM Set the version environment variable + call ..\os\windows\winstore\set-version.bat x86-binaries\openttd.exe + + call ..\os\windows\winstore\prepare-manifests.bat manifests "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" "57420OpenTTDDevelopers.OpenTTDofficial" + + - name: Prepare binaries + shell: bash + run: | + cd builds + + # Copy the Windows Store assets + mkdir common-binaries/Assets + cp -R ../os/windows/winstore/assets-common/* common-binaries/Assets/ + + mkdir Assets + cp -R ../os/windows/winstore/assets/* Assets/ + + cp manifests/*.xml . + + - name: Build + shell: cmd + run: | + REM Add the Windows SDK tools to the PATH + + echo|set /p="SET VS_INSTALLDIR=" > _vspath.bat + vswhere -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath >> _vspath.bat + call _vspath.bat + call "%VS_INSTALLDIR%\Common7\Tools\VsDevCmd.bat" + + REM Set the version environment variable + call os\windows\winstore\set-version.bat builds\x86-binaries\openttd.exe + + cd builds + mkdir output + + REM Build and sign the package + makeappx build /v /f PackagingLayout.xml /op output\ /bv %OTTD_VERSION% /pv %OTTD_VERSION% /ca + SignTool sign /fd sha256 /a /f cert.pfx /p password "output\OpenTTD.appxbundle" + + - name: Store appx + uses: actions/upload-artifact@v3 + with: + name: openttd-windows-store + path: | + builds/output/OpenTTD.appxbundle + builds/cert.pfx + retention-days: 5 diff --git a/.github/workflows/release-windows.yml b/.github/workflows/release-windows.yml new file mode 100644 index 0000000000..af67ffb18f --- /dev/null +++ b/.github/workflows/release-windows.yml @@ -0,0 +1,201 @@ +name: Release (Windows) + +on: + workflow_call: + inputs: + is_tag: + required: true + type: string + +jobs: + windows: + name: Windows + + strategy: + fail-fast: false + matrix: + include: + - arch: x86 + host: x86 + - arch: x64 + host: x64 + - arch: arm64 + host: x64_arm64 + + runs-on: windows-latest + + steps: + - name: Download source + uses: actions/download-artifact@v3 + with: + name: internal-source + + - name: Unpack source + shell: bash + run: | + tar -xf source.tar.gz --strip-components=1 + + - name: Install dependencies + shell: bash + run: | + choco install pandoc + + - name: Prepare cache key + id: key + shell: powershell + run: | + # Work around caching failure with GNU tar + New-Item -Type Junction -Path vcpkg -Target c:\vcpkg + + Write-Output "image=$env:ImageOS-$env:ImageVersion" >> $env:GITHUB_OUTPUT + + - name: Enable vcpkg cache + uses: actions/cache@v3 + with: + path: vcpkg/installed + key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified + restore-keys: | + ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }} + + - name: Prepare vcpkg + shell: bash + run: | + vcpkg install --triplet=${{ matrix.arch }}-windows-static \ + liblzma \ + libpng \ + lzo \ + zlib \ + # EOF + + - name: Install MSVC problem matcher + uses: ammaraskar/msvc-problem-matcher@master + + - name: Configure developer command prompt for tools + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Build tools + shell: bash + run: | + mkdir build-host + cd build-host + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -GNinja \ + -DOPTION_TOOLS_ONLY=ON \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + cmake --build . --target tools + echo "::endgroup::" + + - name: Configure developer command prompt for ${{ matrix.arch }} + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.host }} + + - name: Import code signing certificate + shell: powershell + # If this is run on a fork, there may not be a certificate set up - continue in this case + continue-on-error: true + run: | + $tempFile = [System.IO.Path]::GetTempFileName() + $bytes = [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_P12) + [IO.File]::WriteAllBytes($tempFile, $bytes) + $pwd = ConvertTo-SecureString $env:WINDOWS_CERTIFICATE_PASSWORD -AsPlainText -Force + Import-PfxCertificate -FilePath $tempFile -CertStoreLocation Cert:\CurrentUser\My -Password $pwd + Remove-Item $tempFile + env: + WINDOWS_CERTIFICATE_P12: ${{ secrets.WINDOWS_CERTIFICATE_P12 }} + WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} + + - name: Build (with installer) + if: inputs.is_tag == 'true' + shell: bash + run: | + mkdir build + cd build + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -GNinja \ + -DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \ + -DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \ + -DOPTION_USE_NSIS=ON \ + -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + cmake --build . + echo "::endgroup::" + env: + WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} + + - name: Build (without installer) + if: inputs.is_tag != 'true' + shell: bash + run: | + mkdir build + cd build + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -GNinja \ + -DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \ + -DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \ + -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + cmake --build . + echo "::endgroup::" + env: + WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} + + - name: Create bundles + shell: bash + run: | + cd ${GITHUB_WORKSPACE}/build + echo "::group::Run CPack" + cpack + echo "::endgroup::" + + echo "::group::Prepare PDB to be bundled" + PDB=$(ls bundles/*.zip | cut -d/ -f2 | sed 's/.zip$/.pdb/') + cp openttd.pdb bundles/${PDB} + xz -9 bundles/${PDB} + echo "::endgroup::" + + echo "::group::Cleanup" + # Remove the sha256 files CPack generates; we will do this ourself at + # the end of this workflow. + rm -f bundles/*.sha256 + echo "::endgroup::" + + - name: Sign installer + if: inputs.is_tag == 'true' + shell: bash + # If this is run on a fork, there may not be a certificate set up - continue in this case + continue-on-error: true + run: | + cd ${GITHUB_WORKSPACE}/build/bundles + ../../os/windows/sign.bat *.exe "${WINDOWS_CERTIFICATE_COMMON_NAME}" + env: + WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} + + - name: Store bundles + uses: actions/upload-artifact@v3 + with: + name: openttd-windows-${{ matrix.arch }} + path: build/bundles + retention-days: 5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 94eb6a8018..9526334456 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,917 +18,55 @@ jobs: source: name: Source - runs-on: ubuntu-20.04 - - outputs: - version: ${{ steps.metadata.outputs.version }} - is_tag: ${{ steps.metadata.outputs.is_tag }} - trigger_type: ${{ steps.metadata.outputs.trigger_type }} - folder: ${{ steps.metadata.outputs.folder }} - - steps: - - name: Checkout (Release) - if: github.event_name == 'release' - uses: actions/checkout@v3 - with: - # We generate a changelog; for this we need the full git log. - fetch-depth: 0 - - - name: Checkout (Manual) - if: github.event_name == 'workflow_dispatch' - uses: actions/checkout@v3 - with: - ref: ${{ github.event.inputs.ref }} - # We generate a changelog; for this we need the full git log. - fetch-depth: 0 - - - name: Checkout (Trigger) - if: github.event_name == 'repository_dispatch' - uses: actions/checkout@v3 - with: - ref: ${{ github.event.client_payload.ref }} - # We generate a changelog; for this we need the full git log. - fetch-depth: 0 - - - name: Check valid branch name - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - REF="${{ github.event.inputs.ref }}" - elif [ "${{ github.event_name }}" = "repository_dispatch" ]; then - REF="${{ github.event.client_payload.ref }}" - else - REF="${{ github.ref }}" - fi - - # Check if we are a tag. - if [ -n "$(git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || false)" ]; then - exit 0 - fi - - # Check if the checkout caused the branch to be named. - if [ "$(git rev-parse --abbrev-ref HEAD)" != "HEAD" ]; then - exit 0 - fi - - # Check if this was a pull request. - if [ -n "$(echo ${REF} | grep '^refs/pull/[0-9]*')" ]; then - PULL=$(echo ${REF} | cut -d/ -f3) - git checkout -b pr${PULL} - fi - - # Are we still in a detached state? Error out. - if [ "$(git rev-parse --abbrev-ref HEAD)" == "HEAD" ]; then - echo "The 'ref' given resulted in a checkout of a detached HEAD." - echo "We cannot detect the version for these checkout accurate." - echo "" - echo "If you want to build a Pull Request, make sure you use 'refs/pull/NNN/head'." - echo "" - echo "Cancelling build, as without a version we cannot store the artifacts." - exit 1 - fi - - - name: Generate metadata - id: metadata - run: | - echo "::group::Prepare metadata files" - cmake -DGENERATE_OTTDREV=1 -P cmake/scripts/FindVersion.cmake - ./.github/changelog.sh > .changelog - TZ='UTC' date +"%Y-%m-%d %H:%M UTC" > .release_date - cat .ottdrev | cut -f 1 -d$'\t' > .version - - if [ $(cat .ottdrev | cut -f 5 -d$'\t') = '1' ]; then - # Assume that all tags are always releases. Why else make a tag? - IS_TAG="true" - - FOLDER="${{ env.FOLDER_RELEASES }}" - TRIGGER_TYPE="new-tag" - else - IS_TAG="false" - - BRANCH=$(git symbolic-ref -q HEAD | sed 's@.*/@@') - if [ -z "${BRANCH}" ]; then - echo "Internal error: branch name is empty." - echo "An earlier step should have prevented this from happening." - echo "Cancelling build, as without a branch name we cannot store the artifacts" - exit 1 - fi - - if [ "${BRANCH}" = "${{ env.NIGHTLIES_BRANCH }}" ]; then - # The "master" branch is special, and we call a nightly. - FOLDER="${{ env.FOLDER_NIGHTLIES }}/$(date +%Y)" - TRIGGER_TYPE="new-master" - else - # All other branches, which can be builds of Pull Requests, are - # put in their own folder. - FOLDER="${{ env.FOLDER_BRANCHES }}/${BRANCH}" - TRIGGER_TYPE="new-branch" - fi - fi - - mkdir -p build/bundles - cp .changelog build/bundles/changelog.txt - cp .release_date build/bundles/released.txt - cp README.md build/bundles/README.md - echo "::endgroup::" - - echo "Release Date: $(cat .release_date)" - echo "Revision: $(cat .ottdrev)" - echo "Version: $(cat .version)" - echo "Is tag: ${IS_TAG}" - echo "Folder on CDN: ${FOLDER}" - echo "Workflow trigger: ${TRIGGER_TYPE}" - - echo "version=$(cat .version)" >> $GITHUB_OUTPUT - echo "is_tag=${IS_TAG}" >> $GITHUB_OUTPUT - echo "folder=${FOLDER}" >> $GITHUB_OUTPUT - echo "trigger_type=${TRIGGER_TYPE}" >> $GITHUB_OUTPUT - env: - NIGHTLIES_BRANCH: master - FOLDER_RELEASES: openttd-releases - FOLDER_NIGHTLIES: openttd-nightlies - FOLDER_BRANCHES: openttd-branches - - - name: Remove VCS information - run: | - rm -rf .git - - - name: Create bundles - run: | - FOLDER_NAME=openttd-${{ steps.metadata.outputs.version }} - - # Rename the folder to openttd-NNN - mkdir ${FOLDER_NAME} - find . -maxdepth 1 -not -name . -not -name build -not -name ${FOLDER_NAME} -exec mv {} ${FOLDER_NAME}/ \; - - echo "::group::Create tarball (xz) bundle" - tar --xz -cvf build/bundles/${FOLDER_NAME}-source.tar.xz ${FOLDER_NAME} - echo "::endgroup::" - - # This tarball is only to be used within this workflow. - echo "::group::Create tarball (gz) bundle" - tar --gzip -cvf source.tar.gz ${FOLDER_NAME} - echo "::endgroup::" - - echo "::group::Create zip bundle" - zip -9 -r build/bundles/${FOLDER_NAME}-source.zip ${FOLDER_NAME} - echo "::endgroup::" - - - name: Store bundles - uses: actions/upload-artifact@v3 - with: - name: openttd-source - path: build/bundles/* - retention-days: 5 - - - name: Store source (for other jobs) - uses: actions/upload-artifact@v3 - with: - name: internal-source - path: source.tar.gz - retention-days: 1 + uses: ./.github/workflows/release-source.yml + secrets: inherit docs: name: Docs needs: source - runs-on: ubuntu-20.04 + uses: ./.github/workflows/release-docs.yml + secrets: inherit - steps: - - name: Download source - uses: actions/download-artifact@v3 - with: - name: internal-source - - - name: Unpack source - run: | - tar -xf source.tar.gz --strip-components=1 - - - name: Install dependencies - run: | - echo "::group::Update apt" - sudo apt-get update - echo "::endgroup::" - - echo "::group::Install dependencies" - sudo apt-get install -y --no-install-recommends \ - doxygen \ - # EOF - echo "::endgroup::" - env: - DEBIAN_FRONTEND: noninteractive - - - name: Build - run: | - mkdir -p ${GITHUB_WORKSPACE}/build - cd ${GITHUB_WORKSPACE}/build - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DOPTION_DOCS_ONLY=ON \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - cmake --build . --target docs - echo "::endgroup::" - - - name: Create bundles - run: | - BASENAME=openttd-${{ needs.source.outputs.version }} - - cd ${GITHUB_WORKSPACE}/build - - mv docs/source ${BASENAME}-docs - mv docs/ai-api ${BASENAME}-docs-ai - mv docs/gs-api ${BASENAME}-docs-gs - - mkdir -p bundles - - echo "::group::Create docs bundle" - tar --xz -cf bundles/${BASENAME}-docs.tar.xz ${BASENAME}-docs - echo "::endgroup::" - - echo "::group::Create AI API docs bundle" - tar --xz -cf bundles/${BASENAME}-docs-ai.tar.xz ${BASENAME}-docs-ai - echo "::endgroup::" - - echo "::group::Create GameScript API docs bundle" - tar --xz -cf bundles/${BASENAME}-docs-gs.tar.xz ${BASENAME}-docs-gs - echo "::endgroup::" - - - name: Store bundles - uses: actions/upload-artifact@v3 - with: - name: openttd-docs - path: build/bundles/*.tar.xz - retention-days: 5 + with: + version: ${{ needs.source.outputs.version }} linux: name: Linux (Generic) needs: source - runs-on: ubuntu-20.04 - container: - # manylinux2014 is based on CentOS 7, but already has a lot of things - # installed and preconfigured. It makes it easier to build OpenTTD. - image: quay.io/pypa/manylinux2014_x86_64 - - steps: - - name: Download source - uses: actions/download-artifact@v3 - with: - name: internal-source - - - name: Unpack source - run: | - tar -xf source.tar.gz --strip-components=1 - - - name: Install dependencies - run: | - echo "::group::Install dependencies" - yum install -y \ - fontconfig-devel \ - freetype-devel \ - libicu-devel \ - libpng-devel \ - libpng-devel \ - lzo-devel \ - SDL2-devel \ - wget \ - xz-devel \ - zlib-devel \ - # EOF - echo "::endgroup::" - - # The yum variant of fluidsynth depends on all possible audio drivers, - # like jack, ALSA, pulseaudio, etc. This is not really useful for us, - # as we route the output of fluidsynth back via our sound driver, and - # as such do not use these audio driver outputs at all. So instead, - # we compile fluidsynth ourselves, with as little dependencies as - # possible. This currently means it picks up SDL2, but this is fine, - # as we need SDL2 anyway. - echo "::group::Install fluidsynth" - wget https://github.com/FluidSynth/fluidsynth/archive/v2.1.6.tar.gz - tar xf v2.1.6.tar.gz - ( - cd fluidsynth-2.1.6 - mkdir build - cd build - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr - cmake --build . -j $(nproc) - cmake --install . - ) - echo "::endgroup::" - - - name: Install GCC problem matcher - uses: ammaraskar/gcc-problem-matcher@master - - - name: Build - run: | - mkdir -p build - cd build - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DOPTION_PACKAGE_DEPENDENCIES=ON \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - echo "Running on $(nproc) cores" - cmake --build . -j $(nproc) - echo "::endgroup::" - - - name: Create bundles - run: | - cd ${GITHUB_WORKSPACE}/build - echo "::group::Run CPack" - cpack - echo "::endgroup::" - - echo "::group::Cleanup" - # Remove the sha256 files CPack generates; we will do this ourself at - # the end of this workflow. - rm -f bundles/*.sha256 - echo "::endgroup::" - - - name: Store bundles - uses: actions/upload-artifact@v3 - with: - name: openttd-linux-generic - path: build/bundles - retention-days: 5 + uses: ./.github/workflows/release-linux.yml + secrets: inherit macos: name: MacOS needs: source - runs-on: macos-11 - env: - MACOSX_DEPLOYMENT_TARGET: 10.13 - - steps: - - name: Download source - uses: actions/download-artifact@v3 - with: - name: internal-source - - - name: Unpack source - run: | - tar -xf source.tar.gz --strip-components=1 - - - name: Install dependencies - env: - HOMEBREW_NO_AUTO_UPDATE: 1 - HOMEBREW_NO_INSTALL_CLEANUP: 1 - run: | - brew install pandoc - - - name: Prepare cache key - id: key - run: | - echo "image=$ImageOS-$ImageVersion" >> $GITHUB_OUTPUT - - - name: Enable vcpkg cache - uses: actions/cache@v3 - with: - path: /usr/local/share/vcpkg/installed - key: ${{ steps.key.outputs.image }}-vcpkg-release-0 # Increase the number whenever dependencies are modified - restore-keys: | - ${{ steps.key.outputs.image }}-vcpkg-release - ${{ steps.key.outputs.image }}-vcpkg-x64 - - - name: Prepare vcpkg - run: | - vcpkg install \ - liblzma:x64-osx \ - liblzma:arm64-osx \ - libpng:x64-osx \ - libpng:arm64-osx \ - lzo:x64-osx \ - lzo:arm64-osx \ - zlib:x64-osx \ - zlib:arm64-osx \ - # EOF - - - name: Install GCC problem matcher - uses: ammaraskar/gcc-problem-matcher@master - - - name: Build tools - run: | - mkdir build-host - cd build-host - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DOPTION_TOOLS_ONLY=ON \ - # EOF - echo "::endgroup::" - - echo "::group::Build tools" - echo "Running on $(sysctl -n hw.logicalcpu) cores" - cmake --build . -j $(sysctl -n hw.logicalcpu) --target tools - echo "::endgroup::" - - - name: Import code signing certificates - uses: Apple-Actions/import-codesign-certs@v1 - with: - # The certificates in a PKCS12 file encoded as a base64 string - p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} - # The password used to import the PKCS12 file. - p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} - # If this is run on a fork, there may not be a certificate set up - continue in this case - continue-on-error: true - - - name: Build arm64 - run: | - mkdir build-arm64 - cd build-arm64 - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -DCMAKE_OSX_ARCHITECTURES=arm64 \ - -DVCPKG_TARGET_TRIPLET=arm64-osx \ - -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ - -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - echo "Running on $(sysctl -n hw.logicalcpu) cores" - cmake --build . -j $(sysctl -n hw.logicalcpu) - echo "::endgroup::" - - - name: Build x64 - run: | - mkdir build-x64 - cd build-x64 - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -DCMAKE_OSX_ARCHITECTURES=x86_64 \ - -DVCPKG_TARGET_TRIPLET=x64-osx \ - -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ - -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DCPACK_BUNDLE_APPLE_CERT_APP=${{ secrets.APPLE_DEVELOPER_CERTIFICATE_ID }} \ - "-DCPACK_BUNDLE_APPLE_CODESIGN_PARAMETER=--deep -f --options runtime" \ - -DAPPLE_UNIVERSAL_PACKAGE=1 \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - echo "Running on $(sysctl -n hw.logicalcpu) cores" - cmake --build . -j $(sysctl -n hw.logicalcpu) - echo "::endgroup::" - - - name: Create bundles - run: | - cd build-x64 - - echo "::group::Create universal binary" - # Combine the `openttd` binaries from each build into a single file - lipo -create -output openttd-universal ../build-*/openttd - mv openttd-universal openttd - echo "::endgroup::" - - echo "::group::Run CPack" - cpack - echo "::endgroup::" - - echo "::group::Cleanup" - # Remove the sha256 files CPack generates; we will do this ourself at - # the end of this workflow. - rm -f bundles/*.sha256 - echo "::endgroup::" - - - name: Install gon - env: - HOMEBREW_NO_AUTO_UPDATE: 1 - HOMEBREW_NO_INSTALL_CLEANUP: 1 - run: | - brew tap mitchellh/gon - brew install mitchellh/gon/gon - - - name: Notarize - env: - AC_USERNAME: ${{ secrets.APPLE_DEVELOPER_APP_USERNAME }} - AC_PASSWORD: ${{ secrets.APPLE_DEVELOPER_APP_PASSWORD }} - run: | - cd build-x64 - ../os/macosx/notarize.sh - - - name: Build zip - run: | - cd build-x64 - - pushd _CPack_Packages/*/Bundle/openttd-*/ - - # Remove the Applications symlink from the staging folder - rm -f Applications - - # Remove the original dmg built by CPack to avoid a conflict when resolving - # the zip_filename variable below - rm -f ../*.dmg - - zip_filename=(../openttd-*) - - # Package up the existing, notarised .app into a zip file - zip -r -9 ${zip_filename}.zip OpenTTD.app - - popd - - # Now move it into place to be uploaded - mv _CPack_Packages/*/Bundle/openttd-*.zip bundles/ - - - name: Store bundles - uses: actions/upload-artifact@v3 - with: - name: openttd-macos-universal - path: build-x64/bundles - retention-days: 5 + uses: ./.github/workflows/release-macos.yml + secrets: inherit windows: name: Windows needs: source - strategy: - fail-fast: false - matrix: - include: - - arch: x86 - host: x86 - - arch: x64 - host: x64 - - arch: arm64 - host: x64_arm64 + uses: ./.github/workflows/release-windows.yml + secrets: inherit - runs-on: windows-latest + with: + is_tag: ${{ needs.source.outputs.is_tag }} - steps: - - name: Download source - uses: actions/download-artifact@v3 - with: - name: internal-source - - - name: Unpack source - shell: bash - run: | - tar -xf source.tar.gz --strip-components=1 - - - name: Install dependencies - shell: bash - run: | - choco install pandoc - - - name: Prepare cache key - id: key - shell: powershell - run: | - # Work around caching failure with GNU tar - New-Item -Type Junction -Path vcpkg -Target c:\vcpkg - - Write-Output "image=$env:ImageOS-$env:ImageVersion" >> $env:GITHUB_OUTPUT - - - name: Enable vcpkg cache - uses: actions/cache@v3 - with: - path: vcpkg/installed - key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified - restore-keys: | - ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }} - - - name: Prepare vcpkg - shell: bash - run: | - vcpkg install --triplet=${{ matrix.arch }}-windows-static \ - liblzma \ - libpng \ - lzo \ - zlib \ - # EOF - - - name: Install MSVC problem matcher - uses: ammaraskar/msvc-problem-matcher@master - - - name: Configure developer command prompt for tools - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x64 - - - name: Build tools - shell: bash - run: | - mkdir build-host - cd build-host - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -GNinja \ - -DOPTION_TOOLS_ONLY=ON \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - cmake --build . --target tools - echo "::endgroup::" - - - name: Configure developer command prompt for ${{ matrix.arch }} - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: ${{ matrix.host }} - - - name: Import code signing certificate - shell: powershell - # If this is run on a fork, there may not be a certificate set up - continue in this case - continue-on-error: true - run: | - $tempFile = [System.IO.Path]::GetTempFileName() - $bytes = [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_P12) - [IO.File]::WriteAllBytes($tempFile, $bytes) - $pwd = ConvertTo-SecureString $env:WINDOWS_CERTIFICATE_PASSWORD -AsPlainText -Force - Import-PfxCertificate -FilePath $tempFile -CertStoreLocation Cert:\CurrentUser\My -Password $pwd - Remove-Item $tempFile - env: - WINDOWS_CERTIFICATE_P12: ${{ secrets.WINDOWS_CERTIFICATE_P12 }} - WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} - - - name: Build (with installer) - if: needs.source.outputs.is_tag == 'true' - shell: bash - run: | - mkdir build - cd build - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -GNinja \ - -DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \ - -DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \ - -DOPTION_USE_NSIS=ON \ - -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - cmake --build . - echo "::endgroup::" - env: - WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} - - - name: Build (without installer) - if: needs.source.outputs.is_tag != 'true' - shell: bash - run: | - mkdir build - cd build - - echo "::group::CMake" - cmake ${GITHUB_WORKSPACE} \ - -GNinja \ - -DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \ - -DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \ - -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \ - # EOF - echo "::endgroup::" - - echo "::group::Build" - cmake --build . - echo "::endgroup::" - env: - WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} - - - name: Create bundles - shell: bash - run: | - cd ${GITHUB_WORKSPACE}/build - echo "::group::Run CPack" - cpack - echo "::endgroup::" - - echo "::group::Prepare PDB to be bundled" - PDB=$(ls bundles/*.zip | cut -d/ -f2 | sed 's/.zip$/.pdb/') - cp openttd.pdb bundles/${PDB} - xz -9 bundles/${PDB} - echo "::endgroup::" - - echo "::group::Cleanup" - # Remove the sha256 files CPack generates; we will do this ourself at - # the end of this workflow. - rm -f bundles/*.sha256 - echo "::endgroup::" - - - name: Sign installer - if: needs.source.outputs.is_tag == 'true' - shell: bash - # If this is run on a fork, there may not be a certificate set up - continue in this case - continue-on-error: true - run: | - cd ${GITHUB_WORKSPACE}/build/bundles - ../../os/windows/sign.bat *.exe "${WINDOWS_CERTIFICATE_COMMON_NAME}" - env: - WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} - - - name: Store bundles - uses: actions/upload-artifact@v3 - with: - name: openttd-windows-${{ matrix.arch }} - path: build/bundles - retention-days: 5 - - windows-appx: + windows-store: name: Windows Store needs: - source - windows if: needs.source.outputs.is_tag == 'true' - runs-on: windows-latest - steps: - - name: Download source - uses: actions/download-artifact@v3 - with: - name: internal-source + uses: ./.github/workflows/release-windows-store.yml + secrets: inherit - - name: Unpack source - shell: bash - run: | - tar -xf source.tar.gz --strip-components=1 - - - name: Download x86 build - uses: actions/download-artifact@v3 - with: - name: openttd-windows-x86 - - - name: Download x64 build - uses: actions/download-artifact@v3 - with: - name: openttd-windows-x64 - - - name: Download arm64 build - uses: actions/download-artifact@v3 - with: - name: openttd-windows-arm64 - - - name: Unpack builds - shell: bash - run: | - mkdir builds - cd builds - - function extract { - mkdir $1 - - # Extract the zip version of the release - unzip ../openttd-*-windows-$2.zip -d $1 - - # Remove the extraneous directory - mv $1/openttd-*-windows-$2/* $1/ - rmdir $1/openttd-*-windows-$2 - - # Move the openttd.exe to the '{arch}-binaries' folder - mkdir $1-binaries - mv $1/openttd.exe $1-binaries/ - } - - extract x86 win32 - extract x64 win64 - extract arm64 arm64 - - # Use the "x86" folder as the source of the common binaries (lang files, etc) and remove the others - mv x86 common-binaries - rm -rf x64 arm64 - - - name: Install OpenGFX - shell: bash - run: | - mkdir -p builds/common-binaries/baseset - cd builds/common-binaries/baseset - - echo "::group::Download OpenGFX" - curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip - echo "::endgroup::" - - echo "::group::Unpack OpenGFX" - unzip opengfx-all.zip - tar xf opengfx-*.tar - echo "::endgroup::" - - rm -f opengfx-all.zip opengfx-*.tar - - - name: Install OpenMSX - shell: bash - run: | - mkdir -p builds/common-binaries/baseset - cd builds/common-binaries/baseset - - echo "::group::Download OpenMSX" - curl -L https://cdn.openttd.org/openmsx-releases/0.4.2/openmsx-0.4.2-all.zip -o openmsx-all.zip - echo "::endgroup::" - - echo "::group::Unpack OpenGFX" - unzip openmsx-all.zip - tar xf openmsx-*.tar - echo "::endgroup::" - - rm -f openmsx-all.zip openmsx-*.tar - - - name: Install OpenSFX - shell: bash - run: | - mkdir -p builds/common-binaries/baseset/opensfx - cd builds/common-binaries/baseset/opensfx - - echo "::group::Download OpenSFX" - curl -L https://cdn.openttd.org/opensfx-releases/1.0.3/opensfx-1.0.3-all.zip -o opensfx-all.zip - echo "::endgroup::" - - echo "::group::Unpack OpenSFX" - unzip opensfx-all.zip - tar xf opensfx-*.tar - echo "::endgroup::" - - rm -f opensfx-all.zip opensfx-*.tar - - - name: Generate signing certificate - shell: cmd - run: | - cd builds - - REM We need to provide a signed .appx to the Windows Store, so generate a certificate with password 'password' - call ..\os\windows\winstore\generate-key.bat "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" password cert.pfx - - - name: Generate assets - shell: cmd - run: | - cd os\windows\winstore - call generate-assets.bat - - - name: Prepare manifests - shell: cmd - run: | - cd builds - mkdir manifests - - REM Set the version environment variable - call ..\os\windows\winstore\set-version.bat x86-binaries\openttd.exe - - call ..\os\windows\winstore\prepare-manifests.bat manifests "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" "57420OpenTTDDevelopers.OpenTTDofficial" - - - name: Prepare binaries - shell: bash - run: | - cd builds - - # Copy the Windows Store assets - mkdir common-binaries/Assets - cp -R ../os/windows/winstore/assets-common/* common-binaries/Assets/ - - mkdir Assets - cp -R ../os/windows/winstore/assets/* Assets/ - - cp manifests/*.xml . - - - name: Build - shell: cmd - run: | - REM Add the Windows SDK tools to the PATH - - echo|set /p="SET VS_INSTALLDIR=" > _vspath.bat - vswhere -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath >> _vspath.bat - call _vspath.bat - call "%VS_INSTALLDIR%\Common7\Tools\VsDevCmd.bat" - - REM Set the version environment variable - call os\windows\winstore\set-version.bat builds\x86-binaries\openttd.exe - - cd builds - mkdir output - - REM Build and sign the package - makeappx build /v /f PackagingLayout.xml /op output\ /bv %OTTD_VERSION% /pv %OTTD_VERSION% /ca - SignTool sign /fd sha256 /a /f cert.pfx /p password "output\OpenTTD.appxbundle" - - - name: Store appx - uses: actions/upload-artifact@v3 - with: - name: openttd-windows-store - path: | - builds/output/OpenTTD.appxbundle - builds/cert.pfx - retention-days: 5 - - upload: + upload-aws: name: Upload (AWS) needs: - source @@ -937,55 +75,13 @@ jobs: - macos - windows - # The 'linux' job can be skipped if it is a nightly. That normally causes - # this job to be skipped too, unless we have this length boy :) - # "always()" is important here, it is the keyword to use to stop skipping - # this job if any dependency is skipped. It looks a bit silly, but it is - # how GitHub Actions work ;) - if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && needs.linux.result == 'success' && needs.macos.result == 'success' && needs.windows.result == 'success' + uses: ./.github/workflows/upload-aws.yml + secrets: inherit - runs-on: ubuntu-20.04 - - steps: - - name: Download all bundles - uses: actions/download-artifact@v3 - - - name: Calculate checksums - run: | - echo "::group::Move bundles to a single folder" - mkdir bundles - mv openttd-*/* bundles/ - cd bundles - echo "::group::Build" - - for i in $(ls openttd-*); do - echo "::group::Calculating checksums for ${i}" - openssl dgst -r -md5 -hex $i > $i.md5sum - openssl dgst -r -sha1 -hex $i > $i.sha1sum - openssl dgst -r -sha256 -hex $i > $i.sha256sum - echo "::endgroup::" - done - - - name: Upload bundles to AWS - run: | - aws s3 cp --recursive --only-show-errors bundles/ s3://${{ secrets.CDN_S3_BUCKET }}/${{ needs.source.outputs.folder }}/${{ needs.source.outputs.version }}/ - - # We do not invalidate the CloudFront distribution here. The trigger - # for "New OpenTTD release" first updated the manifest files and - # creates an index.html. We invalidate after that, so everything - # becomes visible at once. - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }} - - - name: Trigger 'New OpenTTD release' - uses: peter-evans/repository-dispatch@v2 - with: - token: ${{ secrets.DEPLOYMENT_TOKEN }} - repository: OpenTTD/workflows - event-type: ${{ needs.source.outputs.trigger_type }} - client-payload: '{"version": "${{ needs.source.outputs.version }}", "folder": "${{ needs.source.outputs.folder }}"}' + with: + version: ${{ needs.source.outputs.version }} + folder: ${{ needs.source.outputs.folder }} + trigger_type: ${{ needs.source.outputs.trigger_type }} upload-steam: name: Upload (Steam) @@ -997,69 +93,9 @@ jobs: if: needs.source.outputs.trigger_type == 'new-master' || needs.source.outputs.trigger_type == 'new-tag' - runs-on: ubuntu-20.04 + uses: ./.github/workflows/upload-steam.yml + secrets: inherit - steps: - - name: Download all bundles - uses: actions/download-artifact@v3 - - - name: Setup steamcmd - uses: CyberAndrii/setup-steamcmd@v1 - - - name: Generate Steam auth code - id: steam-totp - uses: CyberAndrii/steam-totp@v1 - with: - shared_secret: ${{ secrets.STEAM_SHARED_SECRET }} - - - name: Upload to Steam - run: | - echo "::group::Extracting source" - mkdir source - ( - cd source - tar -xf ../internal-source/source.tar.gz --strip-components=1 - ) - echo "::endgroup::" - - mkdir steam - ( - cd steam - - echo "::group::Prepare Win32" - unzip ../openttd-windows-x86/openttd-*-windows-win32.zip - mv openttd-*-windows-win32 steam-win32 - echo "::endgroup::" - - echo "::group::Prepare Win64" - unzip ../openttd-windows-x64/openttd-*-windows-win64.zip - mv openttd-*-windows-win64 steam-win64 - echo "::endgroup::" - - echo "::group::Prepare macOS" - mkdir steam-macos - ( - cd steam-macos - unzip ../../openttd-macos-universal/openttd-*-macos-universal.zip - ) - echo "::endgroup::" - - echo "::group::Prepare Linux" - tar xvf ../openttd-linux-generic/openttd-*-linux-generic-amd64.tar.xz - mv openttd-*-linux-generic-amd64 steam-linux - echo "::endgroup::" - - echo "::group::Preparing build file" - if [ "${{ needs.source.outputs.trigger_type }}" = "new-tag" ]; then - BRANCH="testing" - else - BRANCH="nightly" - fi - cat ../source/os/steam/release.vdf | sed 's/@@DESCRIPTION@@/openttd-${{ needs.source.outputs.version }}/;s/@@BRANCH@@/'${BRANCH}'/' > release.vdf - cat release.vdf - echo "::endgroup::" - - echo "::group::Upload to Steam" - steamcmd +login ${{ secrets.STEAM_USERNAME }} ${{ secrets.STEAM_PASSWORD }} ${{ steps.steam-totp.outputs.code }} +run_app_build $(pwd)/release.vdf +quit - echo "::endgroup::" - ) + with: + version: ${{ needs.source.outputs.version }} + trigger_type: ${{ needs.source.outputs.trigger_type }} diff --git a/.github/workflows/upload-aws.yml b/.github/workflows/upload-aws.yml new file mode 100644 index 0000000000..1840a4341e --- /dev/null +++ b/.github/workflows/upload-aws.yml @@ -0,0 +1,61 @@ +name: Upload (AWS) + +on: + workflow_call: + inputs: + version: + required: true + type: string + folder: + required: true + type: string + trigger_type: + required: true + type: string + +jobs: + upload: + name: Upload (AWS) + + runs-on: ubuntu-20.04 + + steps: + - name: Download all bundles + uses: actions/download-artifact@v3 + + - name: Calculate checksums + run: | + echo "::group::Move bundles to a single folder" + mkdir bundles + mv openttd-*/* bundles/ + cd bundles + echo "::group::Build" + + for i in $(ls openttd-*); do + echo "::group::Calculating checksums for ${i}" + openssl dgst -r -md5 -hex $i > $i.md5sum + openssl dgst -r -sha1 -hex $i > $i.sha1sum + openssl dgst -r -sha256 -hex $i > $i.sha256sum + echo "::endgroup::" + done + + - name: Upload bundles to AWS + run: | + aws s3 cp --recursive --only-show-errors bundles/ s3://${{ secrets.CDN_S3_BUCKET }}/${{ inputs.folder }}/${{ inputs.version }}/ + + # We do not invalidate the CloudFront distribution here. The trigger + # for "New OpenTTD release" first updated the manifest files and + # creates an index.html. We invalidate after that, so everything + # becomes visible at once. + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }} + + - name: Trigger 'New OpenTTD release' + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.DEPLOYMENT_TOKEN }} + repository: OpenTTD/workflows + event-type: ${{ inputs.trigger_type }} + client-payload: '{"version": "${{ inputs.version }}", "folder": "${{ inputs.folder }}"}' diff --git a/.github/workflows/upload-steam.yml b/.github/workflows/upload-steam.yml new file mode 100644 index 0000000000..cd646dd81c --- /dev/null +++ b/.github/workflows/upload-steam.yml @@ -0,0 +1,82 @@ +name: Upload (Steam) + +on: + workflow_call: + inputs: + version: + required: true + type: string + trigger_type: + required: true + type: string + +jobs: + upload: + name: Upload (Steam) + + runs-on: ubuntu-20.04 + + steps: + - name: Download all bundles + uses: actions/download-artifact@v3 + + - name: Setup steamcmd + uses: CyberAndrii/setup-steamcmd@v1 + + - name: Generate Steam auth code + id: steam-totp + uses: CyberAndrii/steam-totp@v1 + with: + shared_secret: ${{ secrets.STEAM_SHARED_SECRET }} + + - name: Upload to Steam + run: | + echo "::group::Extracting source" + mkdir source + ( + cd source + tar -xf ../internal-source/source.tar.gz --strip-components=1 + ) + echo "::endgroup::" + + mkdir steam + ( + cd steam + + echo "::group::Prepare Win32" + unzip ../openttd-windows-x86/openttd-*-windows-win32.zip + mv openttd-*-windows-win32 steam-win32 + echo "::endgroup::" + + echo "::group::Prepare Win64" + unzip ../openttd-windows-x64/openttd-*-windows-win64.zip + mv openttd-*-windows-win64 steam-win64 + echo "::endgroup::" + + echo "::group::Prepare macOS" + mkdir steam-macos + ( + cd steam-macos + unzip ../../openttd-macos-universal/openttd-*-macos-universal.zip + ) + echo "::endgroup::" + + echo "::group::Prepare Linux" + tar xvf ../openttd-linux-generic/openttd-*-linux-generic-amd64.tar.xz + mv openttd-*-linux-generic-amd64 steam-linux + echo "::endgroup::" + + echo "::group::Preparing build file" + if [ "${{ inputs.trigger_type }}" = "new-tag" ]; then + BRANCH="testing" + else + BRANCH="nightly" + fi + cat ../source/os/steam/release.vdf | sed 's/@@DESCRIPTION@@/openttd-${{ inputs.version }}/;s/@@BRANCH@@/'${BRANCH}'/' > release.vdf + cat release.vdf + echo "::endgroup::" + + echo "::group::Upload to Steam" + steamcmd +login ${{ secrets.STEAM_USERNAME }} ${{ secrets.STEAM_PASSWORD }} ${{ steps.steam-totp.outputs.code }} +run_app_build $(pwd)/release.vdf +quit + echo "::endgroup::" + ) From 146bd74077d08a97609533c4071d80b5108c4763 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 28 Jan 2023 14:13:21 +0100 Subject: [PATCH 05/10] Change: [Actions] release Windows Store files to CDN Currently they had a name that the rest of our system cannot deal with correctly. "cert.pfx" is also not very descriptive from a system as a whole. As such, we now name it like any other file, so it can be published safely to the CDN. --- .github/workflows/release-windows-store.yml | 16 ++++++++++++---- .github/workflows/release.yml | 8 ++++++++ .github/workflows/upload-aws.yml | 19 +++++++++++++++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release-windows-store.yml b/.github/workflows/release-windows-store.yml index c4753b5ff0..97b4398b36 100644 --- a/.github/workflows/release-windows-store.yml +++ b/.github/workflows/release-windows-store.yml @@ -2,6 +2,10 @@ name: Release (Windows Store) on: workflow_call: + inputs: + version: + required: true + type: string jobs: windows-store: @@ -174,11 +178,15 @@ jobs: makeappx build /v /f PackagingLayout.xml /op output\ /bv %OTTD_VERSION% /pv %OTTD_VERSION% /ca SignTool sign /fd sha256 /a /f cert.pfx /p password "output\OpenTTD.appxbundle" - - name: Store appx + REM Move resulting files to bundles folder + mkdir bundles + mkdir bundles\internal + move cert.pfx bundles\internal\openttd-${{ inputs.version }}-windows-store.pfx + move output\OpenTTD.appxbundle bundles\internal\openttd-${{ inputs.version }}-windows-store.appxbundle + + - name: Store bundles uses: actions/upload-artifact@v3 with: name: openttd-windows-store - path: | - builds/output/OpenTTD.appxbundle - builds/cert.pfx + path: builds/bundles retention-days: 5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9526334456..5dea7c9f40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,6 +66,9 @@ jobs: uses: ./.github/workflows/release-windows-store.yml secrets: inherit + with: + version: ${{ needs.source.outputs.version }} + upload-aws: name: Upload (AWS) needs: @@ -74,6 +77,11 @@ jobs: - linux - macos - windows + - windows-store + + # As windows-store is condition, we need to check ourselves if we need to run. + # The always() makes sure the rest is always evaluated. + if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && needs.linux.result == 'success' && needs.macos.result == 'success' && needs.windows.result == 'success' && (needs.windows-store.result == 'success' || needs.windows-store.result == 'skipped') uses: ./.github/workflows/upload-aws.yml secrets: inherit diff --git a/.github/workflows/upload-aws.yml b/.github/workflows/upload-aws.yml index 1840a4341e..72319ad5ab 100644 --- a/.github/workflows/upload-aws.yml +++ b/.github/workflows/upload-aws.yml @@ -28,9 +28,9 @@ jobs: echo "::group::Move bundles to a single folder" mkdir bundles mv openttd-*/* bundles/ - cd bundles - echo "::group::Build" + echo "::endgroup::" + cd bundles for i in $(ls openttd-*); do echo "::group::Calculating checksums for ${i}" openssl dgst -r -md5 -hex $i > $i.md5sum @@ -39,6 +39,21 @@ jobs: echo "::endgroup::" done + # Some targets generate files that are meant for our-eyes-only. + # They are stored in the "internal" folder, and contains bundles + # for targets like Windows Store. No user has a benefit of knowing + # they exist, hence: internal. + if [ -e internal ]; then + cd internal + for i in $(ls openttd-*); do + echo "::group::Calculating checksums for ${i}" + openssl dgst -r -md5 -hex $i > $i.md5sum + openssl dgst -r -sha1 -hex $i > $i.sha1sum + openssl dgst -r -sha256 -hex $i > $i.sha256sum + echo "::endgroup::" + done + fi + - name: Upload bundles to AWS run: | aws s3 cp --recursive --only-show-errors bundles/ s3://${{ secrets.CDN_S3_BUCKET }}/${{ inputs.folder }}/${{ inputs.version }}/ From be0d65d9781c561b3d5b7c84eb4d94b75d45ad88 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 28 Jan 2023 16:00:52 +0100 Subject: [PATCH 06/10] Add: [Actions] upload releases to GOG automatically --- .github/workflows/release.yml | 16 ++++ .github/workflows/upload-gog.yml | 124 +++++++++++++++++++++++++++++++ os/gog/linux.json | 64 ++++++++++++++++ os/gog/macos.json | 65 ++++++++++++++++ os/gog/windows.json | 94 +++++++++++++++++++++++ 5 files changed, 363 insertions(+) create mode 100644 .github/workflows/upload-gog.yml create mode 100755 os/gog/linux.json create mode 100755 os/gog/macos.json create mode 100755 os/gog/windows.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5dea7c9f40..bc0225153f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -107,3 +107,19 @@ jobs: with: version: ${{ needs.source.outputs.version }} trigger_type: ${{ needs.source.outputs.trigger_type }} + + upload-gog: + name: Upload (GOG) + needs: + - source + - linux + - macos + - windows + + if: needs.source.outputs.trigger_type == 'new-tag' + + uses: ./.github/workflows/upload-gog.yml + secrets: inherit + + with: + version: ${{ needs.source.outputs.version }} diff --git a/.github/workflows/upload-gog.yml b/.github/workflows/upload-gog.yml new file mode 100644 index 0000000000..b4a591fdcc --- /dev/null +++ b/.github/workflows/upload-gog.yml @@ -0,0 +1,124 @@ +name: Upload (GOG) + +on: + workflow_call: + inputs: + version: + required: true + type: string + +jobs: + upload: + name: Upload (GOG) + + runs-on: ubuntu-20.04 + + steps: + - name: Download all bundles + uses: actions/download-artifact@v3 + + - name: Install GOG Galaxy Build Creator + run: | + wget https://cdn.gog.com/open/galaxy/pipeline/build_creator/gnu-linux/GOGGalaxyBuildCreator-1.4.0.AppImage + 7z x GOGGalaxyBuildCreator-1.4.0.AppImage + chmod +x ./app/GOGGalaxyPipelineBuilder + + - name: Install OpenGFX + shell: bash + run: | + mkdir -p gog/opengfx/baseset + cd gog/opengfx/baseset + + echo "::group::Download OpenGFX" + curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenGFX" + unzip opengfx-all.zip + echo "::endgroup::" + + rm -f opengfx-all.zip + + - name: Install OpenMSX + shell: bash + run: | + mkdir -p gog/openmsx/baseset + cd gog/openmsx/baseset + + echo "::group::Download OpenMSX" + curl -L https://cdn.openttd.org/openmsx-releases/0.4.2/openmsx-0.4.2-all.zip -o openmsx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenGFX" + unzip openmsx-all.zip + tar xf openmsx-*.tar + echo "::endgroup::" + + rm -f openmsx-all.zip openmsx-*.tar + + - name: Install OpenSFX + shell: bash + run: | + mkdir -p gog/opensfx/baseset + cd gog/opensfx/baseset + + echo "::group::Download OpenSFX" + curl -L https://cdn.openttd.org/opensfx-releases/1.0.3/opensfx-1.0.3-all.zip -o opensfx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenSFX" + unzip opensfx-all.zip + tar xf opensfx-*.tar + echo "::endgroup::" + + rm -f opensfx-all.zip opensfx-*.tar + + - name: Upload to GOG + run: | + echo "::group::Extracting source" + mkdir source + ( + cd source + tar -xf ../internal-source/source.tar.gz --strip-components=1 + ) + echo "::endgroup::" + + ( + cd gog + + echo "::group::Prepare Win32" + unzip ../openttd-windows-x86/openttd-*-windows-win32.zip + mv openttd-*-windows-win32 win32 + echo "::endgroup::" + + echo "::group::Prepare Win64" + unzip ../openttd-windows-x64/openttd-*-windows-win64.zip + mv openttd-*-windows-win64 win64 + echo "::endgroup::" + + echo "::group::Prepare macOS" + mkdir macos + ( + cd macos + unzip ../../openttd-macos-universal/openttd-*-macos-universal.zip + ) + echo "::endgroup::" + + echo "::group::Prepare Linux" + tar xvf ../openttd-linux-generic/openttd-*-linux-generic-amd64.tar.xz + mv openttd-*-linux-generic-amd64 linux + echo "::endgroup::" + + echo "::group::Preparing build files" + cp ../source/os/gog/*.json . + for json in $(ls *.json); do + sed -i 's/VERSION/${{ inputs.version }}/g;s/CLIENT_ID/${{ secrets.GOG_CLIENT_ID }}/g;s/CLIENT_SECRET/${{ secrets.GOG_CLIENT_SECRET }}/g' ${json} + done + echo "::endgroup::" + + echo "::group::Upload to GOG" + ../app/GOGGalaxyPipelineBuilder build-game --username "${{ secrets.GOG_USERNAME }}" --password "${{ secrets.GOG_PASSWORD }}" --branch Testing windows.json + ../app/GOGGalaxyPipelineBuilder build-game --username "${{ secrets.GOG_USERNAME }}" --password "${{ secrets.GOG_PASSWORD }}" --branch Testing macos.json + ../app/GOGGalaxyPipelineBuilder build-game --username "${{ secrets.GOG_USERNAME }}" --password "${{ secrets.GOG_PASSWORD }}" --branch Testing linux.json + echo "::endgroup::" + ) diff --git a/os/gog/linux.json b/os/gog/linux.json new file mode 100755 index 0000000000..47e80fd255 --- /dev/null +++ b/os/gog/linux.json @@ -0,0 +1,64 @@ +{ + "project": { + "baseProductId": "1293297882", + "clientId": "CLIENT_ID", + "clientSecret": "CLIENT_SECRET", + "version": "VERSION", + "installDirectory": "OpenTTD", + "name": "OpenTTD", + "platform": "gnu-linux", + "tags": [ + "editor_v_1_4_0" + ], + "languageMode": "together", + "products": [ + { + "name": "OpenTTD", + "productId": "1293297882", + "depots": [ + { + "name": "Linux", + "folder": "linux", + "languages": [ + "en-US" + ] + }, + { + "name": "OpenGFX", + "folder": "opengfx", + "languages": [ + "en-US" + ] + }, + { + "name": "OpenMSX", + "folder": "openmsx", + "languages": [ + "en-US" + ] + }, + { + "name": "OpenSFX", + "folder": "opensfx", + "languages": [ + "en-US" + ] + } + ], + "tasks": [ + { + "type": "FileTask", + "name": "OpenTTD", + "languages": [ + "en-US" + ], + "category": "game", + "path": "openttd", + "isPrimary": true + } + ], + "supportDepots": [] + } + ] + } +} diff --git a/os/gog/macos.json b/os/gog/macos.json new file mode 100755 index 0000000000..8ce9a02be7 --- /dev/null +++ b/os/gog/macos.json @@ -0,0 +1,65 @@ +{ + "project": { + "baseProductId": "1293297882", + "clientId": "CLIENT_ID", + "clientSecret": "CLIENT_SECRET", + "version": "VERSION", + "installDirectory": "OpenTTD", + "name": "OpenTTD", + "platform": "osx", + "tags": [ + "editor_v_1_4_0" + ], + "languageMode": "together", + "products": [ + { + "name": "OpenTTD", + "productId": "1293297882", + "depots": [ + { + "name": "MacOS", + "folder": "macos", + "languages": [ + "en-US" + ] + }, + { + "name": "OpenGFX", + "folder": "opengfx", + "languages": [ + "en-US" + ] + }, + { + "name": "OpenMSX", + "folder": "openmsx", + "languages": [ + "en-US" + ] + }, + { + "name": "OpenSFX", + "folder": "opensfx", + "languages": [ + "en-US" + ] + } + ], + "tasks": [ + { + "type": "FileTask", + "name": "OpenTTD", + "languages": [ + "en-US" + ], + "category": "game", + "path": "OpenTTD.app/Contents/MacOS/openttd", + "isPrimary": true + } + ], + "supportDepots": [] + } + ] + } +} + diff --git a/os/gog/windows.json b/os/gog/windows.json new file mode 100755 index 0000000000..8582abb060 --- /dev/null +++ b/os/gog/windows.json @@ -0,0 +1,94 @@ +{ + "project": { + "baseProductId": "1293297882", + "clientId": "CLIENT_ID", + "clientSecret": "CLIENT_SECRET", + "version": "VERSION", + "installDirectory": "OpenTTD", + "name": "OpenTTD", + "platform": "windows", + "tags": [ + "editor_v_1_4_0" + ], + "languageMode": "together", + "products": [ + { + "name": "OpenTTD", + "productId": "1293297882", + "depots": [ + { + "name": "Win32", + "folder": "win32", + "languages": [ + "en-US" + ], + "osBitness": [ + "32" + ] + }, + { + "name": "Win64", + "folder": "win64", + "languages": [ + "en-US" + ], + "osBitness": [ + "64" + ] + }, + { + "name": "OpenGFX", + "folder": "opengfx", + "languages": [ + "en-US" + ], + "osBitness": [ + "32", + "64" + ] + }, + { + "name": "OpenMSX", + "folder": "openmsx", + "languages": [ + "en-US" + ], + "osBitness": [ + "32", + "64" + ] + }, + { + "name": "OpenSFX", + "folder": "opensfx", + "languages": [ + "en-US" + ], + "osBitness": [ + "32", + "64" + ] + } + ], + "tasks": [ + { + "type": "FileTask", + "name": "OpenTTD", + "languages": [ + "en-US" + ], + "category": "game", + "path": "openttd.exe", + "isPrimary": true, + "osBitness": [ + "32", + "64" + ] + } + ], + "supportDepots": [] + } + ], + "scriptInterpreter": true + } +} From 1951af07c0786551db290c46cc7580a0dd371760 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 28 Jan 2023 19:07:51 +0100 Subject: [PATCH 07/10] Codechange: do not hide parameters with local variables --- src/3rdparty/squirrel/squirrel/sqstate.cpp | 4 ++-- src/3rdparty/squirrel/squirrel/sqvm.cpp | 10 +++++----- src/group_cmd.cpp | 6 +++--- src/saveload/saveload.cpp | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/3rdparty/squirrel/squirrel/sqstate.cpp b/src/3rdparty/squirrel/squirrel/sqstate.cpp index 6c1c9ec2fb..ce2fdfa55d 100644 --- a/src/3rdparty/squirrel/squirrel/sqstate.cpp +++ b/src/3rdparty/squirrel/squirrel/sqstate.cpp @@ -246,9 +246,9 @@ void SQSharedState::DelayFinalFree(SQCollectable *collectable) if (!this->_collectable_free_processing) { this->_collectable_free_processing = true; while (!this->_collectable_free_queue.empty()) { - SQCollectable *collectable = this->_collectable_free_queue.back(); + SQCollectable *collectable_to_free = this->_collectable_free_queue.back(); this->_collectable_free_queue.pop_back(); - collectable->FinalFree(); + collectable_to_free->FinalFree(); } this->_collectable_free_processing = false; } diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index fd41212dfb..e643e25984 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -1064,11 +1064,11 @@ exception_trap: if(traps) { do { if(ci->_etraps > 0) { - SQExceptionTrap &et = _etraps.top(); - ci->_ip = et._ip; - _top = et._stacksize; - _stackbase = et._stackbase; - _stack._vals[_stackbase+et._extarget] = currerror; + SQExceptionTrap &trap = _etraps.top(); + ci->_ip = trap._ip; + _top = trap._stacksize; + _stackbase = trap._stackbase; + _stack._vals[_stackbase+trap._extarget] = currerror; _etraps.pop_back(); traps--; ci->_etraps--; CLEARSTACK(last_top); goto exception_restore; diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index dd8033d4e0..00c7c82b06 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -528,10 +528,10 @@ std::tuple CmdAddVehicleGroup(DoCommandFlag flags, GroupID if (new_g == NEW_GROUP) { /* Create new group. */ - auto [ret, group_id] = CmdCreateGroup(flags, v->type, INVALID_GROUP); - if (ret.Failed()) return { ret, group_id }; + auto [ret, new_group_id] = CmdCreateGroup(flags, v->type, INVALID_GROUP); + if (ret.Failed()) return { ret, new_group_id }; - new_g = group_id; + new_g = new_group_id; } if (flags & DC_EXEC) { diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 04e8113820..ebb8e10223 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1923,26 +1923,26 @@ std::vector SlTableHeader(const SaveLoadTable &slt) Debug(sl, _sl.action == SLA_LOAD ? 2 : 6, "Field '{}' of type 0x{:02x} not found, skipping", key, type); std::shared_ptr handler = nullptr; - SaveLoadType slt; + SaveLoadType saveload_type; switch (type & SLE_FILE_TYPE_MASK) { case SLE_FILE_STRING: /* Strings are always marked with SLE_FILE_HAS_LENGTH_FIELD, as they are a list of chars. */ - slt = SL_STR; + saveload_type = SL_STR; break; case SLE_FILE_STRUCT: /* Structs are always marked with SLE_FILE_HAS_LENGTH_FIELD as SL_STRUCT is seen as a list of 0/1 in length. */ - slt = SL_STRUCTLIST; + saveload_type = SL_STRUCTLIST; handler = std::make_shared(); break; default: - slt = (type & SLE_FILE_HAS_LENGTH_FIELD) ? SL_ARR : SL_VAR; + saveload_type = (type & SLE_FILE_HAS_LENGTH_FIELD) ? SL_ARR : SL_VAR; break; } /* We don't know this field, so read to nothing. */ - saveloads.push_back({key, slt, ((VarType)type & SLE_FILE_TYPE_MASK) | SLE_VAR_NULL, 1, SL_MIN_VERSION, SL_MAX_VERSION, 0, nullptr, 0, handler}); + saveloads.push_back({key, saveload_type, ((VarType)type & SLE_FILE_TYPE_MASK) | SLE_VAR_NULL, 1, SL_MIN_VERSION, SL_MAX_VERSION, 0, nullptr, 0, handler}); continue; } From 6ba55e663e110a08e3373a0ad886f8fa75556f6a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sat, 28 Jan 2023 20:06:51 +0100 Subject: [PATCH 08/10] Codechange: do not hide variables with other variables --- src/3rdparty/squirrel/squirrel/sqobject.cpp | 6 +-- src/autoreplace_cmd.cpp | 1 - src/base_media_func.h | 2 +- src/company_gui.cpp | 3 +- src/gfx.cpp | 19 +++++---- src/industry_cmd.cpp | 8 +--- src/industry_gui.cpp | 4 +- src/network/network_content.cpp | 8 ++-- src/newgrf.cpp | 22 +++++------ src/newgrf_gui.cpp | 8 ++-- src/openttd.cpp | 2 +- src/order_cmd.cpp | 21 +++++----- src/rail_cmd.cpp | 8 ++-- src/road_cmd.cpp | 6 +-- src/saveload/oldloader_sl.cpp | 12 +++--- src/station_cmd.cpp | 41 ++++++++++--------- src/strgen/strgen.cpp | 4 +- src/strgen/strgen_base.cpp | 2 +- src/strings.cpp | 44 ++++++++++----------- src/timetable_gui.cpp | 8 ++-- src/town_cmd.cpp | 8 ++-- src/train_cmd.cpp | 4 +- src/tunnelbridge_cmd.cpp | 4 +- src/vehicle_gui.cpp | 4 +- src/video/opengl.cpp | 4 +- src/viewport.cpp | 18 ++++----- src/water_cmd.cpp | 4 +- src/waypoint_cmd.cpp | 4 +- src/widget.cpp | 2 +- src/window.cpp | 2 +- 30 files changed, 137 insertions(+), 146 deletions(-) diff --git a/src/3rdparty/squirrel/squirrel/sqobject.cpp b/src/3rdparty/squirrel/squirrel/sqobject.cpp index 298efe610c..ca105fd5ef 100644 --- a/src/3rdparty/squirrel/squirrel/sqobject.cpp +++ b/src/3rdparty/squirrel/squirrel/sqobject.cpp @@ -446,11 +446,11 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr for(i = 0; i < noutervalues; i++){ SQUnsignedInteger type; - SQObjectPtr name; + SQObjectPtr value_name; _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger))); _CHECK_IO(ReadObject(v, up, read, o)); - _CHECK_IO(ReadObject(v, up, read, name)); - f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type); + _CHECK_IO(ReadObject(v, up, read, value_name)); + f->_outervalues[i] = SQOuterVar(value_name,o, (SQOuterType)type); } _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 274a8cbcd2..2d3943c863 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -781,7 +781,6 @@ CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id) RestoreRandomSeeds(saved_seeds); if (cost.Succeeded() && (flags & DC_EXEC) != 0) { - CommandCost ret; if (free_wagon) { ret = ReplaceFreeUnit(&v, flags, ¬hing_to_do); } else { diff --git a/src/base_media_func.h b/src/base_media_func.h index 9a24aa94e8..557cec1e95 100644 --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -48,7 +48,7 @@ bool BaseSet::FillSetDetails(IniFile *ini, const this->description[std::string{}] = *item->value; /* Add the translations of the descriptions too. */ - for (const IniItem *item = metadata->item; item != nullptr; item = item->next) { + for (item = metadata->item; item != nullptr; item = item->next) { if (item->name.compare(0, 12, "description.") != 0) continue; this->description[item->name.substr(12)] = item->value.value_or(""); diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 3649e79c21..821abd9f97 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -633,7 +633,6 @@ private: void ShowColourDropDownMenu(uint32 widget) { uint32 used_colours = 0; - const Company *c; const Livery *livery, *default_livery = nullptr; bool primary = widget == WID_SCL_PRI_COL_DROPDOWN; byte default_col = 0; @@ -645,7 +644,7 @@ private: } } - c = Company::Get((CompanyID)this->window_number); + const Company *c = Company::Get((CompanyID)this->window_number); if (this->livery_class < LC_GROUP_RAIL) { /* Get the first selected livery to use as the default dropdown item */ diff --git a/src/gfx.cpp b/src/gfx.cpp index 2b9927ed1e..ec9e28f88c 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1327,7 +1327,6 @@ void DoPaletteAnimations() const ExtraPaletteValues *ev = &_extra_palette_values; Colour old_val[PALETTE_ANIM_SIZE]; const uint old_tc = palette_animation_counter; - uint i; uint j; if (blitter != nullptr && blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_NONE) { @@ -1342,7 +1341,7 @@ void DoPaletteAnimations() /* Fizzy Drink bubbles animation */ s = ev->fizzy_drink; j = EXTR2(512, EPV_CYCLES_FIZZY_DRINK); - for (i = 0; i != EPV_CYCLES_FIZZY_DRINK; i++) { + for (uint i = 0; i != EPV_CYCLES_FIZZY_DRINK; i++) { *palette_pos++ = s[j]; j++; if (j == EPV_CYCLES_FIZZY_DRINK) j = 0; @@ -1351,7 +1350,7 @@ void DoPaletteAnimations() /* Oil refinery fire animation */ s = ev->oil_refinery; j = EXTR2(512, EPV_CYCLES_OIL_REFINERY); - for (i = 0; i != EPV_CYCLES_OIL_REFINERY; i++) { + for (uint i = 0; i != EPV_CYCLES_OIL_REFINERY; i++) { *palette_pos++ = s[j]; j++; if (j == EPV_CYCLES_OIL_REFINERY) j = 0; @@ -1391,7 +1390,7 @@ void DoPaletteAnimations() /* Handle lighthouse and stadium animation */ s = ev->lighthouse; j = EXTR(256, EPV_CYCLES_LIGHTHOUSE); - for (i = 0; i != EPV_CYCLES_LIGHTHOUSE; i++) { + for (uint i = 0; i != EPV_CYCLES_LIGHTHOUSE; i++) { *palette_pos++ = s[j]; j++; if (j == EPV_CYCLES_LIGHTHOUSE) j = 0; @@ -1400,7 +1399,7 @@ void DoPaletteAnimations() /* Dark blue water */ s = (_settings_game.game_creation.landscape == LT_TOYLAND) ? ev->dark_water_toyland : ev->dark_water; j = EXTR(320, EPV_CYCLES_DARK_WATER); - for (i = 0; i != EPV_CYCLES_DARK_WATER; i++) { + for (uint i = 0; i != EPV_CYCLES_DARK_WATER; i++) { *palette_pos++ = s[j]; j++; if (j == EPV_CYCLES_DARK_WATER) j = 0; @@ -1409,7 +1408,7 @@ void DoPaletteAnimations() /* Glittery water */ s = (_settings_game.game_creation.landscape == LT_TOYLAND) ? ev->glitter_water_toyland : ev->glitter_water; j = EXTR(128, EPV_CYCLES_GLITTER_WATER); - for (i = 0; i != EPV_CYCLES_GLITTER_WATER / 3; i++) { + for (uint i = 0; i != EPV_CYCLES_GLITTER_WATER / 3; i++) { *palette_pos++ = s[j]; j += 3; if (j >= EPV_CYCLES_GLITTER_WATER) j -= EPV_CYCLES_GLITTER_WATER; @@ -1669,23 +1668,23 @@ void DrawDirtyBlocks() while (right != w) { byte *p2 = ++p; - int h = h2; + int i = h2; /* Check if a full line of dirty flags is set. */ do { if (!*p2) goto no_more_coalesc; p2 += _dirty_bytes_per_line; - } while (--h != 0); + } while (--i != 0); /* Wohoo, can combine it one step to the right! * Do that, and clear the bits. */ right += DIRTY_BLOCK_WIDTH; - h = h2; + i = h2; p2 = p; do { *p2 = 0; p2 += _dirty_bytes_per_line; - } while (--h != 0); + } while (--i != 0); } no_more_coalesc: diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 2ae899105f..8aa0cbcb79 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -662,8 +662,6 @@ static void AnimateTile_Industry(TileIndex tile) case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6: case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8: if ((_tick_counter & 3) == 0) { - IndustryGfx gfx = GetIndustryGfx(tile); - gfx = (gfx < 155) ? gfx + 1 : 148; SetIndustryGfx(tile, gfx); MarkTileDirtyByTile(tile); @@ -675,8 +673,6 @@ static void AnimateTile_Industry(TileIndex tile) case GFX_OILWELL_ANIMATED_3: if ((_tick_counter & 7) == 0) { bool b = Chance16(1, 7); - IndustryGfx gfx = GetIndustryGfx(tile); - byte m = GetAnimationFrame(tile) + 1; if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) { SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED); @@ -1467,13 +1463,13 @@ static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTil /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */ Backup cur_company(_current_company, OWNER_TOWN, FILE_LINE); - CommandCost ret = Command::Do(DC_NONE, cur_tile); + ret = Command::Do(DC_NONE, cur_tile); cur_company.Restore(); if (ret.Failed()) return ret; } else { /* Clear the tiles, but do not affect town ratings */ - CommandCost ret = Command::Do(DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, cur_tile); + ret = Command::Do(DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, cur_tile); if (ret.Failed()) return ret; } } diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index f670443bcd..01a76810b9 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2775,7 +2775,7 @@ struct IndustryCargoesWindow : public Window { int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)) + houses_accept; int num_indrows = std::max(3, std::max(num_supp, num_cust)); // One is needed for the 'it' industry, and 2 for the cargo labels. for (int i = 0; i < num_indrows; i++) { - CargoesRow &row = this->fields.emplace_back(); + row = this->fields.emplace_back(); row.columns[0].MakeEmpty(CFT_EMPTY); row.columns[1].MakeCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo)); row.columns[2].MakeEmpty(CFT_EMPTY); @@ -2850,7 +2850,7 @@ struct IndustryCargoesWindow : public Window { int num_cust = CountMatchingAcceptingIndustries(&cid, 1) + houses_accept; int num_indrows = std::max(num_supp, num_cust); for (int i = 0; i < num_indrows; i++) { - CargoesRow &row = this->fields.emplace_back(); + row = this->fields.emplace_back(); row.columns[0].MakeEmpty(CFT_EMPTY); row.columns[1].MakeCargo(&cid, 1); row.columns[2].MakeEmpty(CFT_EMPTY); diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index d6381a71b6..885593f484 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -1054,11 +1054,11 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci) * After that's done run over them once again to test their children * to unselect. Don't do it immediately because it'll do exactly what * we're doing now. */ - for (const ContentInfo *c : parents) { - if (c->state == ContentInfo::AUTOSELECTED) this->Unselect(c->id); + for (const ContentInfo *parent : parents) { + if (parent->state == ContentInfo::AUTOSELECTED) this->Unselect(parent->id); } - for (const ContentInfo *c : parents) { - this->CheckDependencyState(this->GetContent(c->id)); + for (const ContentInfo *parent : parents) { + this->CheckDependencyState(this->GetContent(parent->id)); } } } diff --git a/src/newgrf.cpp b/src/newgrf.cpp index d5a2c02f58..7898afe739 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -4270,13 +4270,13 @@ static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteR int n = buf->ReadByte(); for (int j = 0; j != n; j++) { RailTypeLabel label = buf->ReadDWord(); - RailType rt = GetRailTypeByLabel(BSWAP32(label), false); - if (rt != INVALID_RAILTYPE) { + RailType resolved_rt = GetRailTypeByLabel(BSWAP32(label), false); + if (resolved_rt != INVALID_RAILTYPE) { switch (prop) { - case 0x0F: SetBit(rti->powered_railtypes, rt); FALLTHROUGH; // Powered implies compatible. - case 0x0E: SetBit(rti->compatible_railtypes, rt); break; - case 0x18: SetBit(rti->introduction_required_railtypes, rt); break; - case 0x19: SetBit(rti->introduces_railtypes, rt); break; + case 0x0F: SetBit(rti->powered_railtypes, resolved_rt); FALLTHROUGH; // Powered implies compatible. + case 0x0E: SetBit(rti->compatible_railtypes, resolved_rt); break; + case 0x18: SetBit(rti->introduction_required_railtypes, resolved_rt); break; + case 0x19: SetBit(rti->introduces_railtypes, resolved_rt); break; } } } @@ -4484,12 +4484,12 @@ static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteR int n = buf->ReadByte(); for (int j = 0; j != n; j++) { RoadTypeLabel label = buf->ReadDWord(); - RoadType rt = GetRoadTypeByLabel(BSWAP32(label), false); - if (rt != INVALID_ROADTYPE) { + RoadType resolved_rt = GetRoadTypeByLabel(BSWAP32(label), false); + if (resolved_rt != INVALID_ROADTYPE) { switch (prop) { - case 0x0F: SetBit(rti->powered_roadtypes, rt); break; - case 0x18: SetBit(rti->introduction_required_roadtypes, rt); break; - case 0x19: SetBit(rti->introduces_roadtypes, rt); break; + case 0x0F: SetBit(rti->powered_roadtypes, resolved_rt); break; + case 0x18: SetBit(rti->introduction_required_roadtypes, resolved_rt); break; + case 0x19: SetBit(rti->introduces_roadtypes, resolved_rt); break; } } } diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 89e1a6e5e8..820aa10d03 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1285,16 +1285,16 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { WIDGET_LIST_END ); - const GRFConfig *c = (this->avail_sel == nullptr) ? this->active_sel : this->avail_sel; + const GRFConfig *selected_config = (this->avail_sel == nullptr) ? this->active_sel : this->avail_sel; for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { - this->SetWidgetDisabledState(WID_NS_NEWGRF_TEXTFILE + tft, c == nullptr || c->GetTextfile(tft) == nullptr); + this->SetWidgetDisabledState(WID_NS_NEWGRF_TEXTFILE + tft, selected_config == nullptr || selected_config->GetTextfile(tft) == nullptr); } - this->SetWidgetDisabledState(WID_NS_OPEN_URL, c == nullptr || StrEmpty(c->GetURL())); + this->SetWidgetDisabledState(WID_NS_OPEN_URL, selected_config == nullptr || StrEmpty(selected_config->GetURL())); this->SetWidgetDisabledState(WID_NS_SET_PARAMETERS, !this->show_params || this->active_sel == nullptr || this->active_sel->num_valid_params == 0); this->SetWidgetDisabledState(WID_NS_VIEW_PARAMETERS, !this->show_params || this->active_sel == nullptr || this->active_sel->num_valid_params == 0); this->SetWidgetDisabledState(WID_NS_TOGGLE_PALETTE, disable_all || - (!(_settings_client.gui.newgrf_developer_tools || _settings_client.gui.scenario_developer) && ((c->palette & GRFP_GRF_MASK) != GRFP_GRF_UNSET))); + (!(_settings_client.gui.newgrf_developer_tools || _settings_client.gui.scenario_developer) && ((selected_config->palette & GRFP_GRF_MASK) != GRFP_GRF_UNSET))); if (!disable_all) { /* All widgets are now enabled, so disable widgets we can't use */ diff --git a/src/openttd.cpp b/src/openttd.cpp index 20401892be..0274063b60 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1403,7 +1403,7 @@ void StateGameLoop() #ifndef DEBUG_DUMP_COMMANDS { - PerformanceMeasurer framerate(PFE_ALLSCRIPTS); + PerformanceMeasurer script_framerate(PFE_ALLSCRIPTS); AI::GameLoop(); Game::GameLoop(); } diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index ab2f9fb647..5cde853e42 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -754,7 +754,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se if (st == nullptr) return CMD_ERROR; if (st->owner != OWNER_NONE) { - CommandCost ret = CheckOwnership(st->owner); + ret = CheckOwnership(st->owner); if (ret.Failed()) return ret; } @@ -800,7 +800,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se if (st == nullptr) return CMD_ERROR; - CommandCost ret = CheckOwnership(st->owner); + ret = CheckOwnership(st->owner); if (ret.Failed()) return ret; if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) { @@ -811,7 +811,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se if (dp == nullptr) return CMD_ERROR; - CommandCost ret = CheckOwnership(GetTileOwner(dp->xy)); + ret = CheckOwnership(GetTileOwner(dp->xy)); if (ret.Failed()) return ret; switch (v->type) { @@ -849,7 +849,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se case VEH_TRAIN: { if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER); - CommandCost ret = CheckOwnership(wp->owner); + ret = CheckOwnership(wp->owner); if (ret.Failed()) return ret; break; } @@ -857,7 +857,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se case VEH_SHIP: if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER); if (wp->owner != OWNER_NONE) { - CommandCost ret = CheckOwnership(wp->owner); + ret = CheckOwnership(wp->owner); if (ret.Failed()) return ret; } break; @@ -1514,7 +1514,7 @@ CommandCost CmdCloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID ve /* Sanity checks */ if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR; - CommandCost ret = CheckOwnership(src->owner); + ret = CheckOwnership(src->owner); if (ret.Failed()) return ret; /* Trucks can't share orders with busses (and visa versa) */ @@ -1571,7 +1571,7 @@ CommandCost CmdCloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID ve /* Sanity checks */ if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR; - CommandCost ret = CheckOwnership(src->owner); + ret = CheckOwnership(src->owner); if (ret.Failed()) return ret; /* Trucks can't copy all the orders from busses (and visa versa), @@ -1771,12 +1771,9 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool /* Go through all vehicles */ for (Vehicle *v : Vehicle::Iterate()) { - Order *order; - - order = &v->current_order; - if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type && + if ((v->type == VEH_AIRCRAFT && v->current_order.IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : v->current_order.GetType()) == type && (!hangar || v->type == VEH_AIRCRAFT) && v->current_order.GetDestination() == destination) { - order->MakeDummy(); + v->current_order.MakeDummy(); SetWindowDirty(WC_VEHICLE_VIEW, v->index); } diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 75cc0a7c82..77fbe00f5f 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -531,7 +531,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlag flags, TileIndex tile, RailType rai /* Disallow breaking end-of-line of someone else * so trams can still reverse on this tile. */ if (Company::IsValidID(tram_owner) && HasExactlyOneBit(tram)) { - CommandCost ret = CheckOwnership(tram_owner); + ret = CheckOwnership(tram_owner); if (ret.Failed()) return ret; } @@ -893,7 +893,7 @@ static CommandCost CmdRailTrackHelper(DoCommandFlag flags, TileIndex tile, TileI bool had_success = false; CommandCost last_error = CMD_ERROR; for (;;) { - CommandCost ret = remove ? Command::Do(flags, tile, TrackdirToTrack(trackdir)) : Command::Do(flags, tile, railtype, TrackdirToTrack(trackdir), auto_remove_signals); + ret = remove ? Command::Do(flags, tile, TrackdirToTrack(trackdir)) : Command::Do(flags, tile, railtype, TrackdirToTrack(trackdir), auto_remove_signals); if (ret.Failed()) { last_error = ret; @@ -1591,7 +1591,7 @@ CommandCost CmdConvertRail(DoCommandFlag flags, TileIndex tile, TileIndex area_s * Tunnels and bridges have special check later */ if (tt != MP_TUNNELBRIDGE) { if (!IsCompatibleRail(type, totype)) { - CommandCost ret = IsPlainRailTile(tile) ? EnsureNoTrainOnTrackBits(tile, GetTrackBits(tile)) : EnsureNoVehicleOnGround(tile); + ret = IsPlainRailTile(tile) ? EnsureNoTrainOnTrackBits(tile, GetTrackBits(tile)) : EnsureNoVehicleOnGround(tile); if (ret.Failed()) { error = ret; continue; @@ -1675,7 +1675,7 @@ CommandCost CmdConvertRail(DoCommandFlag flags, TileIndex tile, TileIndex area_s /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */ if (!IsCompatibleRail(GetRailType(tile), totype)) { - CommandCost ret = TunnelBridgeIsFree(tile, endtile); + ret = TunnelBridgeIsFree(tile, endtile); if (ret.Failed()) { error = ret; continue; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index d7bb06bf8c..43bb864dc2 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -865,7 +865,7 @@ do_clear:; if (HasPowerOnRoad(rt, existing_rt)) { rt = existing_rt; } else if (HasPowerOnRoad(existing_rt, rt)) { - CommandCost ret = Command::Do(flags, tile, tile, rt); + ret = Command::Do(flags, tile, tile, rt); if (ret.Failed()) return ret; cost.AddCost(ret); } else { @@ -1715,7 +1715,7 @@ static void DrawTile_Road(TileInfo *ti) /* Draw rail/PBS overlay */ bool draw_pbs = _game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile); if (rti->UsesOverlay()) { - PaletteID pal = draw_pbs ? PALETTE_CRASH : PAL_NONE; + pal = draw_pbs ? PALETTE_CRASH : PAL_NONE; SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis; DrawGroundSprite(rail, pal); @@ -1757,7 +1757,7 @@ static void DrawTile_Road(TileInfo *ti) } } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) { /* Add another rail overlay, unless there is only the base road sprite. */ - PaletteID pal = draw_pbs ? PALETTE_CRASH : PAL_NONE; + pal = draw_pbs ? PALETTE_CRASH : PAL_NONE; SpriteID rail = GetCrossingRoadAxis(ti->tile) == AXIS_Y ? GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.single_x : GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.single_y; DrawGroundSprite(rail, pal); } diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 9e858572b5..f6b64ede7a 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -384,11 +384,13 @@ static bool FixTTOEngines() } /* Load the default engine set. Many of them will be overridden later */ - uint j = 0; - for (uint i = 0; i < lengthof(_orig_rail_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_TRAIN, i); - for (uint i = 0; i < lengthof(_orig_road_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_ROAD, i); - for (uint i = 0; i < lengthof(_orig_ship_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_SHIP, i); - for (uint i = 0; i < lengthof(_orig_aircraft_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_AIRCRAFT, i); + { + uint j = 0; + for (uint i = 0; i < lengthof(_orig_rail_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_TRAIN, i); + for (uint i = 0; i < lengthof(_orig_road_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_ROAD, i); + for (uint i = 0; i < lengthof(_orig_ship_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_SHIP, i); + for (uint i = 0; i < lengthof(_orig_aircraft_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_AIRCRAFT, i); + } Date aging_date = std::min(_date + DAYS_TILL_ORIGINAL_BASE_YEAR, ConvertYMDToDate(2050, 0, 1)); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 0d9ad9da38..ace90dc029 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -931,7 +931,7 @@ static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag fl affected_vehicles.push_back(v); } } - CommandCost ret = Command::Do(flags, tile_cur, track); + ret = Command::Do(flags, tile_cur, track); if (ret.Failed()) return ret; cost.AddCost(ret); /* With flags & ~DC_EXEC CmdLandscapeClear would fail since the rail still exists */ @@ -1018,7 +1018,7 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags if (road_owner == OWNER_TOWN) { if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD); } else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE) { - CommandCost ret = CheckOwnership(road_owner); + ret = CheckOwnership(road_owner); if (ret.Failed()) return ret; } uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_ROAD)); @@ -1026,7 +1026,7 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags if (RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD); if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE && road_owner != OWNER_TOWN) { - CommandCost ret = CheckOwnership(road_owner); + ret = CheckOwnership(road_owner); if (ret.Failed()) return ret; } @@ -1044,7 +1044,7 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags /* Disallow breaking end-of-line of someone else * so trams can still reverse on this tile. */ HasExactlyOneBit(GetRoadBits(cur_tile, RTT_TRAM)))) { - CommandCost ret = CheckOwnership(tram_owner); + ret = CheckOwnership(tram_owner); if (ret.Failed()) return ret; } uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_TRAM)); @@ -1308,7 +1308,7 @@ CommandCost CmdBuildRailStation(DoCommandFlag flags, TileIndex tile_org, RailTyp if (ret.Failed()) return ret; if (st != nullptr && st->train_station.tile != INVALID_TILE) { - CommandCost ret = CanExpandRailStation(st, new_location, axis); + ret = CanExpandRailStation(st, new_location, axis); if (ret.Failed()) return ret; } @@ -1573,7 +1573,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector &affected_st if (st == nullptr) continue; if (_current_company != OWNER_WATER) { - CommandCost ret = CheckOwnership(st->owner); + ret = CheckOwnership(st->owner); error.AddCost(ret); if (ret.Failed()) continue; } @@ -2236,13 +2236,13 @@ CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_ty return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT); } - AirportTileTableIterator iter(as->table[layout], tile); - CommandCost cost = CheckFlatLandAirport(iter, flags); + AirportTileTableIterator tile_iter(as->table[layout], tile); + CommandCost cost = CheckFlatLandAirport(tile_iter, flags); if (cost.Failed()) return cost; /* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */ uint dist; - Town *nearest = AirportGetNearestTown(as, iter, dist); + Town *nearest = AirportGetNearestTown(as, tile_iter, dist); uint newnoise_level = GetAirportNoiseLevelForDistance(as, dist); /* Check if local auth would allow a new airport */ @@ -2986,7 +2986,6 @@ draw_default_foundation: /* PBS debugging, draw reserved tracks darker */ if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasStationRail(ti->tile) && HasStationReservation(ti->tile)) { - const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); DrawGroundSprite(GetRailStationAxis(ti->tile) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH); } } @@ -3033,17 +3032,17 @@ void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, Ro int32 total_offset = 0; PaletteID pal = COMPANY_SPRITE_COLOUR(_local_company); const DrawTileSprites *t = GetStationTileLayout(st, image); - const RailtypeInfo *rti = nullptr; + const RailtypeInfo *railtype_info = nullptr; if (railtype != INVALID_RAILTYPE) { - rti = GetRailTypeInfo(railtype); - total_offset = rti->GetRailtypeSpriteOffset(); + railtype_info = GetRailTypeInfo(railtype); + total_offset = railtype_info->GetRailtypeSpriteOffset(); } SpriteID img = t->ground.sprite; RailTrackOffset overlay_offset; - if (rti != nullptr && rti->UsesOverlay() && SplitGroundSpriteForOverlay(nullptr, &img, &overlay_offset)) { - SpriteID ground = GetCustomRailSprite(rti, INVALID_TILE, RTSG_GROUND); + if (railtype_info != nullptr && railtype_info->UsesOverlay() && SplitGroundSpriteForOverlay(nullptr, &img, &overlay_offset)) { + SpriteID ground = GetCustomRailSprite(railtype_info, INVALID_TILE, RTSG_GROUND); DrawSprite(img, PAL_NONE, x, y); DrawSprite(ground + overlay_offset, PAL_NONE, x, y); } else { @@ -3051,25 +3050,25 @@ void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, Ro } if (roadtype != INVALID_ROADTYPE) { - const RoadTypeInfo* rti = GetRoadTypeInfo(roadtype); + const RoadTypeInfo *roadtype_info = GetRoadTypeInfo(roadtype); if (image >= 4) { /* Drive-through stop */ uint sprite_offset = 5 - image; /* Road underlay takes precedence over tram */ - if (rti->UsesOverlay()) { - SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_GROUND); + if (roadtype_info->UsesOverlay()) { + SpriteID ground = GetCustomRoadSprite(roadtype_info, INVALID_TILE, ROTSG_GROUND); DrawSprite(ground + sprite_offset, PAL_NONE, x, y); - SpriteID overlay = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_OVERLAY); + SpriteID overlay = GetCustomRoadSprite(roadtype_info, INVALID_TILE, ROTSG_OVERLAY); if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y); } else if (RoadTypeIsTram(roadtype)) { DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y); } } else { /* Drive-in stop */ - if (RoadTypeIsRoad(roadtype) && rti->UsesOverlay()) { - SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP); + if (RoadTypeIsRoad(roadtype) && roadtype_info->UsesOverlay()) { + SpriteID ground = GetCustomRoadSprite(roadtype_info, INVALID_TILE, ROTSG_ROADSTOP); DrawSprite(ground + image, PAL_NONE, x, y); } } diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp index 025f9406df..b723aa656e 100644 --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -472,9 +472,9 @@ int CDECL main(int argc, char *argv[]) case 'P': printf("name\tflags\tdefault\tdescription\n"); - for (size_t i = 0; i < lengthof(_pragmas); i++) { + for (size_t j = 0; j < lengthof(_pragmas); j++) { printf("\"%s\"\t%s\t\"%s\"\t\"%s\"\n", - _pragmas[i][0], _pragmas[i][1], _pragmas[i][2], _pragmas[i][3]); + _pragmas[j][0], _pragmas[j][1], _pragmas[j][2], _pragmas[j][3]); } return 0; diff --git a/src/strgen/strgen_base.cpp b/src/strgen/strgen_base.cpp index 078e0abbf2..bf3a25e3ad 100644 --- a/src/strgen/strgen_base.cpp +++ b/src/strgen/strgen_base.cpp @@ -877,7 +877,7 @@ static int TranslateArgumentIdx(int argidx, int offset) } for (int i = sum = 0; i < argidx; i++) { - const CmdStruct *cs = _cur_pcs.cmd[i]; + cs = _cur_pcs.cmd[i]; sum += (cs != nullptr) ? cs->consumes : 1; } diff --git a/src/strings.cpp b/src/strings.cpp index 4c78e0fe7b..27a8639550 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -938,7 +938,7 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg buff = GetStringWithArgs(buff, MakeStringID(TEXT_TAB_GAMESCRIPT_START, stringid), &sub_args, last, true); } - for (int i = 0; i < 20; i++) { + for (i = 0; i < 20; i++) { if (sub_args_need_free[i]) free((void *)sub_args.GetParam(i)); } break; @@ -1044,19 +1044,19 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg case SCC_RAW_STRING_POINTER: { // {RAW_STRING} if (game_script) break; - const char *str = (const char *)(size_t)args->GetInt64(SCC_RAW_STRING_POINTER); - buff = FormatString(buff, str, args, last); + const char *raw_string = (const char *)(size_t)args->GetInt64(SCC_RAW_STRING_POINTER); + buff = FormatString(buff, raw_string, args, last); break; } case SCC_STRING: {// {STRING} - StringID str = args->GetInt32(SCC_STRING); - if (game_script && GetStringTab(str) != TEXT_TAB_GAMESCRIPT_START) break; + StringID string_id = args->GetInt32(SCC_STRING); + if (game_script && GetStringTab(string_id) != TEXT_TAB_GAMESCRIPT_START) break; /* WARNING. It's prohibited for the included string to consume any arguments. * For included strings that consume argument, you should use STRING1, STRING2 etc. * To debug stuff you can set argv to nullptr and it will tell you */ StringParameters tmp_params(args->GetDataPointer(), args->GetDataLeft(), nullptr); - buff = GetStringWithArgs(buff, str, &tmp_params, last, next_substr_case_index, game_script); + buff = GetStringWithArgs(buff, string_id, &tmp_params, last, next_substr_case_index, game_script); next_substr_case_index = 0; break; } @@ -1069,14 +1069,14 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg case SCC_STRING6: case SCC_STRING7: { // {STRING1..7} /* Strings that consume arguments */ - StringID str = args->GetInt32(b); - if (game_script && GetStringTab(str) != TEXT_TAB_GAMESCRIPT_START) break; + StringID string_id = args->GetInt32(b); + if (game_script && GetStringTab(string_id) != TEXT_TAB_GAMESCRIPT_START) break; uint size = b - SCC_STRING1 + 1; if (game_script && size > args->GetDataLeft()) { buff = strecat(buff, "(too many parameters)", last); } else { StringParameters sub_args(*args, size); - buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script); + buff = GetStringWithArgs(buff, string_id, &sub_args, last, next_substr_case_index, game_script); } next_substr_case_index = 0; break; @@ -1456,7 +1456,7 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg StringParameters tmp_params(args_array); buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last); } else { - StringID str = st->string_id; + StringID string_id = st->string_id; if (st->indtype != IT_INVALID) { /* Special case where the industry provides the name for the station */ const IndustrySpec *indsp = GetIndustrySpec(st->indtype); @@ -1465,14 +1465,14 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg * thus cause very strange things. Here we check for that before we * actually set the station name. */ if (indsp->station_name != STR_NULL && indsp->station_name != STR_UNDEFINED) { - str = indsp->station_name; + string_id = indsp->station_name; } } uint64 args_array[] = {STR_TOWN_NAME, st->town->index, st->index}; WChar types_array[] = {0, SCC_TOWN_NAME, SCC_NUM}; StringParameters tmp_params(args_array, 3, types_array); - buff = GetStringWithArgs(buff, str, &tmp_params, last); + buff = GetStringWithArgs(buff, string_id, &tmp_params, last); } break; } @@ -1502,9 +1502,9 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg } else { int64 args_array[] = {wp->town->index, wp->town_cn + 1}; StringParameters tmp_params(args_array); - StringID str = ((wp->string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME); - if (wp->town_cn != 0) str++; - buff = GetStringWithArgs(buff, str, &tmp_params, last); + StringID string_id = ((wp->string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME); + if (wp->town_cn != 0) string_id++; + buff = GetStringWithArgs(buff, string_id, &tmp_params, last); } break; } @@ -1526,16 +1526,16 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg int64 args_array[] = {v->unitnumber}; StringParameters tmp_params(args_array); - StringID str; + StringID string_id; switch (v->type) { - default: str = STR_INVALID_VEHICLE; break; - case VEH_TRAIN: str = STR_SV_TRAIN_NAME; break; - case VEH_ROAD: str = STR_SV_ROAD_VEHICLE_NAME; break; - case VEH_SHIP: str = STR_SV_SHIP_NAME; break; - case VEH_AIRCRAFT: str = STR_SV_AIRCRAFT_NAME; break; + default: string_id = STR_INVALID_VEHICLE; break; + case VEH_TRAIN: string_id = STR_SV_TRAIN_NAME; break; + case VEH_ROAD: string_id = STR_SV_ROAD_VEHICLE_NAME; break; + case VEH_SHIP: string_id = STR_SV_SHIP_NAME; break; + case VEH_AIRCRAFT: string_id = STR_SV_AIRCRAFT_NAME; break; } - buff = GetStringWithArgs(buff, str, &tmp_params, last); + buff = GetStringWithArgs(buff, string_id, &tmp_params, last); } break; } diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 94a78b7a61..c76148dd07 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -91,15 +91,15 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID assert(v->GetNumOrders() >= 2); assert(start < v->GetNumOrders()); - Ticks sum = offset; - VehicleOrderID i = start; - const Order *order = v->GetOrder(i); - /* Pre-initialize with unknown time */ for (int i = 0; i < v->GetNumOrders(); ++i) { table[i].arrival = table[i].departure = INVALID_TICKS; } + Ticks sum = offset; + VehicleOrderID i = start; + const Order *order = v->GetOrder(i); + /* Cyclically loop over all orders until we reach the current one again. * As we may start at the current order, do a post-checking loop */ do { diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index a69d32b4aa..61c87b658d 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -93,7 +93,7 @@ static bool TestTownOwnsBridge(TileIndex tile, const Town *t) if (!town_owned) { /* Or other adjacent road */ - TileIndex adjacent = tile + TileOffsByDiagDir(ReverseDiagDir(GetTunnelBridgeDirection(GetOtherTunnelBridgeEnd(tile)))); + adjacent = tile + TileOffsByDiagDir(ReverseDiagDir(GetTunnelBridgeDirection(GetOtherTunnelBridgeEnd(tile)))); town_owned = IsTileType(adjacent, MP_ROAD) && IsTileOwner(adjacent, OWNER_TOWN) && GetTownIndex(adjacent) == t->index; } @@ -2656,15 +2656,15 @@ static bool BuildTownHouse(Town *t, TileIndex tile) byte construction_stage = 0; if (_generating_world || _game_mode == GM_EDITOR) { - uint32 r = Random(); + uint32 construction_random = Random(); construction_stage = TOWN_HOUSE_COMPLETED; - if (Chance16(1, 7)) construction_stage = GB(r, 0, 2); + if (Chance16(1, 7)) construction_stage = GB(construction_random, 0, 2); if (construction_stage == TOWN_HOUSE_COMPLETED) { ChangePopulation(t, hs->population); } else { - construction_counter = GB(r, 2, 2); + construction_counter = GB(construction_random, 2, 2); } } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 8df9ccd284..694fa06a80 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1202,7 +1202,7 @@ CommandCost CmdMoveRailVehicle(DoCommandFlag flags, VehicleID src_veh, VehicleID dst = Train::GetIfValid(dest_veh); if (dst == nullptr) return CMD_ERROR; - CommandCost ret = CheckOwnership(dst->owner); + ret = CheckOwnership(dst->owner); if (ret.Failed()) return ret; /* Do not allow appending to crashed vehicles, too */ @@ -1271,7 +1271,7 @@ CommandCost CmdMoveRailVehicle(DoCommandFlag flags, VehicleID src_veh, VehicleID /* If the autoreplace flag is set we do not need to test for the validity * because we are going to revert the train to its original state. As we * assume the original state was correct autoreplace can skip this. */ - CommandCost ret = ValidateTrains(original_dst_head, dst_head, original_src_head, src_head, true); + ret = ValidateTrains(original_dst_head, dst_head, original_src_head, src_head, true); if (ret.Failed()) { /* Restore the train we had. */ RestoreTrainBackup(original_src); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index bb777eaddd..e9f4fb7169 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -862,7 +862,7 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) /* Check if you are allowed to remove the tunnel owned by a town * Removal depends on difficulty settings */ - CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE); + ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE); if (ret.Failed()) return ret; } @@ -943,7 +943,7 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags) /* Check if you are allowed to remove the bridge owned by a town * Removal depends on difficulty settings */ - CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE); + ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE); if (ret.Failed()) return ret; } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index f8c9bce791..dadb726d21 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -3226,8 +3226,8 @@ public: } /* The same system applies to widget WID_VV_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/ if (v->IsGroundVehicle()) { - PlaneSelections plane = veh_stopped ? SEL_RT_REFIT : SEL_RT_TURN_AROUND; - NWidgetStacked *nwi = this->GetWidget(WID_VV_SELECT_REFIT_TURN); + plane = veh_stopped ? SEL_RT_REFIT : SEL_RT_TURN_AROUND; + nwi = this->GetWidget(WID_VV_SELECT_REFIT_TURN); if (nwi->shown_plane + SEL_RT_BASEPLANE != plane) { this->SelectPlane(plane); this->SetWidgetDirty(WID_VV_SELECT_REFIT_TURN); diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 4b6d68863b..ae46fe78f0 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -1120,8 +1120,8 @@ void OpenGLBackend::PopulateCursorCache() if (!this->cursor_cache.Contains(sprite)) { Sprite *old = this->cursor_cache.Insert(sprite, (Sprite *)GetRawSprite(sprite, ST_NORMAL, &SimpleSpriteAlloc, this)); if (old != nullptr) { - OpenGLSprite *sprite = (OpenGLSprite *)old->data; - sprite->~OpenGLSprite(); + OpenGLSprite *gl_sprite = (OpenGLSprite *)old->data; + gl_sprite->~OpenGLSprite(); free(old); } } diff --git a/src/viewport.cpp b/src/viewport.cpp index af3b26ba99..dd5e469085 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1356,9 +1356,6 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi) bool show_signs = HasBit(_display_opt, DO_SHOW_SIGNS) && !IsInvisibilitySet(TO_SIGNS); bool show_competitors = HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS); - const BaseStation *st; - const Sign *si; - /* Collect all the items first and draw afterwards, to ensure layering */ std::vector stations; std::vector towns; @@ -1366,34 +1363,36 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi) _viewport_sign_kdtree.FindContained(search_rect.left, search_rect.top, search_rect.right, search_rect.bottom, [&](const ViewportSignKdtreeItem & item) { switch (item.type) { - case ViewportSignKdtreeItem::VKI_STATION: + case ViewportSignKdtreeItem::VKI_STATION: { if (!show_stations) break; - st = BaseStation::Get(item.id.station); + const BaseStation *st = BaseStation::Get(item.id.station); /* Don't draw if station is owned by another company and competitor station names are hidden. Stations owned by none are never ignored. */ if (!show_competitors && _local_company != st->owner && st->owner != OWNER_NONE) break; stations.push_back(st); break; + } - case ViewportSignKdtreeItem::VKI_WAYPOINT: + case ViewportSignKdtreeItem::VKI_WAYPOINT: { if (!show_waypoints) break; - st = BaseStation::Get(item.id.station); + const BaseStation *st = BaseStation::Get(item.id.station); /* Don't draw if station is owned by another company and competitor station names are hidden. Stations owned by none are never ignored. */ if (!show_competitors && _local_company != st->owner && st->owner != OWNER_NONE) break; stations.push_back(st); break; + } case ViewportSignKdtreeItem::VKI_TOWN: if (!show_towns) break; towns.push_back(Town::Get(item.id.town)); break; - case ViewportSignKdtreeItem::VKI_SIGN: + case ViewportSignKdtreeItem::VKI_SIGN: { if (!show_signs) break; - si = Sign::Get(item.id.sign); + const Sign *si = Sign::Get(item.id.sign); /* Don't draw if sign is owned by another company and competitor signs should be hidden. * Note: It is intentional that also signs owned by OWNER_NONE are hidden. Bankrupt @@ -1402,6 +1401,7 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi) signs.push_back(si); break; + } default: NOT_REACHED(); diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 85d9fa6f7b..c2bd4a86ef 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -264,7 +264,7 @@ static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlag flags) /* do not check for ship on tile when company goes bankrupt */ if (!(flags & DC_BANKRUPT)) { - CommandCost ret = EnsureNoVehicleOnGround(tile); + ret = EnsureNoVehicleOnGround(tile); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2); if (ret.Failed()) return ret; } @@ -539,7 +539,7 @@ static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags) Owner owner = GetTileOwner(tile); if (owner != OWNER_WATER && owner != OWNER_NONE) { - CommandCost ret = CheckTileOwnership(tile); + ret = CheckTileOwnership(tile); if (ret.Failed()) return ret; } diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index da37a8b15a..f8c3415260 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -217,11 +217,11 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlag flags, TileIndex start_tile, Axis /* check if we want to expand an already existing waypoint? */ if (wp->train_station.tile != INVALID_TILE) { - CommandCost ret = CanExpandRailStation(wp, new_location, axis); + ret = CanExpandRailStation(wp, new_location, axis); if (ret.Failed()) return ret; } - CommandCost ret = wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TEST); + ret = wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TEST); if (ret.Failed()) return ret; } else { /* allocate and initialize new waypoint */ diff --git a/src/widget.cpp b/src/widget.cpp index 08aafb910f..6f679e2f47 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -3209,7 +3209,7 @@ static int MakeWidgetTree(const NWidgetPart *parts, int count, NWidgetBase **par if (fill_sub && (tp == NWID_HORIZONTAL || tp == NWID_HORIZONTAL_LTR || tp == NWID_VERTICAL || tp == NWID_MATRIX || tp == WWT_PANEL || tp == WWT_FRAME || tp == WWT_INSET || tp == NWID_SELECTION)) { NWidgetBase *sub_ptr = sub_widget; - int num_used = MakeWidgetTree(parts, count - total_used, &sub_ptr, biggest_index); + num_used = MakeWidgetTree(parts, count - total_used, &sub_ptr, biggest_index); parts += num_used; total_used += num_used; } diff --git a/src/window.cpp b/src/window.cpp index ec255f0f25..6e48571d86 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -257,7 +257,7 @@ void Window::SetWidgetHighlight(byte widget_index, TextColour highlighted_colour /* If we disable a highlight, check all widgets if anyone still has a highlight */ bool valid = false; for (uint i = 0; i < this->nested_array_size; i++) { - NWidgetBase *nwid = this->GetWidget(i); + nwid = this->GetWidget(i); if (nwid == nullptr) continue; if (!nwid->IsHighlighted()) continue; From 8be908c9191a51981e5e0cd45858423e00b33538 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 29 Jan 2023 16:48:00 +0100 Subject: [PATCH 09/10] Fix #10430, Fix 6ba55e6: display chain window causing assert --- src/industry_gui.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 01a76810b9..f973ee7ed2 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2760,12 +2760,12 @@ struct IndustryCargoesWindow : public Window { _displayed_industries.set(displayed_it); this->fields.clear(); - CargoesRow &row = this->fields.emplace_back(); - row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS); - row.columns[1].MakeEmpty(CFT_SMALL_EMPTY); - row.columns[2].MakeEmpty(CFT_SMALL_EMPTY); - row.columns[3].MakeEmpty(CFT_SMALL_EMPTY); - row.columns[4].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS); + CargoesRow &first_row = this->fields.emplace_back(); + first_row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS); + first_row.columns[1].MakeEmpty(CFT_SMALL_EMPTY); + first_row.columns[2].MakeEmpty(CFT_SMALL_EMPTY); + first_row.columns[3].MakeEmpty(CFT_SMALL_EMPTY); + first_row.columns[4].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS); const IndustrySpec *central_sp = GetIndustrySpec(displayed_it); bool houses_supply = HousesCanSupply(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo)); @@ -2775,7 +2775,7 @@ struct IndustryCargoesWindow : public Window { int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)) + houses_accept; int num_indrows = std::max(3, std::max(num_supp, num_cust)); // One is needed for the 'it' industry, and 2 for the cargo labels. for (int i = 0; i < num_indrows; i++) { - row = this->fields.emplace_back(); + CargoesRow &row = this->fields.emplace_back(); row.columns[0].MakeEmpty(CFT_EMPTY); row.columns[1].MakeCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo)); row.columns[2].MakeEmpty(CFT_EMPTY); @@ -2837,12 +2837,12 @@ struct IndustryCargoesWindow : public Window { _displayed_industries.reset(); this->fields.clear(); - CargoesRow &row = this->fields.emplace_back(); - row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS); - row.columns[1].MakeEmpty(CFT_SMALL_EMPTY); - row.columns[2].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS); - row.columns[3].MakeEmpty(CFT_SMALL_EMPTY); - row.columns[4].MakeEmpty(CFT_SMALL_EMPTY); + CargoesRow &first_row = this->fields.emplace_back(); + first_row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS); + first_row.columns[1].MakeEmpty(CFT_SMALL_EMPTY); + first_row.columns[2].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS); + first_row.columns[3].MakeEmpty(CFT_SMALL_EMPTY); + first_row.columns[4].MakeEmpty(CFT_SMALL_EMPTY); bool houses_supply = HousesCanSupply(&cid, 1); bool houses_accept = HousesCanAccept(&cid, 1); @@ -2850,7 +2850,7 @@ struct IndustryCargoesWindow : public Window { int num_cust = CountMatchingAcceptingIndustries(&cid, 1) + houses_accept; int num_indrows = std::max(num_supp, num_cust); for (int i = 0; i < num_indrows; i++) { - row = this->fields.emplace_back(); + CargoesRow &row = this->fields.emplace_back(); row.columns[0].MakeEmpty(CFT_EMPTY); row.columns[1].MakeCargo(&cid, 1); row.columns[2].MakeEmpty(CFT_EMPTY); From 5a4f0498feac4dac2e912004ca79bb5adb903c23 Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 29 Jan 2023 18:42:05 +0000 Subject: [PATCH 10/10] Update: Translations from eints hebrew: 6 changes by haimlm catalan: 4 changes by J0anJosep turkish: 7 changes by ahmetlii --- src/lang/catalan.txt | 4 ++++ src/lang/hebrew.txt | 6 ++++++ src/lang/turkish.txt | 10 +++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 559f85d381..6765231f44 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -2699,6 +2699,10 @@ STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP :{BLACK}Augmenta STR_SELECT_RAIL_BRIDGE_CAPTION :{WHITE}Selecciona Pont de Tren STR_SELECT_ROAD_BRIDGE_CAPTION :{WHITE}Selecciona Pont de Carretera STR_SELECT_BRIDGE_SELECTION_TOOLTIP :{BLACK}Selecció de pont - clica sobre el pont triat per construir-lo +STR_SELECT_BRIDGE_INFO_NAME :{GOLD}{STRING} +STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED :{GOLD}{STRING},{} {VELOCITY} +STR_SELECT_BRIDGE_INFO_NAME_COST :{GOLD}{0:STRING},{} {WHITE}{2:CURRENCY_LONG} +STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED_COST :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY_LONG} STR_BRIDGE_NAME_SUSPENSION_STEEL :Pont penjant d'acer STR_BRIDGE_NAME_GIRDER_STEEL :Pont biga d'acer STR_BRIDGE_NAME_CANTILEVER_STEEL :Pont en mènsula d'acer diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index f4dc8b772c..ac1a5dd518 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -960,6 +960,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :כל 12 חוד STR_GAME_OPTIONS_LANGUAGE :{BLACK}שפה STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}בחר את שפת הממשק +STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% הסתיים) STR_GAME_OPTIONS_FULLSCREEN :{BLACK}מסך מלא STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}סמן תיבה זו כדי לשחק OpenTTD על כל המסך @@ -1701,6 +1702,7 @@ STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :{STRING} :הצ STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :השנה בה הודעות העיתונות מודפסות בצבע. לפני שנה זו הן מודפסות בשחור-לבן. STR_CONFIG_SETTING_STARTING_YEAR :{STRING} :שנת התחלה +STR_CONFIG_SETTING_ENDING_YEAR :ניקוד סוף שנה: {STRING} ###setting-zero-is-special STR_CONFIG_SETTING_ENDING_YEAR_ZERO :לעולם לא @@ -1711,6 +1713,7 @@ STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :מקורי STR_CONFIG_SETTING_ALLOW_SHARES :אפשר קניית מניות מחברות אחרות: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :כאשר מאופשר, מתיר קנייה ומכירה של מניות של חברות. מניות יהיו זמינות רק עבור חברות המגיעות לגיל מסוים +STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :גיל מינימלי לחברה לסחור במניותיה: {STRING} STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :אחוז הרווח מקטע נסיעה לתשלום במערכות הזנה: {STRING} STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :אחוז הרווח הניתן לקטעי ביניים במערכות הזנה, דבר הנותן שליטה מוגברת על ההכנסות @@ -1763,6 +1766,7 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :לינארי STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :מיקום עצים במהלך המשחק: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :שלוט בהופעה אקראית של עצים במהלך המשחק. זה עלול להשפיע על תעשיות המסתמכות על צמיחת עצים, לדוגמא מנסרות ###length 4 +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :גדל ומתפשט בכל מקום STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :אל תגדל, אל תתפשט {RED}(שובר מנסרות) STR_CONFIG_SETTING_TOOLBAR_POS :{STRING} :מיקום הסרגל העיקרי @@ -2143,6 +2147,7 @@ STR_NETWORK_SERVER_LIST_GAMESCRIPT :{SILVER}סקר STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}מוגן בסיסמה! STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}שרת מנותק STR_NETWORK_SERVER_LIST_SERVER_FULL :{SILVER}שרת מלא +STR_NETWORK_SERVER_LIST_SERVER_TOO_OLD :{SILVER}השרת ישן מדי STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}גרסה לא תואמת STR_NETWORK_SERVER_LIST_GRF_MISMATCH :{SILVER}אי התאמת קבצים גרפיים @@ -4318,6 +4323,7 @@ STR_AI_LIST_CANCEL :{BLACK}בטל STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}אל תשנה את התסריט STR_SCREENSHOT_CAPTION :{WHITE}צלם מסך +STR_SCREENSHOT_SCREENSHOT :תמונת מסך רגילה STR_SCREENSHOT_DEFAULTZOOM_SCREENSHOT :{BLACK}זום ברירת מחדל לצילום מסך STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}צילום מסך של כל המפה diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index 553fafc929..d7e4d82300 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -1926,13 +1926,13 @@ STR_CONFIG_SETTING_LINKGRAPH_TIME :Dağıtım graf STR_CONFIG_SETTING_LINKGRAPH_TIME_HELPTEXT :Bağlantı grafiğini oluşturan parçaların her tekrar hesaplaması için kullanılan zaman. Tekrar hesaplama başlatıldığında bu kadar gün sürecek bir işlem başlatılmış olur. Buraya daha kısa süreler girdikçe işlemin bitmesi gerekirken bitmemiş olma ihtimali artar. Ardından oyun ("lag") olana dek durur. Daha uzun süreler girdiğinizde güzergahlar değiştikçe dağıtımın güncellenmesi daha uzun sürer. STR_CONFIG_SETTING_DISTRIBUTION_PAX :Yolcular için dağıtım kipi: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :"simetrik" seçildiğinde A durağından B durağına taşınan ile B'den A'ya taşınan yolcu miktarı kabaca eşit olur. "asimetrik" seçildiğinde iki yönde de rastgele miktarda yolcu gönderilebilir. "el ile" seçildiğinde yolcular için otomatik dağıtım yapılmaz. +STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :"Simetrik" seçildiğinde A durağından B durağına taşınan ile B'den A'ya taşınan yolcu miktarı kabaca eşit olur. "Asimetrik" seçildiğinde iki yönde de rastgele miktarda yolcu gönderilebilir. "el ile" seçildiğinde yolcular için otomatik dağıtım yapılmaz. STR_CONFIG_SETTING_DISTRIBUTION_MAIL :Posta için dağıtım kipi: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :"simetrik" seçildiğinde A durağından B durağına gönderilen ile B'den A'ya gönderilen posta miktarı kabaca eşit olur. "asimetrik" seçildiğinde iki yönde de rastgele miktarda posta gönderilebilir. "el ile" seçildiğinde posta için otomatik dağıtım yapılmaz. +STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :"Simetrik" seçildiğinde A durağından B durağına gönderilen ile B'den A'ya gönderilen posta miktarı kabaca eşit olur. "Asimetrik" seçildiğinde iki yönde de rastgele miktarda posta gönderilebilir. "El ile" seçildiğinde posta için otomatik dağıtım yapılmaz. STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :ZIRHLI kargo sınıfı için dağıtım kipi: {STRING} STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :ZIRHLI kargo sınıfı ılıman iklimde değerli mallar, yarı-tropik iklimde elmaslar, veya yarı-soğuk iklimde altın içerir. NewGRF dosyaları bunu değiştirebilir. "Simetrik" olarak ayarlandığında A durağından B durağına gönderilen kargo miktarı, B'den A'ya gönderilene kabaca eşit olur. "Asimetrik" ise herhangi bir yönde rastgele miktarda kargo gönderilebileceğini gösterir. "El ile" seçildiğinde o kargo için otomatik dağıtım yapılmaz. Yarı-soğuk iklimde oynarken bu değeri "asimetrik" veya "el ile" olarak ayarlamanız tavsiye edilir, çünkü bankalar altınları altın madenine geri göndermez. Ilıman ve yarı-tropik iklim için aynı zamanda "simetrik" seçebilirsiniz, zira bankalar değerli malların bir kısmını malların geldiği kaynak bankaya geri gönderir. STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Diğer kargo sınıfları için dağılım kipi: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"asimetrik", kargonun iki yönde de rastgele miktarda gönderileceğini gösterir. "el ile" seçildiği takdirde o kargolar için otomatik dağılım yapılmaz. +STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"Asimetrik", kargonun iki yönde de rastgele miktarda gönderileceğini gösterir. "El ile" seçildiği takdirde o kargolar için otomatik dağılım yapılmaz. ###length 3 STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :el ile (manual) STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :asimetrik @@ -2699,6 +2699,10 @@ STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP :{BLACK}Sinyal s STR_SELECT_RAIL_BRIDGE_CAPTION :{WHITE}Tren Köprüsü Seç STR_SELECT_ROAD_BRIDGE_CAPTION :{WHITE}Köprü Seç STR_SELECT_BRIDGE_SELECTION_TOOLTIP :{BLACK}Köprü seçimi - tercih ettiğiniz köprüyü yapmak için tıklayın +STR_SELECT_BRIDGE_INFO_NAME :{GOLD}{STRING} +STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED :{GOLD}{STRING},{} {VELOCITY} +STR_SELECT_BRIDGE_INFO_NAME_COST :{GOLD}{0:STRING},{} {WHITE}{2:CURRENCY_LONG} +STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED_COST :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY_LONG} STR_BRIDGE_NAME_SUSPENSION_STEEL :Çelik, Asma STR_BRIDGE_NAME_GIRDER_STEEL :Çelik, Kirişli STR_BRIDGE_NAME_CANTILEVER_STEEL :Çelik, Ağ