summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Lutz <michi@icosahedron.de>2021-11-06 23:11:22 +0100
committerMichael Lutz <michi@icosahedron.de>2021-12-16 22:28:32 +0100
commitb0990fcff7358e839468e5cf811ffddc8b9d73e2 (patch)
tree08da5cbe48d5dcc46e8c539e0da1aa8f6233bad9 /src
parent4fc055d6e97e76faf53ff3f29e36a4a4549bf6e7 (diff)
downloadopenttd-b0990fcff7358e839468e5cf811ffddc8b9d73e2.tar.xz
Codechange: Make TileIndex a "strong" typedef to give it a distinct type.
This is accomplished by changing it to a single member struct with the appropriate operator overloads to make it all work with not too much source modifications.
Diffstat (limited to 'src')
-rw-r--r--src/build_vehicle_gui.cpp6
-rw-r--r--src/cargopacket.cpp2
-rw-r--r--src/company_func.h2
-rw-r--r--src/company_gui.cpp6
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/strong_typedef_type.hpp73
-rw-r--r--src/disaster_vehicle.cpp2
-rw-r--r--src/group_gui.cpp4
-rw-r--r--src/map.cpp2
-rw-r--r--src/map_func.h4
-rw-r--r--src/newgrf_railtype.cpp2
-rw-r--r--src/newgrf_roadtype.cpp2
-rw-r--r--src/news_gui.cpp2
-rw-r--r--src/saveload/oldloader_sl.cpp2
-rw-r--r--src/script/api/script_company.cpp2
-rw-r--r--src/script/api/script_types.hpp2
-rw-r--r--src/script/squirrel_helper.hpp3
-rw-r--r--src/tile_type.h24
-rw-r--r--src/tilearea_type.h30
-rw-r--r--src/timetable_gui.cpp8
-rw-r--r--src/town_gui.cpp4
-rw-r--r--src/tree_cmd.cpp4
-rw-r--r--src/water_cmd.cpp6
23 files changed, 160 insertions, 33 deletions
diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp
index 34d771090..7901b4574 100644
--- a/src/build_vehicle_gui.cpp
+++ b/src/build_vehicle_gui.cpp
@@ -1081,7 +1081,7 @@ struct BuildVehicleWindow : Window {
{
this->vehicle_type = type;
this->listview_mode = tile == INVALID_TILE;
- this->window_number = this->listview_mode ? (int)type : tile;
+ this->window_number = this->listview_mode ? (int)type : (int)tile;
this->sel_engine = INVALID_ENGINE;
@@ -1116,7 +1116,7 @@ struct BuildVehicleWindow : Window {
this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9);
- this->FinishInitNested(tile == INVALID_TILE ? (int)type : tile);
+ this->FinishInitNested(tile == INVALID_TILE ? (int)type : (int)tile);
this->owner = (tile != INVALID_TILE) ? GetTileOwner(tile) : _local_company;
@@ -1683,7 +1683,7 @@ void ShowBuildVehicleWindow(TileIndex tile, VehicleType type)
* so if tile == INVALID_TILE (Available XXX Window), use 'type' as unique number.
* As it always is a low value, it won't collide with any real tile
* number. */
- uint num = (tile == INVALID_TILE) ? (int)type : tile;
+ uint num = (tile == INVALID_TILE) ? (int)type : (int)tile;
assert(IsCompanyBuildableVehicleType(type));
diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp
index 86bba0261..e9c6e1aa7 100644
--- a/src/cargopacket.cpp
+++ b/src/cargopacket.cpp
@@ -75,7 +75,7 @@ CargoPacket::CargoPacket(uint16 count, byte days_in_transit, StationID source, T
source_id(source_id),
source(source),
source_xy(source_xy),
- loaded_at_xy(loaded_at_xy)
+ loaded_at_xy(loaded_at_xy.value)
{
assert(count != 0);
this->source_type = source_type;
diff --git a/src/company_func.h b/src/company_func.h
index 01f585910..97e1e6e82 100644
--- a/src/company_func.h
+++ b/src/company_func.h
@@ -27,7 +27,7 @@ void UpdateLandscapingLimits();
bool CheckCompanyHasMoney(CommandCost &cost);
void SubtractMoneyFromCompany(const CommandCost& cost);
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost& cost);
-CommandCost CheckOwnership(Owner owner, TileIndex tile = 0);
+CommandCost CheckOwnership(Owner owner, TileIndex tile = 0U);
CommandCost CheckTileOwnership(TileIndex tile);
extern CompanyID _local_company;
diff --git a/src/company_gui.cpp b/src/company_gui.cpp
index 6ab3b0aa7..7a6e68dea 100644
--- a/src/company_gui.cpp
+++ b/src/company_gui.cpp
@@ -2576,11 +2576,11 @@ struct CompanyWindow : Window
break;
case WID_C_BUY_SHARE:
- DoCommandP(CMD_BUY_SHARE_IN_COMPANY, STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS, 0, this->window_number, 0);
+ DoCommandP(CMD_BUY_SHARE_IN_COMPANY, STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS, (TileIndex)0, this->window_number, 0);
break;
case WID_C_SELL_SHARE:
- DoCommandP(CMD_SELL_SHARE_IN_COMPANY, STR_ERROR_CAN_T_SELL_25_SHARE_IN, 0, this->window_number, 0);
+ DoCommandP(CMD_SELL_SHARE_IN_COMPANY, STR_ERROR_CAN_T_SELL_25_SHARE_IN, (TileIndex)0, this->window_number, 0);
break;
case WID_C_COMPANY_PASSWORD:
@@ -2771,7 +2771,7 @@ struct BuyCompanyWindow : Window {
break;
case WID_BC_YES:
- DoCommandP(CMD_BUY_COMPANY, STR_ERROR_CAN_T_BUY_COMPANY, 0, this->window_number, 0);
+ DoCommandP(CMD_BUY_COMPANY, STR_ERROR_CAN_T_BUY_COMPANY, (TileIndex)0, this->window_number, 0);
break;
}
}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b94ed77e9..1c14067ae 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -28,4 +28,5 @@ add_files(
smallvec_type.hpp
span_type.hpp
string_compare_type.hpp
+ strong_typedef_type.hpp
)
diff --git a/src/core/strong_typedef_type.hpp b/src/core/strong_typedef_type.hpp
new file mode 100644
index 000000000..b5df28b2f
--- /dev/null
+++ b/src/core/strong_typedef_type.hpp
@@ -0,0 +1,73 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file strong_typedef_type.hpp Type (helpers) for making a strong typedef that is a distinct type. */
+
+#ifndef STRONG_TYPEDEF_TYPE_HPP
+#define STRONG_TYPEDEF_TYPE_HPP
+
+/** Non-templated base for #StrongTypedef for use with type trait queries. */
+struct StrongTypedefBase {};
+
+/**
+ * Templated helper to make a type-safe 'typedef' representing a single POD value.
+ * A normal 'typedef' is not distinct from its base type and will be treated as
+ * identical in many contexts. This class provides a distinct type that can still
+ * be assign from and compared to values of its base type.
+ *
+ * @note This is meant to be used as a base class, not directly.
+ * @tparam T Storage type
+ * @tparam Tthis Type of the derived class (i.e. the concrete usage of this class).
+ */
+template <class T, class Tthis>
+struct StrongTypedef : StrongTypedefBase {
+ using Type = T;
+
+ T value{}; ///< Backing storage field.
+
+ constexpr StrongTypedef() = default;
+ constexpr StrongTypedef(const StrongTypedef &o) = default;
+ constexpr StrongTypedef(StrongTypedef &&o) = default;
+
+ constexpr StrongTypedef(const T &value) : value(value) {}
+
+ constexpr Tthis &operator =(const StrongTypedef &rhs) { this->value = rhs.value; return static_cast<Tthis &>(*this); }
+ constexpr Tthis &operator =(StrongTypedef &&rhs) { this->value = std::move(rhs.value); return static_cast<Tthis &>(*this); }
+ constexpr Tthis &operator =(const T &rhs) { this->value = rhs; return static_cast<Tthis &>(*this); }
+
+ explicit constexpr operator T() const { return this->value; }
+
+ constexpr bool operator ==(const StrongTypedef &rhs) const { return this->value == rhs.value; }
+ constexpr bool operator !=(const StrongTypedef &rhs) const { return this->value != rhs.value; }
+ constexpr bool operator ==(const T &rhs) const { return this->value == rhs; }
+ constexpr bool operator !=(const T &rhs) const { return this->value != rhs; }
+};
+
+/**
+ * Extension of #StrongTypedef with operators for addition and subtraction.
+ * @tparam T Storage type
+ * @tparam Tthis Type of the derived class (i.e. the concrete usage of this class).
+ */
+template <class T, class Tthis>
+struct StrongIntegralTypedef : StrongTypedef<T, Tthis> {
+ using StrongTypedef<T, Tthis>::StrongTypedef;
+
+ constexpr Tthis &operator ++() { this->value++; return static_cast<Tthis &>(*this); }
+ constexpr Tthis &operator --() { this->value--; return static_cast<Tthis &>(*this); }
+ constexpr Tthis operator ++(int) { auto res = static_cast<Tthis &>(*this); this->value++; return res; }
+ constexpr Tthis operator --(int) { auto res = static_cast<Tthis &>(*this); this->value--; return res; }
+
+ constexpr Tthis &operator +=(const Tthis &rhs) { this->value += rhs.value; return *static_cast<Tthis *>(this); }
+ constexpr Tthis &operator -=(const Tthis &rhs) { this->value -= rhs.value; return *static_cast<Tthis *>(this); }
+
+ constexpr Tthis operator +(const Tthis &rhs) const { return Tthis{ this->value + rhs.value }; }
+ constexpr Tthis operator -(const Tthis &rhs) const { return Tthis{ this->value - rhs.value }; }
+ constexpr Tthis operator +(const T &rhs) const { return Tthis{ this->value + rhs }; }
+ constexpr Tthis operator -(const T &rhs) const { return Tthis{ this->value - rhs }; }
+};
+
+#endif /* STRONG_TYPEDEF_TYPE_HPP */
diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp
index 126e48f5f..63f4188a8 100644
--- a/src/disaster_vehicle.cpp
+++ b/src/disaster_vehicle.cpp
@@ -941,7 +941,7 @@ void ReleaseDisastersTargetingIndustry(IndustryID i)
/* primary disaster vehicles that have chosen target */
if (v->subtype == ST_AIRPLANE || v->subtype == ST_HELICOPTER) {
/* if it has chosen target, and it is this industry (yes, dest_tile is IndustryID here), set order to "leaving map peacefully" */
- if (v->current_order.GetDestination() > 0 && v->dest_tile == i) v->current_order.SetDestination(3);
+ if (v->current_order.GetDestination() > 0 && v->dest_tile == (uint32)i) v->current_order.SetDestination(3);
}
}
}
diff --git a/src/group_gui.cpp b/src/group_gui.cpp
index e9ded9536..8beab1884 100644
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -641,7 +641,7 @@ public:
if (confirmed) {
VehicleGroupWindow *w = (VehicleGroupWindow*)win;
w->vli.index = ALL_GROUP;
- DoCommandP(CMD_DELETE_GROUP, STR_ERROR_GROUP_CAN_T_DELETE, 0, w->group_confirm, 0);
+ DoCommandP(CMD_DELETE_GROUP, STR_ERROR_GROUP_CAN_T_DELETE, (TileIndex)0, w->group_confirm, 0);
}
}
@@ -965,7 +965,7 @@ public:
case ADI_REMOVE_ALL: // Remove all Vehicles from the selected group
assert(Group::IsValidID(this->vli.index));
- DoCommandP(CMD_REMOVE_ALL_VEHICLES_GROUP, STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES, 0, this->vli.index, 0);
+ DoCommandP(CMD_REMOVE_ALL_VEHICLES_GROUP, STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES, (TileIndex)0, this->vli.index, 0);
break;
default: NOT_REACHED();
}
diff --git a/src/map.cpp b/src/map.cpp
index 308e28e49..2a08d656e 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -84,7 +84,7 @@ TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
char buf[512];
seprintf(buf, lastof(buf), "TILE_ADD(%s) when adding 0x%.4X and 0x%.4X failed",
- exp, tile, add);
+ exp, (uint32)tile, add);
#if !defined(_MSC_VER)
fprintf(stderr, "%s:%d %s\n", file, line, buf);
#else
diff --git a/src/map_func.h b/src/map_func.h
index b02ba5777..34cc5ee0e 100644
--- a/src/map_func.h
+++ b/src/map_func.h
@@ -204,7 +204,7 @@ static inline TileIndex TileVirtXY(uint x, uint y)
*/
static inline uint TileX(TileIndex tile)
{
- return tile & MapMaxX();
+ return tile.value & MapMaxX();
}
/**
@@ -214,7 +214,7 @@ static inline uint TileX(TileIndex tile)
*/
static inline uint TileY(TileIndex tile)
{
- return tile >> MapLogX();
+ return tile.value >> MapLogX();
}
/**
diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp
index 471978952..c6e2b1c40 100644
--- a/src/newgrf_railtype.cpp
+++ b/src/newgrf_railtype.cpp
@@ -18,7 +18,7 @@
/* virtual */ uint32 RailTypeScopeResolver::GetRandomBits() const
{
- uint tmp = CountBits(this->tile + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE);
+ uint tmp = CountBits(static_cast<uint32>(this->tile + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE));
return GB(tmp, 0, 2);
}
diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp
index e4d29e4c5..8eb8325c7 100644
--- a/src/newgrf_roadtype.cpp
+++ b/src/newgrf_roadtype.cpp
@@ -18,7 +18,7 @@
/* virtual */ uint32 RoadTypeScopeResolver::GetRandomBits() const
{
- uint tmp = CountBits(this->tile + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE);
+ uint tmp = CountBits(static_cast<uint32>(this->tile + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE));
return GB(tmp, 0, 2);
}
diff --git a/src/news_gui.cpp b/src/news_gui.cpp
index 75b84a443..69ab19b3b 100644
--- a/src/news_gui.cpp
+++ b/src/news_gui.cpp
@@ -311,7 +311,7 @@ struct NewsWindow : Window {
/* Initialize viewport if it exists. */
NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_N_VIEWPORT);
if (nvp != nullptr) {
- nvp->InitializeViewport(this, ni->reftype1 == NR_VEHICLE ? 0x80000000 | ni->ref1 : GetReferenceTile(ni->reftype1, ni->ref1), ZOOM_LVL_NEWS);
+ nvp->InitializeViewport(this, ni->reftype1 == NR_VEHICLE ? 0x80000000 | ni->ref1 : (uint32)GetReferenceTile(ni->reftype1, ni->ref1), ZOOM_LVL_NEWS);
if (this->ni->flags & NF_NO_TRANSPARENT) nvp->disp_flags |= ND_NO_TRANSPARENCY;
if ((this->ni->flags & NF_INCOLOUR) == 0) {
nvp->disp_flags |= ND_SHADE_GREY;
diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp
index 8b33c02db..cfcc6bd37 100644
--- a/src/saveload/oldloader_sl.cpp
+++ b/src/saveload/oldloader_sl.cpp
@@ -1343,7 +1343,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
if (_cargo_count != 0 && CargoPacket::CanAllocateItem()) {
StationID source = (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
- TileIndex source_xy = (source != INVALID_STATION) ? Station::Get(source)->xy : 0;
+ TileIndex source_xy = (source != INVALID_STATION) ? Station::Get(source)->xy : (TileIndex)0;
v->cargo.Append(new CargoPacket(_cargo_count, _cargo_days, source, source_xy, source_xy));
}
}
diff --git a/src/script/api/script_company.cpp b/src/script/api/script_company.cpp
index dddcc950c..876ad84c5 100644
--- a/src/script/api/script_company.cpp
+++ b/src/script/api/script_company.cpp
@@ -238,7 +238,7 @@
EnforcePrecondition(false, company != COMPANY_INVALID);
/* Network commands only allow 0 to indicate invalid tiles, not INVALID_TILE */
- return ScriptObject::DoCommand(tile == INVALID_TILE ? 0 : tile , (uint32)(delta), company | expenses_type << 8 , CMD_CHANGE_BANK_BALANCE);
+ return ScriptObject::DoCommand(tile == INVALID_TILE ? (TileIndex)0U : tile , (uint32)(delta), company | expenses_type << 8 , CMD_CHANGE_BANK_BALANCE);
}
/* static */ bool ScriptCompany::BuildCompanyHQ(TileIndex tile)
diff --git a/src/script/api/script_types.hpp b/src/script/api/script_types.hpp
index 0d652a2d2..a570aabf7 100644
--- a/src/script/api/script_types.hpp
+++ b/src/script/api/script_types.hpp
@@ -82,6 +82,7 @@
#include "../../core/overflowsafe_type.hpp"
#include "../../company_type.h"
+#include "../../tile_type.h"
#include <squirrel.h>
/* Define all types here, so we don't have to include the whole _type.h maze */
@@ -100,7 +101,6 @@ typedef uint32 StringID; ///< The ID of a string.
typedef uint16 SubsidyID; ///< The ID of a subsidy.
typedef uint16 StoryPageID; ///< The ID of a story page.
typedef uint16 StoryPageElementID; ///< The ID of a story page element.
-typedef uint32 TileIndex; ///< The ID of a tile (just named differently).
typedef uint16 TownID; ///< The ID of a town.
typedef uint32 VehicleID; ///< The ID of a vehicle.
diff --git a/src/script/squirrel_helper.hpp b/src/script/squirrel_helper.hpp
index 6a3ba6125..7308006fa 100644
--- a/src/script/squirrel_helper.hpp
+++ b/src/script/squirrel_helper.hpp
@@ -14,6 +14,7 @@
#include "../core/smallvec_type.hpp"
#include "../economy_type.h"
#include "../string_func.h"
+#include "../tile_type.h"
#include "squirrel_helper_type.hpp"
template <class CL, ScriptType ST> const char *GetClassName();
@@ -85,6 +86,7 @@ namespace SQConvert {
template <> inline int Return<int32> (HSQUIRRELVM vm, int32 res) { sq_pushinteger(vm, res); return 1; }
template <> inline int Return<int64> (HSQUIRRELVM vm, int64 res) { sq_pushinteger(vm, res); return 1; }
template <> inline int Return<Money> (HSQUIRRELVM vm, Money res) { sq_pushinteger(vm, res); return 1; }
+ template <> inline int Return<TileIndex> (HSQUIRRELVM vm, TileIndex res) { sq_pushinteger(vm, (int32)res.value); return 1; }
template <> inline int Return<bool> (HSQUIRRELVM vm, bool res) { sq_pushbool (vm, res); return 1; }
template <> inline int Return<char *> (HSQUIRRELVM vm, char *res) { if (res == nullptr) sq_pushnull(vm); else { sq_pushstring(vm, res, -1); free(res); } return 1; }
template <> inline int Return<const char *>(HSQUIRRELVM vm, const char *res) { if (res == nullptr) sq_pushnull(vm); else { sq_pushstring(vm, res, -1); } return 1; }
@@ -103,6 +105,7 @@ namespace SQConvert {
template <> inline int16 GetParam(ForceType<int16> , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; }
template <> inline int32 GetParam(ForceType<int32> , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; }
template <> inline int64 GetParam(ForceType<int64> , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; }
+ template <> inline TileIndex GetParam(ForceType<TileIndex> , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return TileIndex((uint32)(int32)tmp); }
template <> inline Money GetParam(ForceType<Money> , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger (vm, index, &tmp); return tmp; }
template <> inline bool GetParam(ForceType<bool> , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQBool tmp; sq_getbool (vm, index, &tmp); return tmp != 0; }
template <> inline void *GetParam(ForceType<void *> , HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer tmp; sq_getuserpointer(vm, index, &tmp); return tmp; }
diff --git a/src/tile_type.h b/src/tile_type.h
index 73fd0e97e..6b5514d90 100644
--- a/src/tile_type.h
+++ b/src/tile_type.h
@@ -10,6 +10,8 @@
#ifndef TILE_TYPE_H
#define TILE_TYPE_H
+#include "core/strong_typedef_type.hpp"
+
static const uint TILE_SIZE = 16; ///< Tile size in world coordinates.
static const uint TILE_UNIT_MASK = TILE_SIZE - 1; ///< For masking in/out the inner-tile world coordinate units.
static const uint TILE_PIXELS = 32; ///< Pixel distance between tile columns/rows in #ZOOM_LVL_BASE.
@@ -80,11 +82,29 @@ enum TropicZone {
/**
* The index/ID of a Tile.
*/
-typedef uint32 TileIndex;
+struct TileIndex : StrongIntegralTypedef<uint32, TileIndex> {
+ using StrongIntegralTypedef<uint32, TileIndex>::StrongIntegralTypedef;
+
+ /** Implicit conversion to the base type for e.g. array indexing. */
+ constexpr operator uint32() const { return this->value; }
+
+ /* Import operators from the base class into our overload set. */
+ using StrongIntegralTypedef::operator ==;
+ using StrongIntegralTypedef::operator !=;
+ using StrongIntegralTypedef::operator +;
+ using StrongIntegralTypedef::operator -;
+
+ /* Add comparison and add/sub for signed ints as e.g. 0 is signed and will
+ * match ambiguously when only unsigned overloads are present. */
+ constexpr bool operator ==(int rhs) const { return this->value == (uint32)rhs; }
+ constexpr bool operator !=(int rhs) const { return this->value != (uint32)rhs; }
+ constexpr TileIndex operator +(int rhs) const { return { (uint32)(this->value + rhs) }; }
+ constexpr TileIndex operator -(int rhs) const { return { (uint32)(this->value - rhs) }; }
+};
/**
* The very nice invalid tile marker
*/
-static const TileIndex INVALID_TILE = (TileIndex)-1;
+static inline constexpr TileIndex INVALID_TILE = TileIndex{ (uint32)-1 };
#endif /* TILE_TYPE_H */
diff --git a/src/tilearea_type.h b/src/tilearea_type.h
index e6d9bad60..b6af998a7 100644
--- a/src/tilearea_type.h
+++ b/src/tilearea_type.h
@@ -147,6 +147,36 @@ public:
* Allocate a new iterator that is a copy of this one.
*/
virtual TileIterator *Clone() const = 0;
+
+ /**
+ * Equality comparison.
+ */
+ bool operator ==(const TileIterator &rhs) const
+ {
+ return this->tile == rhs.tile;
+ }
+ /**
+ * Inequality comparison.
+ */
+ bool operator !=(const TileIterator &rhs) const
+ {
+ return this->tile != rhs.tile;
+ }
+
+ /**
+ * Equality comparison.
+ */
+ bool operator ==(const TileIndex &rhs) const
+ {
+ return this->tile == rhs;
+ }
+ /**
+ * Inequality comparison.
+ */
+ bool operator !=(const TileIndex &rhs) const
+ {
+ return this->tile != rhs;
+ }
};
/** Iterator to iterate over a tile area (rectangle) of the map. */
diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp
index 00ab50115..a205a505e 100644
--- a/src/timetable_gui.cpp
+++ b/src/timetable_gui.cpp
@@ -578,25 +578,25 @@ struct TimetableWindow : Window {
case WID_VT_CLEAR_TIME: { // Clear waiting time.
uint32 p1 = PackTimetableArgs(v, this->sel_index, false);
- DoCommandP(CMD_CHANGE_TIMETABLE, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, 0, p1, 0);
+ DoCommandP(CMD_CHANGE_TIMETABLE, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, (TileIndex)0, p1, 0);
break;
}
case WID_VT_CLEAR_SPEED: { // Clear max speed button.
uint32 p1 = PackTimetableArgs(v, this->sel_index, true);
- DoCommandP(CMD_CHANGE_TIMETABLE, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, 0, p1, UINT16_MAX);
+ DoCommandP(CMD_CHANGE_TIMETABLE, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, (TileIndex)0, p1, UINT16_MAX);
break;
}
case WID_VT_RESET_LATENESS: // Reset the vehicle's late counter.
- DoCommandP(CMD_SET_VEHICLE_ON_TIME, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, 0, v->index, 0);
+ DoCommandP(CMD_SET_VEHICLE_ON_TIME, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, (TileIndex)0, v->index, 0);
break;
case WID_VT_AUTOFILL: { // Autofill the timetable.
uint32 p2 = 0;
if (!HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(p2, 0);
if (_ctrl_pressed) SetBit(p2, 1);
- DoCommandP(CMD_AUTOFILL_TIMETABLE, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, 0, v->index, p2);
+ DoCommandP(CMD_AUTOFILL_TIMETABLE, STR_ERROR_CAN_T_TIMETABLE_VEHICLE, (TileIndex)0, v->index, p2);
break;
}
diff --git a/src/town_gui.cpp b/src/town_gui.cpp
index 660b1ac98..cb88c5c00 100644
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -474,12 +474,12 @@ public:
_warn_town_no_roads = true;
}
- DoCommandP(CMD_EXPAND_TOWN, STR_ERROR_CAN_T_EXPAND_TOWN, 0, this->window_number, 0);
+ DoCommandP(CMD_EXPAND_TOWN, STR_ERROR_CAN_T_EXPAND_TOWN, (TileIndex)0, this->window_number, 0);
break;
}
case WID_TV_DELETE: // delete town - only available on Scenario editor
- DoCommandP(CMD_DELETE_TOWN, STR_ERROR_TOWN_CAN_T_DELETE, 0, this->window_number, 0);
+ DoCommandP(CMD_DELETE_TOWN, STR_ERROR_TOWN_CAN_T_DELETE, (TileIndex)0, this->window_number, 0);
break;
}
}
diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp
index a16ad7b82..ab439cd58 100644
--- a/src/tree_cmd.cpp
+++ b/src/tree_cmd.cpp
@@ -399,7 +399,7 @@ CommandCost CmdPlantTree(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32
Company *c = (_game_mode != GM_EDITOR) ? Company::GetIfValid(_current_company) : nullptr;
int limit = (c == nullptr ? INT32_MAX : GB(c->tree_limit, 16, 16));
- TileArea ta(tile, p2);
+ TileArea ta(tile, (TileIndex)p2);
for (TileIndex current_tile : ta) {
switch (GetTileType(current_tile)) {
case MP_TREES:
@@ -528,7 +528,7 @@ static void DrawTile_Trees(TileInfo *ti)
/* Do not draw trees when the invisible trees setting is set */
if (IsInvisibilitySet(TO_TREES)) return;
- uint tmp = CountBits(ti->tile + ti->x + ti->y);
+ uint tmp = CountBits(static_cast<uint32>(ti->tile + ti->x + ti->y));
uint index = GB(tmp, 0, 2) + (GetTreeType(ti->tile) << 2);
/* different tree styles above one of the grounds */
diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp
index 145b8084d..6e357f9c6 100644
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -454,7 +454,7 @@ CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32
/* Outside the editor you can only drag canals, and not areas */
if (_game_mode != GM_EDITOR) {
- TileArea ta(tile, p1);
+ TileArea ta(tile, (TileIndex)p1);
if (ta.w != 1 && ta.h != 1) return CMD_ERROR;
}
@@ -462,9 +462,9 @@ CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32
std::unique_ptr<TileIterator> iter;
if (HasBit(p2, 2)) {
- iter = std::make_unique<DiagonalTileIterator>(tile, p1);
+ iter = std::make_unique<DiagonalTileIterator>(tile, (TileIndex)p1);
} else {
- iter = std::make_unique<OrthogonalTileIterator>(tile, p1);
+ iter = std::make_unique<OrthogonalTileIterator>(tile, (TileIndex)p1);
}
for (; *iter != INVALID_TILE; ++(*iter)) {