Refactor ParkFile to just a source file

This commit is contained in:
Ted John 2018-12-15 14:49:53 +00:00
parent 3aaef84392
commit 0b519c68f2
2 changed files with 450 additions and 483 deletions

View File

@ -1,5 +1,3 @@
#include "ParkFile.h"
#include "Context.h"
#include "GameState.h"
#include "OpenRCT2.h"
@ -10,6 +8,7 @@
#include "interface/Viewport.h"
#include "interface/Window.h"
#include "localisation/Date.h"
#include "object/Object.h"
#include "object/ObjectManager.h"
#include "object/ObjectRepository.h"
#include "scenario/Scenario.h"
@ -17,8 +16,15 @@
#include "world/Map.h"
#include "world/Park.h"
using namespace OpenRCT2;
#include <array>
#include <cstdint>
#include <fstream>
#include <sstream>
#include <string_view>
#include <vector>
namespace OpenRCT2
{
constexpr uint32_t PARK_FILE_MAGIC = 0x4B524150; // PARK
// Current version that is saved.
@ -55,7 +61,56 @@ namespace ParkFileChunkType
// clang-format on
}; // namespace ParkFileChunkType
void ParkFile::Save(const std::string_view& path)
class ParkFile
{
public:
std::vector<rct_object_entry> RequiredObjects;
private:
#pragma pack(push, 1)
struct Header
{
uint32_t Magic{};
uint32_t TargetVersion{};
uint32_t MinVersion{};
uint32_t NumChunks{};
uint64_t UncompressedSize{};
uint32_t Compression{};
std::array<uint8_t, 20> Sha1{};
};
struct ChunkEntry
{
uint32_t Id{};
uint64_t Offset{};
uint64_t Length{};
};
#pragma pack(pop)
Header _header;
std::vector<ChunkEntry> _chunks;
std::stringstream _buffer;
ChunkEntry _currentChunk;
std::streampos _currentArrayStartPos;
std::streampos _currentArrayLastPos;
size_t _currentArrayCount;
size_t _currentArrayElementSize;
private:
template<typename T> void WriteValue(T v)
{
WriteBuffer(&v, sizeof(T));
}
template<typename T> T ReadValue()
{
T v{};
ReadBuffer(&v, sizeof(v));
return v;
}
public:
void Save(const std::string_view& path)
{
_header = {};
_header.Magic = PARK_FILE_MAGIC;
@ -83,7 +138,8 @@ void ParkFile::Save(const std::string_view& path)
fs.write(uncompressedData.data(), uncompressedData.size());
}
void ParkFile::WriteHeader(std::ostream& fs)
private:
void WriteHeader(std::ostream& fs)
{
fs.seekp(0);
fs.write((const char*)&_header, sizeof(_header));
@ -93,20 +149,20 @@ void ParkFile::WriteHeader(std::ostream& fs)
}
}
void ParkFile::BeginChunk(uint32_t id)
void BeginChunk(uint32_t id)
{
_currentChunk.Id = id;
_currentChunk.Offset = _buffer.tellp();
_currentChunk.Length = 0;
}
void ParkFile::EndChunk()
void EndChunk()
{
_currentChunk.Length = (uint64_t)_buffer.tellp() - _currentChunk.Offset;
_chunks.push_back(_currentChunk);
}
void ParkFile::BeginArray()
void BeginArray()
{
_currentArrayCount = 0;
_currentArrayElementSize = 0;
@ -116,7 +172,7 @@ void ParkFile::BeginArray()
_currentArrayLastPos = _buffer.tellp();
}
void ParkFile::NextArrayElement()
void NextArrayElement()
{
auto lastElSize = (size_t)_buffer.tellp() - _currentArrayLastPos;
if (_currentArrayCount == 0)
@ -134,7 +190,7 @@ void ParkFile::NextArrayElement()
_currentArrayLastPos = _buffer.tellp();
}
void ParkFile::EndArray()
void EndArray()
{
auto backupPos = _buffer.tellp();
if ((size_t)backupPos != (size_t)_currentArrayStartPos + 8 && _currentArrayCount == 0)
@ -147,12 +203,12 @@ void ParkFile::EndArray()
_buffer.seekp(backupPos);
}
void ParkFile::WriteBuffer(const void* buffer, size_t len)
void WriteBuffer(const void* buffer, size_t len)
{
_buffer.write((char*)buffer, len);
}
void ParkFile::WriteString(const std::string_view& s)
void WriteString(const std::string_view& s)
{
char nullt = '\0';
auto len = s.find('\0');
@ -164,7 +220,7 @@ void ParkFile::WriteString(const std::string_view& s)
_buffer.write(&nullt, sizeof(nullt));
}
void ParkFile::WriteAuthoringChunk()
void WriteAuthoringChunk()
{
BeginChunk(ParkFileChunkType::AUTHORING);
WriteString(gVersionInfoFull);
@ -172,7 +228,7 @@ void ParkFile::WriteAuthoringChunk()
EndChunk();
}
void ParkFile::WriteObjectsChunk()
void WriteObjectsChunk()
{
BeginChunk(ParkFileChunkType::OBJECTS);
BeginArray();
@ -202,7 +258,7 @@ void ParkFile::WriteObjectsChunk()
EndChunk();
}
void ParkFile::WriteGeneralChunk()
void WriteGeneralChunk()
{
BeginChunk(ParkFileChunkType::GENERAL);
WriteValue<uint64_t>(gScenarioTicks);
@ -234,7 +290,7 @@ void ParkFile::WriteGeneralChunk()
EndChunk();
}
void ParkFile::WriteInterfaceChunk()
void WriteInterfaceChunk()
{
BeginChunk(ParkFileChunkType::INTERFACE);
WriteValue(gSavedViewX);
@ -245,7 +301,7 @@ void ParkFile::WriteInterfaceChunk()
EndChunk();
}
void ParkFile::WriteTilesChunk()
void WriteTilesChunk()
{
BeginChunk(ParkFileChunkType::TILES);
WriteValue<uint32_t>(gMapSize);
@ -261,7 +317,8 @@ void ParkFile::WriteTilesChunk()
EndChunk();
}
void ParkFile::Load(const std::string_view& path)
public:
void Load(const std::string_view& path)
{
std::ifstream fs(std::string(path).c_str(), std::ios::binary);
@ -307,21 +364,22 @@ void ParkFile::Load(const std::string_view& path)
}
}
void ParkFile::Import()
void Import()
{
ReadTilesChunk();
ReadGeneralChunk();
ReadInterfaceChunk();
}
ParkFile::Header ParkFile::ReadHeader(std::istream& fs)
private:
Header ReadHeader(std::istream& fs)
{
Header header;
fs.read((char*)&header, sizeof(header));
return header;
}
bool ParkFile::SeekChunk(uint32_t id)
bool SeekChunk(uint32_t id)
{
auto result = std::find_if(_chunks.begin(), _chunks.end(), [id](const ChunkEntry& e) { return e.Id == id; });
if (result != _chunks.end())
@ -333,7 +391,7 @@ bool ParkFile::SeekChunk(uint32_t id)
return false;
}
size_t ParkFile::ReadArray()
size_t ReadArray()
{
_currentArrayCount = ReadValue<uint32_t>();
_currentArrayElementSize = ReadValue<uint32_t>();
@ -341,7 +399,7 @@ size_t ParkFile::ReadArray()
return _currentArrayCount;
}
bool ParkFile::ReadNextArrayElement()
bool ReadNextArrayElement()
{
if (_currentArrayCount == 0)
{
@ -355,12 +413,12 @@ bool ParkFile::ReadNextArrayElement()
return _currentArrayCount == 0;
}
void ParkFile::ReadBuffer(void* dst, size_t len)
void ReadBuffer(void* dst, size_t len)
{
_buffer.read((char*)dst, len);
}
std::string ParkFile::ReadString()
std::string ReadString()
{
std::string buffer;
buffer.reserve(64);
@ -373,7 +431,7 @@ std::string ParkFile::ReadString()
return buffer;
}
void ParkFile::ReadGeneralChunk()
void ReadGeneralChunk()
{
if (SeekChunk(ParkFileChunkType::GENERAL))
{
@ -406,7 +464,7 @@ void ParkFile::ReadGeneralChunk()
}
}
void ParkFile::ReadInterfaceChunk()
void ReadInterfaceChunk()
{
if (SeekChunk(ParkFileChunkType::INTERFACE))
{
@ -418,7 +476,7 @@ void ParkFile::ReadInterfaceChunk()
}
}
void ParkFile::ReadTilesChunk()
void ReadTilesChunk()
{
if (SeekChunk(ParkFileChunkType::TILES))
{
@ -438,6 +496,8 @@ void ParkFile::ReadTilesChunk()
throw std::runtime_error("No tiles chunk found.");
}
}
};
} // namespace OpenRCT2
enum : uint32_t
{
@ -466,7 +526,7 @@ int32_t scenario_save(const utf8* path, int32_t flags)
viewport_set_saved_view();
bool result = false;
auto parkFile = std::make_unique<ParkFile>();
auto parkFile = std::make_unique<OpenRCT2::ParkFile>();
try
{
// if (flags & S6_SAVE_FLAG_EXPORT)
@ -504,7 +564,7 @@ class ParkFileImporter : public IParkImporter
{
private:
const IObjectRepository& _objectRepository;
std::unique_ptr<ParkFile> _parkFile;
std::unique_ptr<OpenRCT2::ParkFile> _parkFile;
public:
ParkFileImporter(IObjectRepository& objectRepository)
@ -514,7 +574,7 @@ public:
ParkLoadResult Load(const utf8* path) override
{
_parkFile = std::make_unique<ParkFile>();
_parkFile = std::make_unique<OpenRCT2::ParkFile>();
_parkFile->Load(path);
return ParkLoadResult(std::move(_parkFile->RequiredObjects));
}

View File

@ -1,93 +0,0 @@
#pragma once
#include <array>
#include <cstdint>
#include <fstream>
#include <sstream>
#include <string_view>
#include <vector>
#include "object/Object.h"
namespace OpenRCT2
{
class ParkFile
{
public:
std::vector<rct_object_entry> RequiredObjects;
void Load(const std::string_view& path);
void Save(const std::string_view& path);
void Import();
private:
#pragma pack(push, 1)
struct Header
{
uint32_t Magic{};
uint32_t TargetVersion{};
uint32_t MinVersion{};
uint32_t NumChunks{};
uint64_t UncompressedSize{};
uint32_t Compression{};
std::array<uint8_t, 20> Sha1{};
};
struct ChunkEntry
{
uint32_t Id{};
uint64_t Offset{};
uint64_t Length{};
};
#pragma pack(pop)
Header _header;
std::vector<ChunkEntry> _chunks;
std::stringstream _buffer;
ChunkEntry _currentChunk;
std::streampos _currentArrayStartPos;
std::streampos _currentArrayLastPos;
size_t _currentArrayCount;
size_t _currentArrayElementSize;
void WriteHeader(std::ostream& fs);
void BeginChunk(uint32_t id);
void EndChunk();
void WriteBuffer(const void* buffer, size_t len);
void WriteString(const std::string_view& s);
void BeginArray();
void NextArrayElement();
void EndArray();
template<typename T>
void WriteValue(T v)
{
WriteBuffer(&v, sizeof(T));
}
void WriteAuthoringChunk();
void WriteObjectsChunk();
void WriteGeneralChunk();
void WriteInterfaceChunk();
void WriteTilesChunk();
void ReadGeneralChunk();
void ReadInterfaceChunk();
void ReadTilesChunk();
Header ReadHeader(std::istream& fs);
bool SeekChunk(uint32_t id);
size_t ReadArray();
bool ReadNextArrayElement();
void ReadBuffer(void* dst, size_t len);
std::string ReadString();
template<typename T>
T ReadValue()
{
T v{};
ReadBuffer(&v, sizeof(v));
return v;
}
};
} // namespace OpenRCT2