diff --git a/src/openrct2/PlatformEnvironment.cpp b/src/openrct2/PlatformEnvironment.cpp index d47f1daa16..db9f90b2f6 100644 --- a/src/openrct2/PlatformEnvironment.cpp +++ b/src/openrct2/PlatformEnvironment.cpp @@ -39,26 +39,27 @@ static constexpr const char* DirectoryNamesRCT2[] = { }; static constexpr u8string_view DirectoryNamesOpenRCT2[] = { - u8"data", // DATA - u8"landscape", // LANDSCAPE - u8"language", // LANGUAGE - u8"chatlogs", // LOG_CHAT - u8"serverlogs", // LOG_SERVER - u8"keys", // NETWORK_KEY - u8"object", // OBJECT - u8"plugin", // PLUGIN - u8"save", // SAVE - u8"scenario", // SCENARIO - u8"screenshot", // SCREENSHOT - u8"sequence", // SEQUENCE - u8"shaders", // SHADER - u8"themes", // THEME - u8"track", // TRACK - u8"heightmap", // HEIGHTMAP - u8"replay", // REPLAY - u8"desyncs", // DESYNCS - u8"crash", // CRASH - u8"assetpack", // ASSET_PACK + u8"data", // DATA + u8"landscape", // LANDSCAPE + u8"language", // LANGUAGE + u8"chatlogs", // LOG_CHAT + u8"serverlogs", // LOG_SERVER + u8"keys", // NETWORK_KEY + u8"object", // OBJECT + u8"plugin", // PLUGIN + u8"save", // SAVE + u8"scenario", // SCENARIO + u8"screenshot", // SCREENSHOT + u8"sequence", // SEQUENCE + u8"shaders", // SHADER + u8"themes", // THEME + u8"track", // TRACK + u8"heightmap", // HEIGHTMAP + u8"replay", // REPLAY + u8"desyncs", // DESYNCS + u8"crash", // CRASH + u8"assetpack", // ASSET_PACK + u8"scenario_patches", // SCENARIO_PATCHES }; static constexpr u8string_view FileNames[] = { diff --git a/src/openrct2/PlatformEnvironment.h b/src/openrct2/PlatformEnvironment.h index b716da22df..e9f6d5c118 100644 --- a/src/openrct2/PlatformEnvironment.h +++ b/src/openrct2/PlatformEnvironment.h @@ -32,26 +32,27 @@ namespace OpenRCT2 enum class DIRID { - DATA, // Contains g1.dat, music etc. - LANDSCAPE, // Contains scenario editor landscapes (SC6). - LANGUAGE, // Contains language packs. - LOG_CHAT, // Contains chat logs. - LOG_SERVER, // Contains server logs. - NETWORK_KEY, // Contains the user's public and private keys. - OBJECT, // Contains objects. - PLUGIN, // Contains plugins (.js). - SAVE, // Contains saved games (SV6). - SCENARIO, // Contains scenarios (SC6). - SCREENSHOT, // Contains screenshots. - SEQUENCE, // Contains title sequences. - SHADER, // Contains OpenGL shaders. - THEME, // Contains interface themes. - TRACK, // Contains track designs. - HEIGHTMAP, // Contains heightmap data. - REPLAY, // Contains recorded replays. - LOG_DESYNCS, // Contains desync reports. - CRASH, // Contains crash dumps. - ASSET_PACK, // Contains asset packs. + DATA, // Contains g1.dat, music etc. + LANDSCAPE, // Contains scenario editor landscapes (SC6). + LANGUAGE, // Contains language packs. + LOG_CHAT, // Contains chat logs. + LOG_SERVER, // Contains server logs. + NETWORK_KEY, // Contains the user's public and private keys. + OBJECT, // Contains objects. + PLUGIN, // Contains plugins (.js). + SAVE, // Contains saved games (SV6). + SCENARIO, // Contains scenarios (SC6). + SCREENSHOT, // Contains screenshots. + SEQUENCE, // Contains title sequences. + SHADER, // Contains OpenGL shaders. + THEME, // Contains interface themes. + TRACK, // Contains track designs. + HEIGHTMAP, // Contains heightmap data. + REPLAY, // Contains recorded replays. + LOG_DESYNCS, // Contains desync reports. + CRASH, // Contains crash dumps. + ASSET_PACK, // Contains asset packs. + SCENARIO_PATCHES, // Contains scenario patches. }; enum class PATHID diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index f70648b2d0..ee73abdf55 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -995,6 +995,7 @@ + diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp new file mode 100644 index 0000000000..17814a7ace --- /dev/null +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -0,0 +1,129 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "ScenarioPatcher.h" + +#include "../Context.h" +#include "../PlatformEnvironment.h" +#include "../core/File.h" +#include "../core/Guard.hpp" +#include "../core/Json.hpp" +#include "../core/Path.hpp" +#include "../world/Location.hpp" +#include "../world/Map.h" +#include "../world/Surface.h" + +#include + +static u8string ToOwnershipJsonKey(int ownershipType) +{ + switch (ownershipType) + { + case OWNERSHIP_UNOWNED: + return "unowned"; + case OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED: + return "construction_rights_owned"; + case OWNERSHIP_OWNED: + return "owned"; + case OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE: + return "construction_rights_available"; + case OWNERSHIP_AVAILABLE: + return "available"; + } + Guard::Assert(0, "Unrecognized ownership type flag"); + return {}; +} + +static void ApplyLandOwnershipFixes(const json_t& landOwnershipFixes, int ownershipType) +{ + auto ownershipTypeKey = ToOwnershipJsonKey(ownershipType); + if (!landOwnershipFixes.contains(ownershipTypeKey)) + { + return; + } + + auto ownershipParameters = landOwnershipFixes[ownershipTypeKey]; + constexpr u8string_view coordinatesKey = "coordinates"; + if (!ownershipParameters.contains(coordinatesKey)) + { + Guard::Assert(0, "Cannot have ownership fix without coordinates array"); + return; + } + else if (!ownershipParameters[coordinatesKey].is_array()) + { + Guard::Assert(0, "Ownership fix coordinates should be an array"); + return; + } + + auto ownershipCoords = Json::AsArray(ownershipParameters[coordinatesKey]); + if (ownershipCoords.empty()) + { + Guard::Assert(0, "Ownership fix coordinates array should not be empty"); + return; + } + + const bool cannotDowngrade = ownershipParameters.contains("cannot_downgrade") + ? Json::GetBoolean(ownershipParameters["cannot_downgrade"], false) + : false; + std::initializer_list tiles; + for (size_t i = 0; i < ownershipCoords.size(); ++i) + { + if (!ownershipCoords[i].is_array()) + { + Guard::Assert(0, "Ownership fix coordinates should contain only arrays"); + return; + } + + auto coordinatesPair = Json::AsArray(ownershipCoords[i]); + if (coordinatesPair.size() != 2) + { + Guard::Assert(0, "Ownership fix coordinates sub array should have 2 elements"); + return; + } + FixLandOwnershipTilesWithOwnership( + { { Json::GetNumber(coordinatesPair[0]), Json::GetNumber(coordinatesPair[1]) } }, ownershipType, + cannotDowngrade); + } +} + +static void ApplyLandOwnershipFixes(const json_t& scenarioPatch) +{ + constexpr u8string_view landOwnershipKey = "land_ownership"; + if (!scenarioPatch.contains(landOwnershipKey)) + { + return; + } + + auto landOwnershipFixes = scenarioPatch[landOwnershipKey]; + for (const auto& ownershipType : { OWNERSHIP_UNOWNED, OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED, OWNERSHIP_OWNED, + OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE, OWNERSHIP_AVAILABLE }) + { + ApplyLandOwnershipFixes(landOwnershipFixes, ownershipType); + } +} + +static u8string GetPatchFileName(u8string_view scenarioName) +{ + auto env = OpenRCT2::GetContext()->GetPlatformEnvironment(); + auto scenarioPatches = env->GetDirectoryPath(OpenRCT2::DIRBASE::OPENRCT2, OpenRCT2::DIRID::SCENARIO_PATCHES); + auto scenarioPatchFile = Path::WithExtension(Path::GetFileNameWithoutExtension(scenarioName), ".json"); + return Path::Combine(scenarioPatches, scenarioPatchFile); +} + +void RCT12::FetchAndApplyScenarioPatch(u8string_view scenarioName) +{ + auto patchPath = GetPatchFileName(scenarioName); + std::cout << "Path is: " << patchPath << std::endl; + // TODO: Check if case sensitive, some scenario names have all lowercase variations + if (File::Exists(patchPath)) + { + auto scenarioPatch = Json::ReadFromFile(patchPath); + ApplyLandOwnershipFixes(scenarioPatch); + } +} \ No newline at end of file diff --git a/src/openrct2/rct12/ScenarioPatcher.h b/src/openrct2/rct12/ScenarioPatcher.h new file mode 100644 index 0000000000..28cb9ac1ad --- /dev/null +++ b/src/openrct2/rct12/ScenarioPatcher.h @@ -0,0 +1,17 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../core/String.hpp" + +namespace RCT12 +{ + void FetchAndApplyScenarioPatch(u8string_view scenarioName); +}