From 48f5515a5553470fbcb75ec12de0d34f87cc20ae Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 15 Jul 2019 22:04:59 +0100 Subject: [PATCH] Fix nested arrays and ride measurement --- src/openrct2/ParkFile.cpp | 28 +++++-------- src/openrct2/core/OrcaStream.hpp | 68 ++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/openrct2/ParkFile.cpp b/src/openrct2/ParkFile.cpp index dcb9103a4e..3b79c838d1 100644 --- a/src/openrct2/ParkFile.cpp +++ b/src/openrct2/ParkFile.cpp @@ -548,6 +548,16 @@ namespace OpenRCT2 // Stats if (cs.GetMode() == OrcaStream::Mode::READING) + { + auto hasMeasurement = cs.Read(); + if (hasMeasurement != 0) + { + ride.measurement = std::make_unique(); + ride.measurement->ride = &ride; + ReadWriteRideMeasurement(cs, *ride.measurement); + } + } + else { if (ride.measurement == nullptr) { @@ -559,18 +569,6 @@ namespace OpenRCT2 ReadWriteRideMeasurement(cs, *ride.measurement); } } - else - { - auto hasMeasurement = cs.Read(); - if (hasMeasurement) - { - ride.measurement = std::make_unique(); - ride.measurement->ride = &ride; - ReadWriteRideMeasurement(cs, *ride.measurement); - } - } - - cs.ReadWrite(ride.measurement); cs.ReadWrite(ride.special_track_elements); cs.ReadWrite(ride.max_speed); @@ -673,12 +671,6 @@ namespace OpenRCT2 static void ReadWriteRideMeasurement(OrcaStream::ChunkStream& cs, RideMeasurement& measurement) { - if (cs.GetMode() == OrcaStream::Mode::READING) - { - // Initialise measurement (mainly just for the fixed arrays) - measurement = {}; - } - cs.ReadWrite(measurement.flags); cs.ReadWrite(measurement.last_use_tick); cs.ReadWrite(measurement.num_items); diff --git a/src/openrct2/core/OrcaStream.hpp b/src/openrct2/core/OrcaStream.hpp index 9f9e8743c0..9528a753c3 100644 --- a/src/openrct2/core/OrcaStream.hpp +++ b/src/openrct2/core/OrcaStream.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace OpenRCT2 @@ -189,12 +190,17 @@ namespace OpenRCT2 class ChunkStream { private: + struct ArrayState + { + std::streampos StartPos{}; + std::streampos LastPos{}; + size_t Count{}; + size_t ElementSize{}; + }; + std::stringstream& _buffer; Mode _mode; - std::streampos _currentArrayStartPos; - std::streampos _currentArrayLastPos; - size_t _currentArrayCount; - size_t _currentArrayElementSize; + std::stack _arrayStack; public: ChunkStream(std::stringstream& buffer, Mode mode) @@ -388,78 +394,82 @@ namespace OpenRCT2 size_t BeginArray() { + auto& arrayState = _arrayStack.emplace(); if (_mode == Mode::READING) { - _currentArrayCount = Read(); - _currentArrayElementSize = Read(); - _currentArrayLastPos = _buffer.tellg(); - return _currentArrayCount; + arrayState.Count = Read(); + arrayState.ElementSize = Read(); + arrayState.LastPos = _buffer.tellg(); + return arrayState.Count; } else { - _currentArrayCount = 0; - _currentArrayElementSize = 0; - _currentArrayStartPos = _buffer.tellp(); + arrayState.Count = 0; + arrayState.ElementSize = 0; + arrayState.StartPos = _buffer.tellp(); Write(0); Write(0); - _currentArrayLastPos = _buffer.tellp(); + arrayState.LastPos = _buffer.tellp(); return 0; } } bool NextArrayElement() { + auto& arrayState = _arrayStack.top(); if (_mode == Mode::READING) { - if (_currentArrayCount == 0) + if (arrayState.Count == 0) { return false; } - if (_currentArrayElementSize != 0) + if (arrayState.ElementSize != 0) { - _currentArrayLastPos += _currentArrayElementSize; - _buffer.seekg(_currentArrayLastPos); + arrayState.LastPos += arrayState.ElementSize; + _buffer.seekg(arrayState.LastPos); } - _currentArrayCount--; - return _currentArrayCount == 0; + arrayState.Count--; + return arrayState.Count == 0; } else { - auto lastElSize = (size_t)_buffer.tellp() - _currentArrayLastPos; - if (_currentArrayCount == 0) + auto lastElSize = (size_t)_buffer.tellp() - arrayState.LastPos; + if (arrayState.Count == 0) { // Set array element size based on first element size - _currentArrayElementSize = lastElSize; + arrayState.ElementSize = lastElSize; } - else if (_currentArrayElementSize != lastElSize) + else if (arrayState.ElementSize != lastElSize) { // Array element size was different from first element so reset it // to dynamic - _currentArrayElementSize = 0; + arrayState.ElementSize = 0; } - _currentArrayCount++; - _currentArrayLastPos = _buffer.tellp(); + arrayState.Count++; + arrayState.LastPos = _buffer.tellp(); return true; } } void EndArray() { + auto& arrayState = _arrayStack.top(); if (_mode == Mode::READING) { } else { auto backupPos = _buffer.tellp(); - if ((size_t)backupPos != (size_t)_currentArrayStartPos + 8 && _currentArrayCount == 0) + if ((size_t)backupPos != (size_t)arrayState.StartPos + 8 && arrayState.Count == 0) { throw std::runtime_error("Array data was written but no elements were added."); } - _buffer.seekp(_currentArrayStartPos); - Write((uint32_t)_currentArrayCount); - Write((uint32_t)_currentArrayElementSize); + _buffer.seekp(arrayState.StartPos); + Write((uint32_t)arrayState.Count); + Write((uint32_t)arrayState.ElementSize); _buffer.seekp(backupPos); } + _arrayStack.pop(); } }; };