Try to fix cmclient command callbacks
This commit is contained in:
@@ -74,7 +74,7 @@ inline constexpr size_t _callback_tuple_size = std::tuple_size_v<decltype(_callb
|
||||
|
||||
template <size_t... i>
|
||||
inline auto MakeCallbackTable(std::index_sequence<i...>) noexcept {
|
||||
return std::array<CommandCallback *, sizeof...(i)>{{ reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(std::get<i>(_callback_tuple)))... }}; // MingW64 fails linking when casting a pointer to its own type. To work around, cast it to some other type first.
|
||||
return std::array<::CommandCallback *, sizeof...(i)>{{ reinterpret_cast<::CommandCallback *>(reinterpret_cast<void(*)()>(std::get<i>(_callback_tuple)))... }}; // MingW64 fails linking when casting a pointer to its own type. To work around, cast it to some other type first.
|
||||
}
|
||||
/** Type-erased table of callbacks. */
|
||||
static auto _callback_table = MakeCallbackTable(std::make_index_sequence<_callback_tuple_size>{});\n
|
||||
@@ -87,7 +87,7 @@ struct CallbackArgsHelper<void(*const)(Commands, const CommandCost &, Targs...)>
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static size_t FindCallbackIndex(CommandCallback *callback) {
|
||||
static size_t FindCallbackIndex(::CommandCallback *callback) {
|
||||
if (auto it = std::find(std::cbegin(_callback_table), std::cend(_callback_table), callback); it != std::cend(_callback_table)) {
|
||||
return static_cast<size_t>(std::distance(std::cbegin(_callback_table), it));
|
||||
}
|
||||
@@ -102,7 +102,7 @@ template <Commands Tcmd, size_t Tcb, typename... Targs>
|
||||
constexpr auto MakeCallback() noexcept {
|
||||
/* Check if the callback matches with the command arguments. If not, don''t generate an Unpack proc. */
|
||||
using Tcallback = std::tuple_element_t<Tcb, decltype(_callback_tuple)>;
|
||||
if constexpr (std::is_same_v<Tcallback, CommandCallback * const> ||
|
||||
if constexpr (std::is_same_v<Tcallback, ::CommandCallback * const> ||
|
||||
std::is_same_v<Tcallback, CommandCallbackData * const> ||
|
||||
std::is_same_v<typename CommandTraits<Tcmd>::CbArgs, typename CallbackArgsHelper<Tcallback>::Args> ||
|
||||
(!std::is_void_v<typename CommandTraits<Tcmd>::RetTypes> && std::is_same_v<typename CallbackArgsHelper<typename CommandTraits<Tcmd>::RetCallbackProc const>::Args, typename CallbackArgsHelper<Tcallback>::Args>)) {
|
||||
@@ -170,8 +170,9 @@ def run():
|
||||
f.write(
|
||||
f' ~{name}() override {{}}\n'
|
||||
f'\n'
|
||||
f' bool do_post(CommandCallback * callback) override;\n'
|
||||
f' bool do_test() override;\n'
|
||||
f' bool _post(::CommandCallback * callback) override;\n'
|
||||
f' CommandCost _do(DoCommandFlag flags) override;\n'
|
||||
f' Commands get_command() override;\n'
|
||||
f'}};\n\n'
|
||||
)
|
||||
f.write(
|
||||
@@ -198,7 +199,7 @@ def run():
|
||||
' * but the table is not the same.\n'
|
||||
' */\n'
|
||||
'static constexpr auto _callback_tuple = std::make_tuple(\n'
|
||||
' (CommandCallback *)nullptr, // Make sure this is actually a pointer-to-function.\n'
|
||||
' (::CommandCallback *)nullptr, // Make sure this is actually a pointer-to-function.\n'
|
||||
)
|
||||
for i, cb in enumerate(callbacks):
|
||||
comma = ',' if i != len(callbacks) - 1 else ''
|
||||
@@ -226,12 +227,13 @@ def run():
|
||||
sep_args_type_list = ', ' + args_type_list
|
||||
sep_this_args_list = ', ' + this_args_list
|
||||
f.write(
|
||||
f'Commands {name}::get_command() {{ return {constant}; }}\n'
|
||||
f'static constexpr auto _{name}_dispatch = MakeDispatchTable<{constant}{sep_args_type_list}>();\n'
|
||||
f'bool {name}::do_post(CommandCallback *callback) {{\n'
|
||||
f'bool {name}::_post(::CommandCallback *callback) {{\n'
|
||||
f' return _{name}_dispatch[FindCallbackIndex(callback)](this->error, this->tile{sep_this_args_list});\n'
|
||||
'}\n'
|
||||
f'bool {name}::do_test() {{\n'
|
||||
f' return {cost_getter}(::Command<{constant}>::Do(DC_NONE, {test_args_list})).Succeeded();\n'
|
||||
f'CommandCost {name}::_do(DoCommandFlag flags) {{\n'
|
||||
f' return {cost_getter}(::Command<{constant}>::Do(flags, {test_args_list}));\n'
|
||||
'}\n'
|
||||
)
|
||||
f.write('\n')
|
||||
|
||||
@@ -42,6 +42,8 @@ add_files(
|
||||
cm_minimap.cpp
|
||||
cm_misc_gui.hpp
|
||||
cm_misc_gui.cpp
|
||||
cm_rail_gui.hpp
|
||||
cm_rail_gui.cpp
|
||||
cm_station_gui.hpp
|
||||
cm_station_gui.cpp
|
||||
cm_tooltips.hpp
|
||||
|
||||
@@ -128,7 +128,7 @@ up<Command> GetBlueprintCommand(TileIndex start, const Blueprint::Item &item) {
|
||||
end_tile = new_tile;
|
||||
tdir = NextTrackdir(tdir);
|
||||
}
|
||||
return make_up<cmd::BuildRailroadTrack>(
|
||||
return std::make_unique<cmd::BuildRailroadTrack>(
|
||||
end_tile,
|
||||
start_tile,
|
||||
_cur_railtype,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "../group_cmd.h"
|
||||
#include "../engine_type.h"
|
||||
#include "../livery.h"
|
||||
#include "../network/network_type.h"
|
||||
#include "../misc_cmd.h"
|
||||
#include "../news_type.h"
|
||||
#include "../object_type.h"
|
||||
@@ -23,43 +24,59 @@ enum StationClassID : byte;
|
||||
|
||||
namespace citymania {
|
||||
|
||||
typedef std::function<bool(bool)> CommandCallback;
|
||||
|
||||
extern bool _auto_command;
|
||||
extern CommandCallback _current_callback;
|
||||
|
||||
class Command {
|
||||
public:
|
||||
TileIndex tile = 0;
|
||||
bool automatic = false;
|
||||
CompanyID company = INVALID_COMPANY;
|
||||
StringID error = (StringID)0;
|
||||
CommandCallback callback = nullptr;
|
||||
|
||||
Command() {}
|
||||
Command(TileIndex tile) :tile{tile} {}
|
||||
virtual ~Command() {}
|
||||
|
||||
virtual bool do_post(CommandCallback *callback)=0;
|
||||
virtual bool do_test()=0;
|
||||
virtual bool _post(::CommandCallback *callback)=0;
|
||||
virtual CommandCost _do(DoCommandFlag flags)=0;
|
||||
virtual Commands get_command()=0;
|
||||
|
||||
template <typename Tcallback>
|
||||
bool post(Tcallback callback) {
|
||||
CompanyID old = _current_company;
|
||||
if (this->company != INVALID_COMPANY)
|
||||
_current_company = company;
|
||||
bool res = this->do_post(reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)));
|
||||
_auto_command = this->automatic;
|
||||
_current_callback = this->callback;
|
||||
bool res = this->_post(reinterpret_cast<::CommandCallback *>(reinterpret_cast<void(*)()>(callback)));
|
||||
assert(_current_callback == nullptr);
|
||||
_current_callback = nullptr;
|
||||
_auto_command = false;
|
||||
_current_company = old;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool post() {
|
||||
return this->post<CommandCallback *>(nullptr);
|
||||
return this->post<::CommandCallback *>(nullptr);
|
||||
}
|
||||
|
||||
bool test() {
|
||||
CommandCost call(DoCommandFlag flags) {
|
||||
CompanyID old = _current_company;
|
||||
if (this->company != INVALID_COMPANY)
|
||||
_current_company = company;
|
||||
bool res = this->do_test();
|
||||
auto res = this->_do(flags);
|
||||
_current_company = old;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool test() {
|
||||
return this->call(DC_NONE).Succeeded();
|
||||
}
|
||||
|
||||
Command &with_tile(TileIndex tile) {
|
||||
this->tile = tile;
|
||||
return *this;
|
||||
@@ -79,6 +96,11 @@ public:
|
||||
this->company = company;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Command &with_callback(CommandCallback callback) {
|
||||
this->callback = callback;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namaespace citymania
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
#include "cm_commands.hpp"
|
||||
|
||||
#include "../command_func.h"
|
||||
#include "../debug.h"
|
||||
#include "../network/network.h"
|
||||
#include "../network/network_client.h"
|
||||
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace citymania {
|
||||
|
||||
@@ -14,6 +17,9 @@ const uint32 MAX_CALLBACK_LIFETIME = 30; // it should be executed within few fr
|
||||
|
||||
std::map<size_t, std::pair<uint32, std::vector<CommandCallback>>> _command_callbacks;
|
||||
std::queue<std::pair<size_t, uint32>> _command_sent;
|
||||
CommandCallback _current_callback = nullptr;
|
||||
bool _auto_command = false;
|
||||
std::queue<std::pair<size_t, CommandCallback>> _callback_queue;
|
||||
|
||||
uint GetCurrentQueueDelay();
|
||||
|
||||
@@ -24,11 +30,62 @@ void hash_combine(std::size_t& seed, const T& v, const Rest&... rest)
|
||||
(hash_combine(seed, rest), ...);
|
||||
}
|
||||
|
||||
size_t GetCommandHash(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text) {
|
||||
} // namespace citymania
|
||||
namespace std {
|
||||
template<typename T>
|
||||
struct hash<std::vector<T>> {
|
||||
typedef std::vector<T> argument_type;
|
||||
typedef std::size_t result_type;
|
||||
result_type operator()(argument_type const& in) const {
|
||||
size_t size = in.size();
|
||||
size_t seed = 0;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
citymania::hash_combine(seed, in[i]);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
namespace citymania {
|
||||
|
||||
size_t GetCommandHash(Commands cmd, CompanyID company_id, StringID err_msg, ::CommandCallback callback, TileIndex tile, const CommandDataBuffer &data) {
|
||||
size_t res = 0;
|
||||
// hash_combine(res, tile, p1, p2, cmd, text);
|
||||
hash_combine(res, cmd, (uint16)company_id, err_msg, callback, (uint32)tile, data);
|
||||
return res;
|
||||
}
|
||||
|
||||
void ExecuteCurrentCallback(const CommandCost &cost) {
|
||||
if (_current_callback != nullptr) {
|
||||
_current_callback(cost.Succeeded());
|
||||
_current_callback == nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BeforeNetworkCommandExecution(const CommandPacket* cp) {
|
||||
if (!cp->my_cmd) return;
|
||||
size_t hash = GetCommandHash(cp->cmd, cp->company, cp->err_msg, cp->callback, cp->tile, cp->data);
|
||||
while (!_callback_queue.empty() && _callback_queue.front().first != hash) {
|
||||
Debug(misc, 0, "CM Dismissing command from callback queue: cmd={}", cp->cmd);
|
||||
_callback_queue.pop();
|
||||
}
|
||||
if (_callback_queue.empty()) {
|
||||
Debug(misc, 0, "CM Received unexpected network command: cmd={}", cp->cmd);
|
||||
return;
|
||||
}
|
||||
_current_callback = _callback_queue.front().second;
|
||||
_callback_queue.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
void AfterNetworkCommandExecution(const CommandPacket* cp) {
|
||||
_current_callback = nullptr;
|
||||
}
|
||||
|
||||
void AddCommandCallback(const CommandPacket *cp) {
|
||||
size_t hash = GetCommandHash(cp->cmd, cp->company, cp->err_msg, cp->callback, cp->tile, cp->data);
|
||||
_callback_queue.push(std::make_pair(hash, _current_callback));
|
||||
_current_callback = nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
void AddCommandCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text, CommandCallback callback) {
|
||||
if (!_networking) {
|
||||
@@ -43,21 +100,8 @@ void AddCommandCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const
|
||||
// fprintf(stderr, "CALLBACK %lu (%u %u %u %u %s)\n", hash, tile, p1, p2, (uint)(cmd & CMD_ID_MASK), text.c_str());
|
||||
}
|
||||
|
||||
bool DoCommandWithCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, ::CommandCallback *callback, const std::string &text, CommandCallback cm_callback) {
|
||||
if (_networking) {
|
||||
AddCommandCallback(tile, p1, p2, cmd, text, cm_callback);
|
||||
return DoCommandP(tile, p1, p2, cmd, callback, text);
|
||||
}
|
||||
auto res = DoCommandP(tile, p1, p2, cmd, callback, text);
|
||||
cm_callback(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DoCommandWithCallback(const CommandContainer &cc, CommandCallback callback) {
|
||||
return DoCommandWithCallback(cc.tile, cc.p1, cc.p2, cc.cmd, cc.callback, cc.text, callback);
|
||||
}
|
||||
*/
|
||||
void HandleCommandExecution(bool res, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text) {
|
||||
//void HandleCommandExecution(bool res, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text) {
|
||||
/* FIXME
|
||||
auto hash = GetCommandHash(tile, p1, p2, cmd & CMD_ID_MASK, text);
|
||||
auto p = _command_callbacks.find(hash);
|
||||
@@ -66,7 +110,7 @@ void HandleCommandExecution(bool res, TileIndex tile, uint32 p1, uint32 p2, uint
|
||||
for (auto &cb : p->second.second)
|
||||
cb(res);
|
||||
_command_callbacks.erase(p); */
|
||||
}
|
||||
//}
|
||||
|
||||
void ClearOldCallbacks() {
|
||||
while(!_command_sent.empty() && _command_sent.front().second + MAX_CALLBACK_LIFETIME < _frame_counter) {
|
||||
@@ -107,16 +151,17 @@ void FlushCommandQueue() {
|
||||
void HandleNextClientFrame() {
|
||||
_commands_this_frame = 0;
|
||||
FlushCommandQueue();
|
||||
ClearOldCallbacks();
|
||||
// ClearOldCallbacks();
|
||||
}
|
||||
|
||||
/*void SendClientCommand(const CommandPacket *cp) {
|
||||
void SendClientCommand(const CommandPacket *cp) {
|
||||
AddCommandCallback(cp);
|
||||
if (_outgoing_queue.empty() && CanSendCommand()) {
|
||||
MyClient::SendCommand(cp);
|
||||
_commands_this_frame++;
|
||||
return;
|
||||
}
|
||||
_outgoing_queue.push(*cp);
|
||||
}*/
|
||||
}
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
@@ -3,21 +3,22 @@
|
||||
|
||||
#include "../command_type.h"
|
||||
#include "../tile_type.h"
|
||||
#include "../network/network_internal.h"
|
||||
|
||||
#include "generated/cm_gen_commands.hpp"
|
||||
|
||||
struct CommandPacket;
|
||||
|
||||
namespace citymania {
|
||||
|
||||
typedef std::function<bool(bool)> CommandCallback;
|
||||
// void AddCommandCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text, CommandCallback callback);
|
||||
// bool DoCommandWithCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, ::CommandCallback *callback, const std::string &text, CommandCallback cm_callback);
|
||||
// bool DoCommandWithCallback(const CommandContainer &cc, CommandCallback callback);
|
||||
void HandleCommandExecution(bool res, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text);
|
||||
// void HandleCommandExecution(bool res, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text);
|
||||
void AddCommandCallback(const CommandPacket *cp);
|
||||
void ExecuteCurrentCallback(const CommandCost &cost);
|
||||
void BeforeNetworkCommandExecution(const CommandPacket* cp);
|
||||
void AfterNetworkCommandExecution(const CommandPacket* cp);
|
||||
|
||||
void InitCommandQueue();
|
||||
void HandleNextClientFrame();
|
||||
// void SendClientCommand(const CommandPacket *cp);
|
||||
void SendClientCommand(const CommandPacket *cp);
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
|
||||
@@ -472,7 +472,7 @@ void ObjectHighlight::UpdateTiles() {
|
||||
auto add_track = [this, z](TileIndex tile, TileIndex end_tile, Trackdir trackdir, SpriteID palette, TileIndex point1, TileIndex point2) {
|
||||
if (trackdir == INVALID_TRACKDIR) return;
|
||||
|
||||
for(;;) {
|
||||
while(tile <= MapSize()) {
|
||||
this->sprites.emplace_back(
|
||||
RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, z * TILE_HEIGHT + 7 /* z_offset */),
|
||||
SPR_AUTORAIL_BASE + _AutorailTilehSprite[0][TrackdirToTrack(trackdir)],
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
extern const Station *_viewport_highlight_station;
|
||||
extern TileHighlightData _thd;
|
||||
extern void MarkCatchmentTilesDirty();
|
||||
|
||||
@@ -43,6 +43,10 @@ template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_up(Args&&...) = delete;
|
||||
|
||||
// template<typename T> const auto make_up = std::make_unique<T>;
|
||||
// template<typename T> const auto make_sp = std::make_shared<T>;
|
||||
template<typename T, class... Args> const auto make_sp = std::make_shared<T, Args...>;
|
||||
|
||||
|
||||
enum class GameType: uint8 {
|
||||
GENERIC = 0,
|
||||
@@ -65,9 +69,6 @@ enum class ControllerType: uint8 {
|
||||
TOWN_DEFENCE = 6,
|
||||
};
|
||||
|
||||
// template<typename T> const auto make_up = std::make_unique<T>;
|
||||
// template<typename T> const auto make_sp = std::make_shared<T>;
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -233,7 +233,7 @@ std::tuple<bool, bool, bool> CommandHelperBase::InternalPostBefore(Commands cmd,
|
||||
* However, in case of incoming network commands,
|
||||
* map generation or the pause button we do want
|
||||
* to execute. */
|
||||
bool estimate_only = citymania::_estimate_mod && IsLocalCompany() && !_generating_world && !network_command && !(flags & CMD_NO_EST);
|
||||
bool estimate_only = citymania::_estimate_mod && IsLocalCompany() && !_generating_world && !network_command && !(flags & CMD_NO_EST) && !citymania::_auto_command;
|
||||
|
||||
/* We're only sending the command, so don't do
|
||||
* fancy things for 'success'. */
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include "misc/endian_buffer.hpp"
|
||||
#include "tile_map.h"
|
||||
|
||||
struct CommandPacket;
|
||||
namespace citymania { extern void ExecuteCurrentCallback(const CommandCost &cost); }
|
||||
|
||||
/**
|
||||
* Define a default return value for a failed command.
|
||||
*
|
||||
@@ -338,6 +341,7 @@ protected:
|
||||
std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res, args));
|
||||
}
|
||||
}
|
||||
citymania::ExecuteCurrentCallback(ExtractCommandCost(res));
|
||||
}
|
||||
|
||||
return ExtractCommandCost(res).Succeeded();
|
||||
|
||||
@@ -286,14 +286,15 @@ void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *cal
|
||||
c.my_cmd = true;
|
||||
|
||||
_local_wait_queue.Append(&c);
|
||||
citymania::AddCommandCallback(&c);
|
||||
return;
|
||||
}
|
||||
|
||||
c.frame = 0; // The client can't tell which frame, so just make it 0
|
||||
|
||||
/* Clients send their command to the server and forget all about the packet */
|
||||
MyClient::SendCommand(&c);
|
||||
// FIXME citymania::SendClientCommand(&c);
|
||||
// MyClient::SendCommand(&c);
|
||||
citymania::SendClientCommand(&c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -542,6 +543,8 @@ CommandDataBuffer SanitizeCmdStrings(const CommandDataBuffer &data)
|
||||
template <Commands Tcmd, size_t Tcb>
|
||||
void UnpackNetworkCommand(const CommandPacket* cp)
|
||||
{
|
||||
citymania::BeforeNetworkCommandExecution(cp);
|
||||
auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp->data);
|
||||
Command<Tcmd>::PostFromNet(cp->err_msg, std::get<Tcb>(_callback_tuple), cp->my_cmd, cp->tile, args);
|
||||
citymania::AfterNetworkCommandExecution(cp);
|
||||
}
|
||||
|
||||
195
src/rail_gui.cpp
195
src/rail_gui.cpp
@@ -52,6 +52,7 @@
|
||||
#include "citymania/cm_hotkeys.hpp"
|
||||
#include "citymania/cm_highlight.hpp"
|
||||
#include "citymania/cm_station_gui.hpp"
|
||||
#include "citymania/cm_rail_gui.hpp"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
@@ -66,8 +67,6 @@ static bool _convert_signal_button; ///< convert signal button in the s
|
||||
static SignalVariant _cur_signal_variant; ///< set the signal variant (for signal GUI)
|
||||
static SignalType _cur_signal_type; ///< set the signal type (for signal GUI)
|
||||
|
||||
extern TileIndex _rail_track_endtile; // CM rail_cmd.cpp
|
||||
|
||||
static const int HOTKEY_MASK = 0x1000;
|
||||
static const int HOTKEY_POLYRAIL = 0x1000;
|
||||
static const int HOTKEY_NEW_POLYRAIL = 0x1001;
|
||||
@@ -111,17 +110,6 @@ void CcPlaySound_CONSTRUCTION_RAIL(Commands cmd, const CommandCost &result, Tile
|
||||
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
|
||||
}
|
||||
|
||||
static void GenericPlaceRail(TileIndex tile, Track track)
|
||||
{
|
||||
if (_remove_button_clicked) {
|
||||
Command<CMD_REMOVE_SINGLE_RAIL>::Post(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
|
||||
tile, track);
|
||||
} else {
|
||||
Command<CMD_BUILD_SINGLE_RAIL>::Post(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
|
||||
tile, _cur_railtype, track, _settings_client.gui.auto_remove_signals);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to add an additional rail-track at the entrance of a depot
|
||||
* @param tile Tile to use for adding the rail-track
|
||||
@@ -373,185 +361,6 @@ static void BuildRailClick_Remove(Window *w)
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME static CommandContainer DoRailroadTrackCmd(TileIndex start_tile, TileIndex end_tile, Track track)
|
||||
{
|
||||
CommandContainer ret = {
|
||||
start_tile, // tile
|
||||
end_tile, // p1
|
||||
((uint32)_cur_railtype | ((uint32)track << 6) | ((uint32)_settings_client.gui.auto_remove_signals << 11)), // p2
|
||||
_remove_button_clicked ?
|
||||
CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
|
||||
CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK), // cmd
|
||||
CcPlaySound_CONSTRUCTION_RAIL, // callback
|
||||
"" // text
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
namespace citymania {
|
||||
/*
|
||||
static bool DoAutodirTerraform(bool diagonal, TileIndex start_tile, TileIndex end_tile, Track track, CommandContainer &rail_cmd, TileIndex s1, TileIndex e1, TileIndex s2, TileIndex e2) {
|
||||
auto rail_callback = [rail_cmd, start_tile, end_tile, track, estimate=citymania::_estimate_mod](bool res) -> bool {
|
||||
if (DoCommand(&rail_cmd, DC_AUTO | DC_NO_WATER).GetErrorMessage() != STR_ERROR_ALREADY_BUILT ||
|
||||
_rail_track_endtile == INVALID_TILE) {
|
||||
if (!DoCommandP(&rail_cmd)) return false;
|
||||
}
|
||||
if (!estimate && _rail_track_endtile != INVALID_TILE)
|
||||
StoreRailPlacementEndpoints(start_tile, _rail_track_endtile, track, true);
|
||||
return res;
|
||||
};
|
||||
|
||||
auto h1 = TileHeight(s1);
|
||||
auto h2 = TileHeight(s2);
|
||||
uint32 diag_flag = diagonal ? 1 : 0;
|
||||
uint32 p2_1 = ((h1 < h2 ? LM_RAISE : LM_LEVEL) << 1) | diag_flag;
|
||||
uint32 p2_2 = ((h2 < h1 ? LM_RAISE : LM_LEVEL) << 1) | diag_flag;
|
||||
auto l1_fail = (!DoCommand(e1, s1, p2_1, DC_AUTO | DC_NO_WATER, CMD_LEVEL_LAND).Succeeded());
|
||||
auto l2_fail = (!DoCommand(e2, s2, p2_2, DC_AUTO | DC_NO_WATER, CMD_LEVEL_LAND).Succeeded());
|
||||
if (l1_fail && l2_fail) return rail_callback(true);
|
||||
if (l2_fail) return citymania::DoCommandWithCallback(e1, s1, p2_1, CMD_LEVEL_LAND, CcTerraform, "", rail_callback);
|
||||
if (!l1_fail) DoCommandP(e1, s1, p2_1, CMD_LEVEL_LAND, CcTerraform);
|
||||
return citymania::DoCommandWithCallback(e2, s2, p2_2, CMD_LEVEL_LAND, CcTerraform, "", rail_callback);
|
||||
}
|
||||
|
||||
static bool HandleAutodirTerraform(TileIndex start_tile, TileIndex end_tile, Track track, CommandContainer &rail_cmd) {
|
||||
bool eq = (TileX(end_tile) - TileY(end_tile) == TileX(start_tile) - TileY(start_tile));
|
||||
bool ez = (TileX(end_tile) + TileY(end_tile) == TileX(start_tile) + TileY(start_tile));
|
||||
// StoreRailPlacementEndpoints(start_tile, end_tile, track, true);
|
||||
switch (_thd.cm_poly_dir) {
|
||||
case TRACKDIR_X_NE:
|
||||
return DoAutodirTerraform(false, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 1, 0), end_tile,
|
||||
TILE_ADDXY(start_tile, 1, 1), TILE_ADDXY(end_tile, 0, 1));
|
||||
break;
|
||||
case TRACKDIR_X_SW:
|
||||
return DoAutodirTerraform(false, start_tile, end_tile, track, rail_cmd,
|
||||
start_tile, TILE_ADDXY(end_tile, 1, 0),
|
||||
TILE_ADDXY(start_tile, 0, 1), TILE_ADDXY(end_tile, 1, 1));
|
||||
break;
|
||||
case TRACKDIR_Y_SE:
|
||||
return DoAutodirTerraform(false, start_tile, end_tile, track, rail_cmd,
|
||||
start_tile, TILE_ADDXY(end_tile, 0, 1),
|
||||
TILE_ADDXY(start_tile, 1, 0), TILE_ADDXY(end_tile, 1, 1));
|
||||
break;
|
||||
case TRACKDIR_Y_NW:
|
||||
return DoAutodirTerraform(false, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 0, 1), end_tile,
|
||||
TILE_ADDXY(start_tile, 1, 1), TILE_ADDXY(end_tile, 1, 0));
|
||||
break;
|
||||
case TRACKDIR_LEFT_N: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 1, 0), TILE_ADDXY(end_tile, eq, 0),
|
||||
TILE_ADDXY(start_tile, 1, 1), TILE_ADDXY(end_tile, 0, !eq));
|
||||
break;
|
||||
}
|
||||
case TRACKDIR_RIGHT_N: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 0, 1), TILE_ADDXY(end_tile, 0, eq),
|
||||
TILE_ADDXY(start_tile, 1, 1), TILE_ADDXY(end_tile, !eq, 0));
|
||||
break;
|
||||
}
|
||||
case TRACKDIR_LEFT_S: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 1, 0), TILE_ADDXY(end_tile, 1, !eq),
|
||||
start_tile, TILE_ADDXY(end_tile, eq, 1));
|
||||
break;
|
||||
}
|
||||
case TRACKDIR_RIGHT_S: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 0, 1), TILE_ADDXY(end_tile, !eq, 1),
|
||||
start_tile, TILE_ADDXY(end_tile, 1, eq));
|
||||
break;
|
||||
}
|
||||
case TRACKDIR_UPPER_E: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
start_tile, TILE_ADDXY(end_tile, 0, !ez),
|
||||
TILE_ADDXY(start_tile, 1, 0), TILE_ADDXY(end_tile, !ez, 1));
|
||||
break;
|
||||
}
|
||||
case TRACKDIR_LOWER_E: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 1, 1), TILE_ADDXY(end_tile, ez, 1),
|
||||
TILE_ADDXY(start_tile, 1, 0), TILE_ADDXY(end_tile, 0, ez));
|
||||
break;
|
||||
}
|
||||
case TRACKDIR_UPPER_W: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
start_tile, TILE_ADDXY(end_tile, !ez, 0),
|
||||
TILE_ADDXY(start_tile, 0, 1), TILE_ADDXY(end_tile, 1, !ez));
|
||||
break;
|
||||
}
|
||||
case TRACKDIR_LOWER_W: {
|
||||
return DoAutodirTerraform(true, start_tile, end_tile, track, rail_cmd,
|
||||
TILE_ADDXY(start_tile, 1, 1), TILE_ADDXY(end_tile, 1, ez),
|
||||
TILE_ADDXY(start_tile, 0, 1), TILE_ADDXY(end_tile, ez, 0));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}*/
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
//FIXME
|
||||
static void DoRailroadTrack(Track track)
|
||||
{
|
||||
if (_remove_button_clicked) {
|
||||
Command<CMD_REMOVE_RAILROAD_TRACK>::Post(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
|
||||
TileVirtXY(_thd.selend.x, _thd.selend.y), TileVirtXY(_thd.selstart.x, _thd.selstart.y), track);
|
||||
} else {
|
||||
Command<CMD_BUILD_RAILROAD_TRACK>::Post(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
|
||||
TileVirtXY(_thd.selend.x, _thd.selend.y), TileVirtXY(_thd.selstart.x, _thd.selstart.y), _cur_railtype, track, _settings_client.gui.auto_remove_signals, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleAutodirPlacement()
|
||||
{
|
||||
Track trackstat = static_cast<Track>( _thd.drawstyle & HT_DIR_MASK); // 0..5
|
||||
|
||||
if (_thd.drawstyle & HT_RAIL) { // one tile case
|
||||
GenericPlaceRail(TileVirtXY(_thd.selend.x, _thd.selend.y), trackstat);
|
||||
return;
|
||||
}
|
||||
|
||||
DoRailroadTrack(trackstat);
|
||||
}
|
||||
// end FIXME
|
||||
|
||||
/*
|
||||
static void HandleAutodirPlacement()
|
||||
{
|
||||
Track track = (Track)(_thd.drawstyle & HT_DIR_MASK); // 0..5
|
||||
TileIndex start_tile = TileVirtXY(_thd.selstart.x, _thd.selstart.y);
|
||||
TileIndex end_tile = TileVirtXY(_thd.selend.x, _thd.selend.y);
|
||||
/* FIXME
|
||||
CommandContainer cmd = (_thd.drawstyle & HT_RAIL) ?
|
||||
GenericPlaceRailCmd(end_tile, track) : // one tile case
|
||||
DoRailroadTrackCmd(start_tile, end_tile, track); // multitile selection
|
||||
|
||||
/* When overbuilding existing tracks in polyline mode we want to move the
|
||||
* snap point over the last overbuilt track piece. In such case we don't
|
||||
* wan't to show any errors to the user. Don't execute the command right
|
||||
* away, first check if overbuilding. */
|
||||
/* if (citymania::_estimate_mod || !(_thd.place_mode & HT_POLY) || _remove_button_clicked) {
|
||||
if (!DoCommandP(&cmd)) return;
|
||||
} else if (_thd.cm_poly_terra) {
|
||||
citymania::HandleAutodirTerraform(start_tile, end_tile, track, cmd);
|
||||
return;
|
||||
} else if (DoCommand(&cmd, DC_AUTO | DC_NO_WATER).GetErrorMessage() != STR_ERROR_ALREADY_BUILT ||
|
||||
_rail_track_endtile == INVALID_TILE) {
|
||||
if (!DoCommandP(&cmd)) return;
|
||||
} */
|
||||
/* Save new snap points for the polyline tool, no matter if the command
|
||||
* succeeded, the snapping will be extended over overbuilt track pieces. */
|
||||
/*if (!citymania::_estimate_mod && _rail_track_endtile != INVALID_TILE) {
|
||||
StoreRailPlacementEndpoints(start_tile, _rail_track_endtile, track, true);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Build new signals or remove signals or (if only one tile marked) edit a signal.
|
||||
*
|
||||
@@ -1002,7 +811,7 @@ struct BuildRailToolbarWindow : Window {
|
||||
break;
|
||||
|
||||
case DDSP_PLACE_RAIL:
|
||||
HandleAutodirPlacement();
|
||||
citymania::HandleAutodirPlacement(_cur_railtype, _remove_button_clicked);
|
||||
break;
|
||||
|
||||
case DDSP_BUILD_SIGNALS:
|
||||
|
||||
Reference in New Issue
Block a user