1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 04:23:20 +01:00

Support loading images from zip

This commit is contained in:
Ted John
2018-05-12 16:11:51 +01:00
parent 0f0bb021d6
commit 4e86d18dad
4 changed files with 135 additions and 43 deletions

View File

@@ -41,10 +41,52 @@
#include "WallObject.h"
#include "WaterObject.h"
interface IFileDataRetriever
{
virtual ~IFileDataRetriever() = default;
virtual std::vector<uint8> GetData(const std::string_view& path) const abstract;
};
class FileSystemDataRetriever : public IFileDataRetriever
{
private:
std::string _basePath;
public:
FileSystemDataRetriever(const std::string_view& basePath)
: _basePath(basePath)
{
}
std::vector<uint8> GetData(const std::string_view& path) const override
{
auto absolutePath = Path::Combine(_basePath, path.data());
return File::ReadAllBytes(absolutePath);
}
};
class ZipDataRetriever : public IFileDataRetriever
{
private:
const IZipArchive& _zipArchive;
public:
ZipDataRetriever(const IZipArchive& zipArchive)
: _zipArchive(zipArchive)
{
}
std::vector<uint8> GetData(const std::string_view& path) const override
{
return _zipArchive.GetFileData(path);
}
};
class ReadObjectContext : public IReadObjectContext
{
private:
IObjectRepository& _objectRepository;
const IFileDataRetriever * _fileDataRetriever;
std::string _objectName;
bool _loadImages;
@@ -56,11 +98,15 @@ public:
bool WasWarning() const { return _wasWarning; }
bool WasError() const { return _wasError; }
ReadObjectContext(IObjectRepository& objectRepository, const std::string &objectName, bool loadImages, const std::string& basePath)
ReadObjectContext(
IObjectRepository& objectRepository,
const std::string &objectName,
bool loadImages,
const IFileDataRetriever * fileDataRetriever)
: _objectRepository(objectRepository),
_objectName(objectName),
_loadImages(loadImages),
_basePath(basePath)
_fileDataRetriever(fileDataRetriever)
{
}
@@ -76,8 +122,11 @@ public:
std::vector<uint8> GetData(const std::string_view& path) override
{
auto absolutePath = Path::Combine(_basePath, path.data());
return File::ReadAllBytes(absolutePath);
if (_fileDataRetriever != nullptr)
{
return _fileDataRetriever->GetData(path);
}
return {};
}
void LogWarning(uint32 code, const utf8 * text) override
@@ -103,7 +152,7 @@ public:
namespace ObjectFactory
{
static Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const std::string_view& basePath);
static Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const IFileDataRetriever * fileRetriever);
static void ReadObjectLegacy(Object * object, IReadObjectContext * context, IStream * stream)
{
@@ -143,7 +192,7 @@ namespace ObjectFactory
log_verbose(" size: %zu", chunk->GetLength());
auto chunkStream = MemoryStream(chunk->GetData(), chunk->GetLength());
auto readContext = ReadObjectContext(objectRepository, objectName, !gOpenRCT2Headless, "");
auto readContext = ReadObjectContext(objectRepository, objectName, !gOpenRCT2Headless, nullptr);
ReadObjectLegacy(result, &readContext, &chunkStream);
if (readContext.WasError())
{
@@ -169,7 +218,7 @@ namespace ObjectFactory
utf8 objectName[DAT_NAME_LENGTH + 1];
object_entry_get_name_fixed(objectName, sizeof(objectName), entry);
auto readContext = ReadObjectContext(objectRepository, objectName, !gOpenRCT2Headless, "");
auto readContext = ReadObjectContext(objectRepository, objectName, !gOpenRCT2Headless, nullptr);
auto chunkStream = MemoryStream(data, dataSize);
ReadObjectLegacy(result, &readContext, &chunkStream);
@@ -241,12 +290,12 @@ namespace ObjectFactory
return 0xFF;
}
Object * CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string &path)
Object * CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path)
{
Object * result = nullptr;
try
{
auto archive = Zip::Open(path.c_str(), ZIP_ACCESS::READ);
auto archive = Zip::Open(path, ZIP_ACCESS::READ);
auto jsonBytes = archive->GetFileData("object.json");
if (jsonBytes.empty())
{
@@ -254,17 +303,18 @@ namespace ObjectFactory
}
json_error_t jsonLoadError;
auto jRoot = json_loads((const char *)jsonBytes.data(), 0, &jsonLoadError);
auto jRoot = json_loadb((const char *)jsonBytes.data(), jsonBytes.size(), 0, &jsonLoadError);
if (jRoot == nullptr)
{
throw JsonException(&jsonLoadError);
}
return CreateObjectFromJson(objectRepository, jRoot, "");
auto fileDataRetriever = ZipDataRetriever(*archive);
return CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
}
catch (const std::exception& e)
{
Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), e.what());
Console::Error::WriteLine("Unable to open or read '%s': %s", path.data(), e.what());
delete result;
result = nullptr;
@@ -280,7 +330,8 @@ namespace ObjectFactory
try
{
auto jRoot = Json::ReadFromFile(path.c_str());
result = CreateObjectFromJson(objectRepository, jRoot, Path::GetDirectory(path));
auto fileDataRetriever = FileSystemDataRetriever(Path::GetDirectory(path));
result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
json_decref(jRoot);
}
catch (const std::runtime_error &err)
@@ -293,7 +344,7 @@ namespace ObjectFactory
return result;
}
Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const std::string_view& basePath)
Object * CreateObjectFromJson(IObjectRepository& objectRepository, const json_t * jRoot, const IFileDataRetriever * fileRetriever)
{
log_verbose("CreateObjectFromJson(...)");
@@ -319,7 +370,7 @@ namespace ObjectFactory
memcpy(entry.name, originalName.c_str(), minLength);
result = CreateObject(entry);
auto readContext = ReadObjectContext(objectRepository, id, !gOpenRCT2Headless, basePath.data());
auto readContext = ReadObjectContext(objectRepository, id, !gOpenRCT2Headless, fileRetriever);
result->ReadJson(&readContext, jRoot);
if (readContext.WasError())
{