OpenTTD Source 20260531-master-g0e951f3528
command_func.h
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef COMMAND_FUNC_H
11#define COMMAND_FUNC_H
12
13#include "command_type.h"
15#include "company_type.h"
16#include "company_func.h"
17#include "core/backup_type.hpp"
19#include "tile_map.h"
20
29
30void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data);
32
33bool IsValidCommand(Commands cmd);
34CommandFlags GetCommandFlags(Commands cmd);
35std::string_view GetCommandName(Commands cmd);
37
38template <Commands Tcmd>
39constexpr CommandFlags GetCommandFlags()
40{
42}
43
49static constexpr inline DoCommandFlags CommandFlagsToDCFlags(CommandFlags cmd_flags)
50{
51 DoCommandFlags flags = {};
53 if (cmd_flags.Test(CommandFlag::Auto)) flags.Set(DoCommandFlag::Auto);
55 return flags;
56}
57
64
69 bool IsTopLevel() const { return _counter == 1; }
70private:
71 static int _counter;
72};
73
74#if defined(__GNUC__) && !defined(__clang__)
75/*
76 * We cast specialized function pointers to a generic one, but don't use the
77 * converted value to call the function, which is safe, except that GCC
78 * helpfully thinks it is not.
79 *
80 * "Any pointer to function can be converted to a pointer to a different function type.
81 * Calling the function through a pointer to a different function type is undefined,
82 * but converting such pointer back to pointer to the original function type yields
83 * the pointer to the original function." */
84# pragma GCC diagnostic push
85# pragma GCC diagnostic ignored "-Wcast-function-type"
86# define SILENCE_GCC_FUNCTION_POINTER_CAST
87#endif
88
89template <Commands TCmd, typename T, bool THasTile> struct CommandHelper;
90
92protected:
93 static void InternalDoBefore(bool top_level, bool test);
94 static void InternalDoAfter(CommandCost &res, DoCommandFlags flags, bool top_level, bool test);
95 static std::tuple<bool, bool, bool> InternalPostBefore(Commands cmd, CommandFlags flags, TileIndex tile, StringID err_message, bool network_command);
96 static void InternalPostResult(CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd);
97 static bool InternalExecutePrepTest(CommandFlags cmd_flags, Backup<CompanyID> &cur_company);
98 static std::tuple<bool, bool, bool> InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, Backup<CompanyID> &cur_company);
99 static CommandCost InternalExecuteProcessResult(Commands cmd, CommandFlags cmd_flags, const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup<CompanyID> &cur_company);
100 static void LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed);
101};
102
109template <typename Tret>
111{
112 if constexpr (std::is_same_v<Tret, CommandCost>) {
113 return ret;
114 } else {
115 static_assert(std::is_same_v<std::tuple_element_t<0, Tret>, CommandCost>);
116 return std::get<0>(ret);
117 }
118}
119
121template <typename Tret>
123{
124 if constexpr (std::is_same_v<Tret, CommandCost>) {
125 return ret;
126 } else {
127 static_assert(std::is_same_v<std::tuple_element_t<0, Tret>, CommandCost>);
128 return std::get<0>(ret);
129 }
130}
131
139template <Commands Tcmd, typename Tret, typename... Targs>
140struct CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), true> : protected CommandHelperBase {
141private:
147 static inline Tret MakeResult(const CommandCost &cost)
148 {
149 Tret ret{};
150 ExtractCommandCost(ret) = cost;
151 return ret;
152 }
153
154public:
167 static Tret Do(DoCommandFlags flags, Targs... args)
168 {
169 if constexpr (std::is_same_v<TileIndex, std::tuple_element_t<0, std::tuple<Targs...>>>) {
170 /* Do not even think about executing out-of-bounds tile-commands. */
171 TileIndex tile = std::get<0>(std::make_tuple(args...));
172 if (tile != 0 && (tile >= Map::Size() || (!IsValidTile(tile) && !flags.Test(DoCommandFlag::AllTiles)))) return MakeResult(CMD_ERROR);
173 }
174
175 RecursiveCommandCounter counter{};
176
177 /* Only execute the test call if it's toplevel, or we're not execing. */
178 if (counter.IsTopLevel() || !flags.Test(DoCommandFlag::Execute)) {
179 InternalDoBefore(counter.IsTopLevel(), true);
180 Tret res = CommandTraits<Tcmd>::proc(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), args...);
181 InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(), true); // Can modify res.
182
183 if (ExtractCommandCost(res).Failed() || !flags.Test(DoCommandFlag::Execute)) return res;
184 }
185
186 /* Execute the command here. All cost-relevant functions set the expenses type
187 * themselves to the cost object at some point. */
188 InternalDoBefore(counter.IsTopLevel(), false);
189 Tret res = CommandTraits<Tcmd>::proc(flags, args...);
190 InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(), false);
191
192 return res;
193 }
194
201 static inline bool Post(StringID err_message, Targs... args) { return Post<CommandCallback>(err_message, nullptr, std::forward<Targs>(args)...); }
202
209 template <typename Tcallback>
210 static inline bool Post(Tcallback *callback, Targs... args) { return Post((StringID)0, callback, std::forward<Targs>(args)...); }
211
217 static inline bool Post(Targs... args) { return Post<CommandCallback>((StringID)0, nullptr, std::forward<Targs>(args)...); }
218
229 template <typename Tcallback>
230 static bool Post(StringID err_message, Tcallback *callback, Targs... args)
231 {
232 assert(::IsNetworkRegisteredCallback(reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback))));
233 return InternalPost(err_message, callback, true, false, std::forward_as_tuple(args...));
234 }
235
244 template <typename Tcallback>
245 static bool PostFromNet(StringID err_message, Tcallback *callback, bool my_cmd, std::tuple<Targs...> args)
246 {
247 return InternalPost(err_message, callback, my_cmd, true, std::move(args));
248 }
249
256 static void SendNet(StringID err_message, CompanyID company, Targs... args)
257 {
258 auto args_tuple = std::forward_as_tuple(args...);
259
260 ::NetworkSendCommand(Tcmd, err_message, nullptr, company, EndianBufferWriter<CommandDataBuffer>::FromValue(args_tuple));
261 }
262
273 template <typename Tcallback>
274 static Tret Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple<Targs...> args)
275 {
276 return Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)), my_cmd, estimate_only, false, location, std::move(args));
277 }
278
279protected:
284 template <class T>
285 static inline void SetClientIdHelper([[maybe_unused]] T &data)
286 {
287 if constexpr (std::is_same_v<ClientID, T>) {
288 if (data == INVALID_CLIENT_ID) data = CLIENT_ID_SERVER;
289 }
290 }
291
296 template <class Ttuple, size_t... Tindices>
297 static inline void SetClientIds(Ttuple &values, std::index_sequence<Tindices...>)
298 {
299 ((SetClientIdHelper(std::get<Tindices>(values))), ...);
300 }
301
307 template <template <typename...> typename Tt, typename T1, typename... Ts>
308 static inline Tt<Ts...> RemoveFirstTupleElement(const Tt<T1, Ts...> &tuple)
309 {
310 return std::apply([](auto &&, const auto&... args) { return std::tie(args...); }, tuple);
311 }
312
313 template <typename Tcallback>
314 static bool InternalPost(StringID err_message, Tcallback *callback, bool my_cmd, bool network_command, std::tuple<Targs...> args)
315 {
316 /* Where to show the message? */
317 TileIndex tile{};
318 if constexpr (std::is_same_v<TileIndex, std::tuple_element_t<0, decltype(args)>>) {
319 tile = std::get<0>(args);
320 }
321
322 return InternalPost(err_message, callback, my_cmd, network_command, tile, std::move(args));
323 }
324
325 template <typename Tcallback>
326 static bool InternalPost(StringID err_message, Tcallback *callback, bool my_cmd, bool network_command, TileIndex tile, std::tuple<Targs...> args)
327 {
328 /* Do not even think about executing out-of-bounds tile-commands. */
329 if (tile != 0 && (tile >= Map::Size() || (!IsValidTile(tile) && !GetCommandFlags<Tcmd>().Test(CommandFlag::AllTiles)))) return false;
330
331 auto [err, estimate_only, only_sending] = InternalPostBefore(Tcmd, GetCommandFlags<Tcmd>(), tile, err_message, network_command);
332 if (err) return false;
333
334 /* Only set client IDs when the command does not come from the network. */
335 if (!network_command && GetCommandFlags<Tcmd>().Test(CommandFlag::ClientID)) SetClientIds(args, std::index_sequence_for<Targs...>{});
336
337 Tret res = Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)), my_cmd, estimate_only, network_command, tile, args);
338 InternalPostResult(ExtractCommandCost(res), tile, estimate_only, only_sending, err_message, my_cmd);
339
340 if (!estimate_only && !only_sending && callback != nullptr) {
341 if constexpr (std::is_same_v<Tcallback, CommandCallback>) {
342 /* Callback that doesn't need any command arguments. */
343 callback(Tcmd, ExtractCommandCost(res), tile);
344 } else if constexpr (std::is_same_v<Tcallback, CommandCallbackData>) {
345 /* Generic callback that takes packed arguments as a buffer. */
346 if constexpr (std::is_same_v<Tret, CommandCost>) {
347 callback(Tcmd, ExtractCommandCost(res), EndianBufferWriter<CommandDataBuffer>::FromValue(args), {});
348 } else {
349 callback(Tcmd, ExtractCommandCost(res), EndianBufferWriter<CommandDataBuffer>::FromValue(args), EndianBufferWriter<CommandDataBuffer>::FromValue(RemoveFirstTupleElement(res)));
350 }
351 } else if constexpr (!std::is_same_v<Tret, CommandCost> && std::is_same_v<Tcallback *, typename CommandTraits<Tcmd>::RetCallbackProc>) {
352 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res));
353 } else {
354 /* Callback with arguments. We assume that the tile is only interesting if it actually is in the command arguments. */
355 if constexpr (std::is_same_v<Tret, CommandCost>) {
356 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd, res), args));
357 } else {
358 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res, args));
359 }
360 }
361 }
362
363 return ExtractCommandCost(res).Succeeded();
364 }
365
371 template <class T>
372 static inline bool ClientIdIsSet([[maybe_unused]] T &data)
373 {
374 if constexpr (std::is_same_v<ClientID, T>) {
375 return data != INVALID_CLIENT_ID;
376 } else {
377 return true;
378 }
379 }
380
386 template <class Ttuple, size_t... Tindices>
387 static inline bool AllClientIdsSet(Ttuple &values, std::index_sequence<Tindices...>)
388 {
389 return (ClientIdIsSet(std::get<Tindices>(values)) && ...);
390 }
391
392 template <class Ttuple>
393 static inline Money ExtractAdditionalMoney([[maybe_unused]] Ttuple &values)
394 {
395 if constexpr (std::is_same_v<std::tuple_element_t<1, Tret>, Money>) {
396 return std::get<1>(values);
397 } else {
398 return {};
399 }
400 }
401
402 static Tret Execute(StringID err_message, CommandCallback *callback, bool, bool estimate_only, bool network_command, TileIndex tile, std::tuple<Targs...> args)
403 {
404 /* Prevent recursion; it gives a mess over the network */
405 RecursiveCommandCounter counter{};
406 assert(counter.IsTopLevel());
407
408 /* Command flags are used internally */
409 constexpr CommandFlags cmd_flags = GetCommandFlags<Tcmd>();
410
411 if constexpr (cmd_flags.Test(CommandFlag::ClientID)) {
412 /* Make sure arguments are properly set to a ClientID also when processing external commands. */
413 assert(AllClientIdsSet(args, std::index_sequence_for<Targs...>{}));
414 }
415
417 if (!InternalExecutePrepTest(cmd_flags, cur_company)) {
418 cur_company.Trash();
419 return MakeResult(CMD_ERROR);
420 }
421
422 /* Test the command. */
423 DoCommandFlags flags = CommandFlagsToDCFlags(cmd_flags);
424 Tret res = std::apply(CommandTraits<Tcmd>::proc, std::tuple_cat(std::make_tuple(flags), args));
425
426 auto [exit_test, desync_log, send_net] = InternalExecuteValidateTestAndPrepExec(ExtractCommandCost(res), cmd_flags, estimate_only, network_command, cur_company);
427 if (exit_test) {
428 if (desync_log) LogCommandExecution(Tcmd, err_message, EndianBufferWriter<CommandDataBuffer>::FromValue(args), true);
429 cur_company.Restore();
430 return res;
431 }
432
433 /* If we are in network, and the command is not from the network
434 * send it to the command-queue and abort execution. */
435 if (send_net) {
436 ::NetworkSendCommand(Tcmd, err_message, callback, _current_company, EndianBufferWriter<CommandDataBuffer>::FromValue(args));
437 cur_company.Restore();
438
439 /* Don't return anything special here; no error, no costs.
440 * This way it's not handled by DoCommand and only the
441 * actual execution of the command causes messages. Also
442 * reset the storages as we've not executed the command. */
443 return {};
444 }
445
446 if (desync_log) LogCommandExecution(Tcmd, err_message, EndianBufferWriter<CommandDataBuffer>::FromValue(args), false);
447
448 /* Actually try and execute the command. */
449 Tret res2 = std::apply(CommandTraits<Tcmd>::proc, std::tuple_cat(std::make_tuple(flags | DoCommandFlag::Execute), args));
450
451 /* Convention: If the second result element is of type Money,
452 * this is the additional cash required for the command. */
453 Money additional_money{};
454 if constexpr (!std::is_same_v<Tret, CommandCost>) { // No short-circuiting for 'if constexpr'.
455 additional_money = ExtractAdditionalMoney(res2);
456 }
457
458 if constexpr (std::is_same_v<Tret, CommandCost>) {
459 return InternalExecuteProcessResult(Tcmd, cmd_flags, res, res2, additional_money, tile, cur_company);
460 } else {
461 ExtractCommandCost(res2) = InternalExecuteProcessResult(Tcmd, cmd_flags, ExtractCommandCost(res), ExtractCommandCost(res2), additional_money, tile, cur_company);
462 return res2;
463 }
464 }
465};
466
474template <Commands Tcmd, typename Tret, typename... Targs>
475struct CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), false> : CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), true>
476{
477 /* Do not allow Post without explicit location. */
478 static inline bool Post(StringID err_message, Targs... args) = delete;
479 template <typename Tcallback>
480 static inline bool Post(Tcallback *callback, Targs... args) = delete;
481 static inline bool Post(Targs... args) = delete;
482 template <typename Tcallback>
483 static bool Post(StringID err_message, Tcallback *callback, Targs... args) = delete;
484
492 static inline bool Post(StringID err_message, TileIndex location, Targs... args) { return Post<CommandCallback>(err_message, nullptr, location, std::forward<Targs>(args)...); }
493
501 template <typename Tcallback>
502 static inline bool Post(Tcallback *callback, TileIndex location, Targs... args) { return Post((StringID)0, callback, location, std::forward<Targs>(args)...); }
503
510 static inline bool Post(TileIndex location, Targs... args) { return Post<CommandCallback>((StringID)0, nullptr, location, std::forward<Targs>(args)...); }
511
521 template <typename Tcallback>
522 static inline bool Post(StringID err_message, Tcallback *callback, TileIndex location, Targs... args)
523 {
524 return CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), true>::InternalPost(err_message, callback, true, false, location, std::forward_as_tuple(args...));
525 }
526};
527
528#ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
529# pragma GCC diagnostic pop
530#endif
531
532template <Commands Tcmd>
534
535#endif /* COMMAND_FUNC_H */
Class for backupping variables and making sure they are restored later.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
Common return value for all commands.
bool Succeeded() const
Did this command succeed?
static std::tuple< bool, bool, bool > InternalPostBefore(Commands cmd, CommandFlags flags, TileIndex tile, StringID err_message, bool network_command)
Decide what to do with the command depending on current game state.
Definition command.cpp:200
static void InternalPostResult(CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd)
Process result of executing a command, possibly displaying any error to the player.
Definition command.cpp:231
static void InternalDoBefore(bool top_level, bool test)
Prepare for calling a command proc.
Definition command.cpp:162
static void LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed)
Helper to make a desync log for a command.
Definition command.cpp:260
static CommandCost InternalExecuteProcessResult(Commands cmd, CommandFlags cmd_flags, const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup< CompanyID > &cur_company)
Process the result of a command test run and execution run.
Definition command.cpp:341
static bool InternalExecutePrepTest(CommandFlags cmd_flags, Backup< CompanyID > &cur_company)
Prepare for the test run of a command proc call.
Definition command.cpp:271
static void InternalDoAfter(CommandCost &res, DoCommandFlags flags, bool top_level, bool test)
Process result after calling a command proc.
Definition command.cpp:175
static std::tuple< bool, bool, bool > InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, Backup< CompanyID > &cur_company)
Validate result of test run and prepare for real execution.
Definition command.cpp:301
CommandFlags GetCommandFlags(Commands cmd)
Get the command flags associated with the given command.
Definition command.cpp:113
CommandFlags GetCommandFlags(Commands cmd)
Get the command flags associated with the given command.
Definition command.cpp:113
CommandCost & ExtractCommandCost(Tret &ret)
Extract the CommandCost from a command proc result.
bool IsCommandAllowedWhilePaused(Commands cmd)
Returns whether the command is allowed while the game is paused.
Definition command.cpp:137
static constexpr DoCommandFlags CommandFlagsToDCFlags(CommandFlags cmd_flags)
Extracts the DC flags needed for DoCommand from the flags returned by GetCommandFlags.
bool IsNetworkRegisteredCallback(CommandCallback *callback)
Helper function to ensure that callbacks used when Posting commands are actually registered for the n...
std::string_view GetCommandName(Commands cmd)
Get the name of the given command.
Definition command.cpp:125
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
bool IsValidCommand(Commands cmd)
This function range-checks a Commands.
Definition command.cpp:103
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data)
Prepare a DoCommand to be send over the network.
Types related to commands.
void CommandCallback(Commands cmd, const CommandCost &result, TileIndex tile)
Define a callback function for the client, after the command is finished.
@ Auto
don't allow building on structures
@ NoWater
don't allow building on water
@ Execute
execute the given command
@ AllTiles
allow this command also on TileType::Void tiles
@ Auto
set the DoCommandFlag::Auto flag on this command
@ NoWater
set the DoCommandFlag::NoWater flag on this command
@ AllTiles
allow this command also on TileType::Void tiles
@ ClientID
set p2 with the ClientID of the sending client.
@ Location
the command has implicit location argument.
std::vector< uint8_t > CommandDataBuffer
Storage buffer for serialized command data.
Commands
List of commands.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
Types related to companies.
Endian-aware buffer.
#define T
Climate temperate.
Definition engines.h:91
static void SetClientIds(Ttuple &values, ClientID client_id, std::index_sequence< Tindices... >)
Set all invalid ClientIDs to the proper value.
static void SetClientIdHelper(T &data, ClientID client_id)
Helper to process a single ClientID argument.
Types used for networking.
@ INVALID_CLIENT_ID
Client is not part of anything.
@ CLIENT_ID_SERVER
Servers always have this ID.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
Class to backup a specific variable and restore it later.
static bool Post(TileIndex location, Targs... args)
Shortcut for Post when not using a callback or an error message.
static bool Post(StringID err_message, Tcallback *callback, TileIndex location, Targs... args)
Post variant that takes a TileIndex (for error window location and text effects) for commands that do...
static bool Post(StringID err_message, TileIndex location, Targs... args)
Shortcut for Post when not using a callback.
static bool Post(Tcallback *callback, TileIndex location, Targs... args)
Shortcut for Post when not using an error message.
static bool Post(StringID err_message, Tcallback *callback, Targs... args)
Top-level network safe command execution for the current company.
static Tret Do(DoCommandFlags flags, Targs... args)
This function executes a given command.
static bool ClientIdIsSet(T &data)
Helper to process a single ClientID argument.
static bool Post(StringID err_message, Targs... args)
Shortcut for the long Post when not using a callback.
static void SetClientIdHelper(T &data)
Helper to process a single ClientID argument.
static bool PostFromNet(StringID err_message, Tcallback *callback, bool my_cmd, std::tuple< Targs... > args)
Execute a command coming from the network.
static Tret Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple< Targs... > args)
Top-level network safe command execution without safety checks.
static void SendNet(StringID err_message, CompanyID company, Targs... args)
Prepare a command to be send over the network.
static bool Post(Tcallback *callback, Targs... args)
Shortcut for the long Post when not using an error message.
static Tt< Ts... > RemoveFirstTupleElement(const Tt< T1, Ts... > &tuple)
Remove the first element of a tuple.
static Tret MakeResult(const CommandCost &cost)
Make a command proc result from a CommandCost.
static bool Post(Targs... args)
Shortcut for the long Post when not using a callback or an error message.
static bool AllClientIdsSet(Ttuple &values, std::index_sequence< Tindices... >)
Check if all ClientID arguments are set to valid values.
static void SetClientIds(Ttuple &values, std::index_sequence< Tindices... >)
Set all invalid ClientIDs to the proper value.
Defines the traits of a command.
static uint Size()
Get the size of the map.
Definition map_func.h:280
Helper class to keep track of command nesting level.
~RecursiveCommandCounter() noexcept
Decrement the recursion counter.
static int _counter
Number of instances of this class.
RecursiveCommandCounter() noexcept
Increment the recursion counter.
bool IsTopLevel() const
Are we in the top-level command execution?
Map writing/reading functions for tiles.
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92