diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index efb571db29..e6a9a0f672 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -981,12 +981,7 @@ static void window_new_ride_paint_ride_information( gfx_draw_string_left_clipped(dpi, STR_AVAILABLE_VEHICLES, &drawString, COLOUR_BLACK, x, y + 39, WW - 2); } - // Track designs are disabled in multiplayer, so don't say there are any designs available when in multiplayer - if (network_get_mode() != NETWORK_MODE_NONE) - { - _lastTrackDesignCount = 0; - } - else if (item.type != _lastTrackDesignCountRideType.type || item.entry_index != _lastTrackDesignCountRideType.entry_index) + if (item.type != _lastTrackDesignCountRideType.type || item.entry_index != _lastTrackDesignCountRideType.entry_index) { _lastTrackDesignCountRideType = item; _lastTrackDesignCount = get_num_track_designs(item); @@ -1047,17 +1042,7 @@ static void window_new_ride_select(rct_window* w) window_close(w); window_close_construction_windows(); - bool allowTrackDesigns = true; -#ifndef NETWORK_DISABLE - // TODO: FIX NETWORK TRACKS - // Until tracks work with the network this will disable them - if (network_get_mode() != NETWORK_MODE_NONE) - { - allowTrackDesigns = false; - } -#endif - - if (allowTrackDesigns && _lastTrackDesignCount > 0) + if (_lastTrackDesignCount > 0) { auto intent = Intent(WC_TRACK_DESIGN_LIST); intent.putExtra(INTENT_EXTRA_RIDE_TYPE, item.type); diff --git a/src/openrct2/actions/GameActionCompat.cpp b/src/openrct2/actions/GameActionCompat.cpp index 5815160294..ad155c9fb8 100644 --- a/src/openrct2/actions/GameActionCompat.cpp +++ b/src/openrct2/actions/GameActionCompat.cpp @@ -100,7 +100,7 @@ money32 ride_create_command(int32_t type, int32_t subType, int32_t flags, ride_i auto gameAction = RideCreateAction(type, subType, colour1, colour2); gameAction.SetFlags(flags); - auto r = GameActions::Execute(&gameAction); + auto r = GameActions::ExecuteNested(&gameAction); const RideCreateGameActionResult* res = static_cast(r.get()); // Callee's of this function expect MONEY32_UNDEFINED in case of failure. diff --git a/src/openrct2/actions/TrackDesignAction.cpp b/src/openrct2/actions/TrackDesignAction.cpp index 9b7c5a04af..c83abf0d58 100644 --- a/src/openrct2/actions/TrackDesignAction.cpp +++ b/src/openrct2/actions/TrackDesignAction.cpp @@ -14,6 +14,8 @@ #include "../object/ObjectRepository.h" #include "../ride/RideGroupManager.h" #include "../ride/TrackDesign.h" +#include "RideSetName.hpp" +#include "RideDemolishAction.hpp" #include "RideSetSetting.hpp" #include "RideSetVehiclesAction.hpp" @@ -107,7 +109,10 @@ GameActionResult::Ptr TrackDesignAction::Query() const } rct_string_id error_reason = gGameCommandErrorText; - ride_action_modify(ride, RIDE_MODIFY_DEMOLISH, GetFlags()); + auto gameAction = RideDemolishAction(ride->id, RIDE_MODIFY_DEMOLISH); + gameAction.SetFlags(GetFlags()); + + GameActions::ExecuteNested(&gameAction); if (cost == MONEY32_UNDEFINED) { return MakeResult(GA_ERROR::DISALLOWED, error_reason); @@ -217,7 +222,10 @@ GameActionResult::Ptr TrackDesignAction::Execute() const if (cost == MONEY32_UNDEFINED) { rct_string_id error_reason = gGameCommandErrorText; - ride_action_modify(ride, RIDE_MODIFY_DEMOLISH, GetFlags()); + auto gameAction = RideDemolishAction(ride->id, RIDE_MODIFY_DEMOLISH); + gameAction.SetFlags(GetFlags()); + + GameActions::ExecuteNested(&gameAction); return MakeResult(GA_ERROR::DISALLOWED, error_reason); } @@ -268,7 +276,9 @@ GameActionResult::Ptr TrackDesignAction::Execute() const ride->vehicle_colours[i].Ternary = _td.vehicle_additional_colour[i]; } - ride_set_name(ride, _td.name.c_str(), GAME_COMMAND_FLAG_APPLY); + auto gameAction = RideSetNameAction(ride->id, _td.name); + gameAction.SetFlags(GetFlags()); + GameActions::ExecuteNested(&gameAction); res->Cost = cost; res->rideIndex = ride->id; return res; diff --git a/src/openrct2/actions/TrackDesignAction.h b/src/openrct2/actions/TrackDesignAction.h index 1fd606856f..bc9e9f9e77 100644 --- a/src/openrct2/actions/TrackDesignAction.h +++ b/src/openrct2/actions/TrackDesignAction.h @@ -53,7 +53,7 @@ public: uint16_t GetActionFlags() const override { - return GameActionBase::GetActionFlags() | GA_FLAGS::CLIENT_ONLY; + return GameActionBase::GetActionFlags(); } void Serialise(DataSerialiser & stream) override @@ -61,6 +61,7 @@ public: GameAction::Serialise(stream); stream << DS_TAG(_loc); + _td.Serialise(stream); } GameActionResult::Ptr Query() const override; diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index c6b91dc10e..85789c8157 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -15,6 +15,7 @@ #include "../network/NetworkTypes.h" #include "../network/network.h" #include "../ride/Ride.h" +#include "../ride/TrackDesign.h" #include "../world/Location.hpp" #include "../world/TileElement.h" #include "DataSerialiserTag.h" @@ -353,6 +354,47 @@ template struct DataSerializerTraits struct DataSerializerTraits> +{ + static void encode(IStream* stream, const std::vector<_Ty>& val) + { + uint16_t len = (uint16_t)val.size(); + uint16_t swapped = ByteSwapBE(len); + stream->Write(&swapped); + + DataSerializerTraits<_Ty> s; + for (auto&& sub : val) + { + s.encode(stream, sub); + } + } + static void decode(IStream* stream, std::vector<_Ty>& val) + { + uint16_t len; + stream->Read(&len); + len = ByteSwapBE(len); + + DataSerializerTraits<_Ty> s; + for (auto i = 0; i < len; ++i) + { + _Ty sub; + s.decode(stream, sub); + val.push_back(sub); + } + } + static void log(IStream* stream, const std::vector<_Ty>& val) + { + stream->Write("{", 1); + DataSerializerTraits<_Ty> s; + for (auto&& sub : val) + { + s.log(stream, sub); + stream->Write("; ", 2); + } + stream->Write("}", 1); + } +}; + template<> struct DataSerializerTraits { static void encode(IStream* stream, const MapRange& v) @@ -516,3 +558,45 @@ template<> struct DataSerializerTraits stream->Write(cheatName, strlen(cheatName)); } }; + +template<> struct DataSerializerTraits +{ + static void encode(IStream* stream, const rct_object_entry& val) + { + uint32_t temp = ByteSwapBE(val.flags); + stream->Write(&temp); + stream->WriteArray(val.nameWOC, 12); + } + static void decode(IStream* stream, rct_object_entry& val) + { + uint32_t temp; + stream->Read(&temp); + val.flags = ByteSwapBE(temp); + const char* str = stream->ReadArray(12); + memcpy(val.nameWOC, str, 12); + } + static void log(IStream* stream, const rct_object_entry& val) + { + stream->WriteArray(val.name, 8); + } +}; + +template<> struct DataSerializerTraits +{ + static void encode(IStream* stream, const TrackDesignTrackElement& val) + { + stream->Write(&val.flags); + stream->Write(&val.type); + } + static void decode(IStream* stream, TrackDesignTrackElement& val) + { + stream->Read(&val.flags); + stream->Read(&val.type); + } + static void log(IStream* stream, const TrackDesignTrackElement& val) + { + char msg[128] = {}; + snprintf(msg, sizeof(msg), "TrackDesignElement(type = %d, flags = %d)", val.type, val.flags); + stream->Write(msg, strlen(msg)); + } +}; diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index da87c4dfb0..99dbce56d1 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -20,6 +20,7 @@ #include "../actions/MazePlaceTrackAction.hpp" #include "../actions/RideEntranceExitPlaceAction.hpp" #include "../actions/RideSetSetting.hpp" +#include "../actions/RideSetName.hpp" #include "../actions/RideSetVehiclesAction.hpp" #include "../actions/SmallSceneryPlaceAction.hpp" #include "../actions/SmallSceneryRemoveAction.hpp" @@ -30,6 +31,7 @@ #include "../audio/audio.h" #include "../core/File.h" #include "../core/String.hpp" +#include "../core/DataSerialiser.h" #include "../drawing/X8DrawingEngine.h" #include "../localisation/Localisation.h" #include "../localisation/StringIds.h" @@ -558,6 +560,57 @@ rct_string_id TrackDesign::CreateTrackDesignScenery() return STR_NONE; } +void TrackDesign::Serialise(DataSerialiser& stream) +{ + stream << DS_TAG(type); + stream << DS_TAG(vehicle_type); + stream << DS_TAG(cost); + stream << DS_TAG(flags); + stream << DS_TAG(ride_mode); + stream << DS_TAG(track_flags); + stream << DS_TAG(colour_scheme); + //stream << DS_TAG(vehicle_colours); todo + stream << DS_TAG(entrance_style); + stream << DS_TAG(total_air_time); + stream << DS_TAG(depart_flags); + stream << DS_TAG(number_of_trains); + stream << DS_TAG(number_of_cars_per_train); + stream << DS_TAG(min_waiting_time); + stream << DS_TAG(max_waiting_time); + stream << DS_TAG(operation_setting); + stream << DS_TAG(max_speed); + stream << DS_TAG(average_speed); + stream << DS_TAG(ride_length); + stream << DS_TAG(max_positive_vertical_g); + stream << DS_TAG(max_negative_vertical_g); + stream << DS_TAG(max_lateral_g); + stream << DS_TAG(inversions); + stream << DS_TAG(holes); + stream << DS_TAG(drops); + stream << DS_TAG(highest_drop_height); + stream << DS_TAG(excitement); + stream << DS_TAG(intensity); + stream << DS_TAG(nausea); + stream << DS_TAG(upkeep_cost); + stream << DS_TAG(track_spine_colour); + stream << DS_TAG(track_rail_colour); + stream << DS_TAG(track_support_colour); + stream << DS_TAG(flags2); + stream << DS_TAG(vehicle_object); + stream << DS_TAG(space_required_x); + stream << DS_TAG(space_required_y); + stream << DS_TAG(vehicle_additional_colour); + stream << DS_TAG(lift_hill_speed); + stream << DS_TAG(num_circuits); + + //stream << DS_TAG(maze_elements); + stream << DS_TAG(track_elements); + //stream << DS_TAG(entrance_elements); + //stream << DS_TAG(scenery_elements); + + stream << DS_TAG(name); +} + std::unique_ptr track_design_open(const utf8* path) { try diff --git a/src/openrct2/ride/TrackDesign.h b/src/openrct2/ride/TrackDesign.h index 68dd6ca65a..7168d2e16d 100644 --- a/src/openrct2/ride/TrackDesign.h +++ b/src/openrct2/ride/TrackDesign.h @@ -77,6 +77,8 @@ struct TrackDesignMazeElement }; }; +class DataSerialiser; + struct TrackDesign { uint8_t type; @@ -130,6 +132,7 @@ struct TrackDesign public: rct_string_id CreateTrackDesign(const Ride& ride); rct_string_id CreateTrackDesignScenery(); + void Serialise(DataSerialiser& stream); private: uint8_t _saveDirection;