mirror of https://github.com/OpenRCT2/OpenRCT2.git
Fix nested arrays and ride measurement
This commit is contained in:
parent
ccb2eed939
commit
48f5515a55
|
@ -548,6 +548,16 @@ namespace OpenRCT2
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
if (cs.GetMode() == OrcaStream::Mode::READING)
|
if (cs.GetMode() == OrcaStream::Mode::READING)
|
||||||
|
{
|
||||||
|
auto hasMeasurement = cs.Read<uint8_t>();
|
||||||
|
if (hasMeasurement != 0)
|
||||||
|
{
|
||||||
|
ride.measurement = std::make_unique<RideMeasurement>();
|
||||||
|
ride.measurement->ride = &ride;
|
||||||
|
ReadWriteRideMeasurement(cs, *ride.measurement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (ride.measurement == nullptr)
|
if (ride.measurement == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -559,18 +569,6 @@ namespace OpenRCT2
|
||||||
ReadWriteRideMeasurement(cs, *ride.measurement);
|
ReadWriteRideMeasurement(cs, *ride.measurement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
auto hasMeasurement = cs.Read<uint8_t>();
|
|
||||||
if (hasMeasurement)
|
|
||||||
{
|
|
||||||
ride.measurement = std::make_unique<RideMeasurement>();
|
|
||||||
ride.measurement->ride = &ride;
|
|
||||||
ReadWriteRideMeasurement(cs, *ride.measurement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cs.ReadWrite(ride.measurement);
|
|
||||||
|
|
||||||
cs.ReadWrite(ride.special_track_elements);
|
cs.ReadWrite(ride.special_track_elements);
|
||||||
cs.ReadWrite(ride.max_speed);
|
cs.ReadWrite(ride.max_speed);
|
||||||
|
@ -673,12 +671,6 @@ namespace OpenRCT2
|
||||||
|
|
||||||
static void ReadWriteRideMeasurement(OrcaStream::ChunkStream& cs, RideMeasurement& measurement)
|
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.flags);
|
||||||
cs.ReadWrite(measurement.last_use_tick);
|
cs.ReadWrite(measurement.last_use_tick);
|
||||||
cs.ReadWrite(measurement.num_items);
|
cs.ReadWrite(measurement.num_items);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace OpenRCT2
|
namespace OpenRCT2
|
||||||
|
@ -189,12 +190,17 @@ namespace OpenRCT2
|
||||||
class ChunkStream
|
class ChunkStream
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
struct ArrayState
|
||||||
|
{
|
||||||
|
std::streampos StartPos{};
|
||||||
|
std::streampos LastPos{};
|
||||||
|
size_t Count{};
|
||||||
|
size_t ElementSize{};
|
||||||
|
};
|
||||||
|
|
||||||
std::stringstream& _buffer;
|
std::stringstream& _buffer;
|
||||||
Mode _mode;
|
Mode _mode;
|
||||||
std::streampos _currentArrayStartPos;
|
std::stack<ArrayState> _arrayStack;
|
||||||
std::streampos _currentArrayLastPos;
|
|
||||||
size_t _currentArrayCount;
|
|
||||||
size_t _currentArrayElementSize;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChunkStream(std::stringstream& buffer, Mode mode)
|
ChunkStream(std::stringstream& buffer, Mode mode)
|
||||||
|
@ -388,78 +394,82 @@ namespace OpenRCT2
|
||||||
|
|
||||||
size_t BeginArray()
|
size_t BeginArray()
|
||||||
{
|
{
|
||||||
|
auto& arrayState = _arrayStack.emplace();
|
||||||
if (_mode == Mode::READING)
|
if (_mode == Mode::READING)
|
||||||
{
|
{
|
||||||
_currentArrayCount = Read<uint32_t>();
|
arrayState.Count = Read<uint32_t>();
|
||||||
_currentArrayElementSize = Read<uint32_t>();
|
arrayState.ElementSize = Read<uint32_t>();
|
||||||
_currentArrayLastPos = _buffer.tellg();
|
arrayState.LastPos = _buffer.tellg();
|
||||||
return _currentArrayCount;
|
return arrayState.Count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_currentArrayCount = 0;
|
arrayState.Count = 0;
|
||||||
_currentArrayElementSize = 0;
|
arrayState.ElementSize = 0;
|
||||||
_currentArrayStartPos = _buffer.tellp();
|
arrayState.StartPos = _buffer.tellp();
|
||||||
Write<uint32_t>(0);
|
Write<uint32_t>(0);
|
||||||
Write<uint32_t>(0);
|
Write<uint32_t>(0);
|
||||||
_currentArrayLastPos = _buffer.tellp();
|
arrayState.LastPos = _buffer.tellp();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NextArrayElement()
|
bool NextArrayElement()
|
||||||
{
|
{
|
||||||
|
auto& arrayState = _arrayStack.top();
|
||||||
if (_mode == Mode::READING)
|
if (_mode == Mode::READING)
|
||||||
{
|
{
|
||||||
if (_currentArrayCount == 0)
|
if (arrayState.Count == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_currentArrayElementSize != 0)
|
if (arrayState.ElementSize != 0)
|
||||||
{
|
{
|
||||||
_currentArrayLastPos += _currentArrayElementSize;
|
arrayState.LastPos += arrayState.ElementSize;
|
||||||
_buffer.seekg(_currentArrayLastPos);
|
_buffer.seekg(arrayState.LastPos);
|
||||||
}
|
}
|
||||||
_currentArrayCount--;
|
arrayState.Count--;
|
||||||
return _currentArrayCount == 0;
|
return arrayState.Count == 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto lastElSize = (size_t)_buffer.tellp() - _currentArrayLastPos;
|
auto lastElSize = (size_t)_buffer.tellp() - arrayState.LastPos;
|
||||||
if (_currentArrayCount == 0)
|
if (arrayState.Count == 0)
|
||||||
{
|
{
|
||||||
// Set array element size based on first element size
|
// 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
|
// Array element size was different from first element so reset it
|
||||||
// to dynamic
|
// to dynamic
|
||||||
_currentArrayElementSize = 0;
|
arrayState.ElementSize = 0;
|
||||||
}
|
}
|
||||||
_currentArrayCount++;
|
arrayState.Count++;
|
||||||
_currentArrayLastPos = _buffer.tellp();
|
arrayState.LastPos = _buffer.tellp();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndArray()
|
void EndArray()
|
||||||
{
|
{
|
||||||
|
auto& arrayState = _arrayStack.top();
|
||||||
if (_mode == Mode::READING)
|
if (_mode == Mode::READING)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto backupPos = _buffer.tellp();
|
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.");
|
throw std::runtime_error("Array data was written but no elements were added.");
|
||||||
}
|
}
|
||||||
_buffer.seekp(_currentArrayStartPos);
|
_buffer.seekp(arrayState.StartPos);
|
||||||
Write((uint32_t)_currentArrayCount);
|
Write((uint32_t)arrayState.Count);
|
||||||
Write((uint32_t)_currentArrayElementSize);
|
Write((uint32_t)arrayState.ElementSize);
|
||||||
_buffer.seekp(backupPos);
|
_buffer.seekp(backupPos);
|
||||||
}
|
}
|
||||||
|
_arrayStack.pop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue