diff --git a/distribution/changelog.txt b/distribution/changelog.txt index e73cc41948..ce36403b1d 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,7 +1,8 @@ 0.3.1+ (in development) ------------------------------------------------------------------------ -- Feature: [#13000] objective_options command for console -- Fix: [#3200] Close Construction window upon selecting vehicle page +- Feature: [#12999] .sea (RCT Classic) scenarios are now listed in the “New Scenario” dialog. +- Feature: [#13000] objective_options command for console. +- Fix: [#3200] Close Construction window upon selecting vehicle page. - Improved: [#13023] Made add_news_item console command last argument, assoc, optional. 0.3.1 (2020-09-27) diff --git a/distribution/linux/openrct2-mimeinfo.xml b/distribution/linux/openrct2-mimeinfo.xml index 9f616ebb6e..7b72a6b3bb 100644 --- a/distribution/linux/openrct2-mimeinfo.xml +++ b/distribution/linux/openrct2-mimeinfo.xml @@ -49,6 +49,7 @@ OpenRCT2 劇情檔案 + diff --git a/src/openrct2/FileClassifier.cpp b/src/openrct2/FileClassifier.cpp index 77fedaf7d2..6f6fd74ee3 100644 --- a/src/openrct2/FileClassifier.cpp +++ b/src/openrct2/FileClassifier.cpp @@ -175,6 +175,8 @@ uint32_t get_file_extension_type(const utf8* path) return FILE_EXTENSION_TD4; if (String::Equals(extension, ".sc6", true)) return FILE_EXTENSION_SC6; + if (String::Equals(extension, ".sea", true)) + return FILE_EXTENSION_SC6; if (String::Equals(extension, ".sv6", true)) return FILE_EXTENSION_SV6; if (String::Equals(extension, ".sv7", true)) diff --git a/src/openrct2/ParkImporter.cpp b/src/openrct2/ParkImporter.cpp index c812df4bf1..a8483a582d 100644 --- a/src/openrct2/ParkImporter.cpp +++ b/src/openrct2/ParkImporter.cpp @@ -42,6 +42,7 @@ namespace ParkImporter bool ExtensionIsScenario(const std::string& extension) { - return String::Equals(extension, ".sc4", true) || String::Equals(extension, ".sc6", true); + return String::Equals(extension, ".sc4", true) || String::Equals(extension, ".sc6", true) + || String::Equals(extension, ".sea", true); } } // namespace ParkImporter diff --git a/src/openrct2/platform/Platform.Win32.cpp b/src/openrct2/platform/Platform.Win32.cpp index 99b77f5821..59110fa973 100644 --- a/src/openrct2/platform/Platform.Win32.cpp +++ b/src/openrct2/platform/Platform.Win32.cpp @@ -363,6 +363,7 @@ namespace Platform SetUpFileAssociation(".sv4", "RCT1 Saved Game (.sc4)", "Play", "\"%1\"", 0); SetUpFileAssociation(".sv6", "RCT2 Saved Game (.sv6)", "Play", "\"%1\"", 0); SetUpFileAssociation(".sv7", "RCT Modified Saved Game (.sv7)", "Play", "\"%1\"", 0); + SetUpFileAssociation(".sea", "RCTC Saved Game (.sea)", "Play", "\"%1\"", 0); SetUpFileAssociation(".td4", "RCT1 Track Design (.td4)", "Install", "\"%1\"", 0); SetUpFileAssociation(".td6", "RCT2 Track Design (.td6)", "Install", "\"%1\"", 0); @@ -507,6 +508,7 @@ namespace Platform RemoveFileAssociation(".sv4"); RemoveFileAssociation(".sv6"); RemoveFileAssociation(".sv7"); + RemoveFileAssociation(".sea"); RemoveFileAssociation(".td4"); RemoveFileAssociation(".td6"); diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index 57790b0345..21f3432dc9 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -18,6 +18,7 @@ #include "../core/File.h" #include "../core/FileIndex.hpp" #include "../core/FileStream.hpp" +#include "../core/MemoryStream.h" #include "../core/Path.hpp" #include "../core/String.hpp" #include "../localisation/Language.h" @@ -128,7 +129,7 @@ class ScenarioFileIndex final : public FileIndex private: static constexpr uint32_t MAGIC_NUMBER = 0x58444953; // SIDX static constexpr uint16_t VERSION = 3; - static constexpr auto PATTERN = "*.sc4;*.sc6"; + static constexpr auto PATTERN = "*.sc4;*.sc6;*.sea"; public: explicit ScenarioFileIndex(const IPlatformEnvironment& env) @@ -203,6 +204,22 @@ protected: } private: + static std::unique_ptr GetStreamFromRCT2Scenario(const std::string& path) + { + if (String::Equals(Path::GetExtension(path), ".sea", true)) + { + auto data = DecryptSea(fs::u8path(path)); + auto ms = std::make_unique(); + // Need to copy the data into MemoryStream as the overload will borrow instead of copy. + ms->Write(data.data(), data.size()); + ms->SetPosition(0); + return ms; + } + + auto fs = std::make_unique(path, FILE_MODE_OPEN); + return fs; + } + /** * Reads basic information from a scenario file. */ @@ -234,9 +251,9 @@ private: } else { - // RCT2 scenario - auto fs = FileStream(path, FILE_MODE_OPEN); - auto chunkReader = SawyerChunkReader(&fs); + // RCT2 or RCTC scenario + auto stream = GetStreamFromRCT2Scenario(path); + auto chunkReader = SawyerChunkReader(stream.get()); rct_s6_header header = chunkReader.ReadChunkAs(); if (header.type == S6_TYPE_SCENARIO)