1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-02-02 03:35:09 +01:00

Merge pull request #9571 from ZehMatt/replay-cleanup

Replay cleanup
This commit is contained in:
ζeh Matt
2019-08-05 18:31:03 +02:00
committed by GitHub
21 changed files with 244 additions and 302 deletions

View File

@@ -26,11 +26,15 @@ set(TITLE_SEQUENCE_SHA1 "19263f8ca383345959473e64da4785a60f00f420")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.11/objects.zip")
set(OBJECTS_SHA1 "8674120086929f9196560d77cada631fb478d7c0")
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.2/replays.zip")
set(REPLAYS_SHA1 "6E034E5299A8EC30A8D0A1B93F6A30A3A6429FEC")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests")
option(PORTABLE "Create a portable build (-rpath=$ORIGIN)" OFF)
option(DOWNLOAD_TITLE_SEQUENCES "Download title sequences during installation." ON)
option(DOWNLOAD_OBJECTS "Download objects during installation." ON)
option(DOWNLOAD_REPLAYS "Download replays during installation." ON)
# Options
option(STATIC "Create a static build.")
@@ -287,6 +291,16 @@ if (DOWNLOAD_OBJECTS)
file(REMOVE \$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/object/objects.zip)\n\
endif ()")
endif ()
if (DOWNLOAD_REPLAYS)
install(CODE
"if (EXISTS \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/testdata/replays/)\n\
message(\"Using cached replays\")\n\
else () \n\
file(DOWNLOAD ${REPLAYS_URL} \$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/testdata/replays/replays.zip EXPECTED_HASH SHA1=${REPLAYS_SHA1} SHOW_PROGRESS)\n\
execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/testdata/replays/ \"${CMAKE_COMMAND}\" -E tar xf replays.zip)\n\
file(REMOVE \$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/testdata/replays/replays.zip)\n\
endif ()")
endif ()
install(TARGETS "libopenrct2" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
if(NOT DISABLE_GUI)

View File

@@ -72,6 +72,8 @@
<TitleSequencesSha1>19263f8ca383345959473e64da4785a60f00f420</TitleSequencesSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.0.11/objects.zip</ObjectsUrl>
<ObjectsSha1>8674120086929f9196560d77cada631fb478d7c0</ObjectsSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.2/replays.zip</ReplaysUrl>
<ReplaysSha1>6E034E5299A8EC30A8D0A1B93F6A30A3A6429FEC</ReplaysSha1>
</PropertyGroup>
<ItemGroup>
@@ -226,6 +228,15 @@
OutputDirectory="$(TargetDir)data\object" />
</Target>
<!-- Target to download replays -->
<Target Name="DownloadReplays" AfterTargets="Build">
<DownloadDependency Name="Replays"
Url="$(ReplaysUrl)"
Sha1="$(ReplaysSha1)"
CheckFile="$(DependenciesCheckFile)"
OutputDirectory="$(TargetDir)testdata\replays" />
</Target>
<!-- Target to publish OpenRCT2 as a portable zip -->
<Target Name="PublishPortable" DependsOnTargets="Build;g2" Inputs="@(PublishItems)" Outputs="$(PublishZip)"
Condition="'$(TestConfig)'!='true'">

View File

@@ -13,6 +13,7 @@
#include "actions/ParkSetLoanAction.hpp"
#include "actions/SetCheatAction.hpp"
#include "config/Config.h"
#include "core/DataSerialiser.h"
#include "localisation/Localisation.h"
#include "network/network.h"
#include "ride/Ride.h"
@@ -28,6 +29,8 @@
using namespace OpenRCT2;
// TODO: Refactor this. Cheat variables should contain the cheat type
// and a serialisation method.
bool gCheatsSandboxMode = false;
bool gCheatsDisableClearanceChecks = false;
bool gCheatsDisableSupportLimits = false;
@@ -80,6 +83,136 @@ void CheatsSet(CheatType cheatType, int32_t param1 /* = 0*/, int32_t param2 /* =
GameActions::Execute(&setCheatAction);
}
template<typename T> static void CheatEntrySerialise(DataSerialiser& ds, CheatType type, const T& value, uint16_t& count)
{
ds << static_cast<int32_t>(type) << value;
count++;
}
void CheatsSerialise(DataSerialiser& ds)
{
uint16_t count = 0;
if (ds.IsSaving())
{
IStream& stream = ds.GetStream();
// Temporarily write 0, will be updated after every cheat is written.
uint64_t countOffset = stream.GetPosition();
ds << count;
CheatEntrySerialise(ds, CheatType::SandboxMode, gCheatsSandboxMode, count);
CheatEntrySerialise(ds, CheatType::DisableClearanceChecks, gCheatsDisableClearanceChecks, count);
CheatEntrySerialise(ds, CheatType::DisableSupportLimits, gCheatsDisableSupportLimits, count);
CheatEntrySerialise(ds, CheatType::ShowAllOperatingModes, gCheatsShowAllOperatingModes, count);
CheatEntrySerialise(ds, CheatType::ShowVehiclesFromOtherTrackTypes, gCheatsShowVehiclesFromOtherTrackTypes, count);
CheatEntrySerialise(ds, CheatType::FastLiftHill, gCheatsFastLiftHill, count);
CheatEntrySerialise(ds, CheatType::DisableBrakesFailure, gCheatsDisableBrakesFailure, count);
CheatEntrySerialise(ds, CheatType::DisableAllBreakdowns, gCheatsDisableAllBreakdowns, count);
CheatEntrySerialise(ds, CheatType::BuildInPauseMode, gCheatsBuildInPauseMode, count);
CheatEntrySerialise(ds, CheatType::IgnoreRideIntensity, gCheatsIgnoreRideIntensity, count);
CheatEntrySerialise(ds, CheatType::DisableVandalism, gCheatsDisableVandalism, count);
CheatEntrySerialise(ds, CheatType::DisableLittering, gCheatsDisableLittering, count);
CheatEntrySerialise(ds, CheatType::NeverEndingMarketing, gCheatsNeverendingMarketing, count);
CheatEntrySerialise(ds, CheatType::FreezeWeather, gCheatsFreezeWeather, count);
CheatEntrySerialise(ds, CheatType::DisableTrainLengthLimit, gCheatsDisableTrainLengthLimit, count);
CheatEntrySerialise(ds, CheatType::DisablePlantAging, gCheatsDisablePlantAging, count);
CheatEntrySerialise(ds, CheatType::EnableChainLiftOnAllTrack, gCheatsEnableChainLiftOnAllTrack, count);
CheatEntrySerialise(ds, CheatType::AllowArbitraryRideTypeChanges, gCheatsAllowArbitraryRideTypeChanges, count);
CheatEntrySerialise(ds, CheatType::DisableRideValueAging, gCheatsDisableRideValueAging, count);
CheatEntrySerialise(ds, CheatType::IgnoreResearchStatus, gCheatsIgnoreResearchStatus, count);
CheatEntrySerialise(ds, CheatType::EnableAllDrawableTrackPieces, gCheatsEnableAllDrawableTrackPieces, count);
// Remember current position and update count.
uint64_t endOffset = stream.GetPosition();
stream.SetPosition(countOffset);
ds << count; // Write correct count.
// Set position back.
stream.SetPosition(endOffset);
}
else
{
ds << count;
for (uint16_t i = 0; i < count; i++)
{
int32_t type = 0;
ds << type;
switch (static_cast<CheatType>(type))
{
case CheatType::SandboxMode:
ds << gCheatsSandboxMode;
break;
case CheatType::DisableClearanceChecks:
ds << gCheatsDisableClearanceChecks;
break;
case CheatType::DisableSupportLimits:
ds << gCheatsDisableSupportLimits;
break;
case CheatType::ShowAllOperatingModes:
ds << gCheatsShowAllOperatingModes;
break;
case CheatType::ShowVehiclesFromOtherTrackTypes:
ds << gCheatsShowVehiclesFromOtherTrackTypes;
break;
case CheatType::FastLiftHill:
ds << gCheatsFastLiftHill;
break;
case CheatType::DisableBrakesFailure:
ds << gCheatsDisableBrakesFailure;
break;
case CheatType::DisableAllBreakdowns:
ds << gCheatsDisableAllBreakdowns;
break;
case CheatType::BuildInPauseMode:
ds << gCheatsBuildInPauseMode;
break;
case CheatType::IgnoreRideIntensity:
ds << gCheatsIgnoreRideIntensity;
break;
case CheatType::DisableVandalism:
ds << gCheatsDisableVandalism;
break;
case CheatType::DisableLittering:
ds << gCheatsDisableLittering;
break;
case CheatType::NeverEndingMarketing:
ds << gCheatsNeverendingMarketing;
break;
case CheatType::FreezeWeather:
ds << gCheatsFreezeWeather;
break;
case CheatType::DisableTrainLengthLimit:
ds << gCheatsDisableTrainLengthLimit;
break;
case CheatType::DisablePlantAging:
ds << gCheatsDisablePlantAging;
break;
case CheatType::EnableChainLiftOnAllTrack:
ds << gCheatsEnableChainLiftOnAllTrack;
break;
case CheatType::AllowArbitraryRideTypeChanges:
ds << gCheatsAllowArbitraryRideTypeChanges;
break;
case CheatType::DisableRideValueAging:
ds << gCheatsDisableRideValueAging;
break;
case CheatType::IgnoreResearchStatus:
ds << gCheatsIgnoreResearchStatus;
break;
case CheatType::EnableAllDrawableTrackPieces:
ds << gCheatsEnableAllDrawableTrackPieces;
break;
default:
break;
}
}
}
}
const char* CheatsGetName(CheatType cheatType)
{
switch (cheatType)

View File

@@ -115,5 +115,6 @@ enum
void CheatsReset();
const char* CheatsGetName(CheatType cheatType);
void CheatsSet(CheatType cheatType, int32_t param1 = 0, int32_t param2 = 0);
void CheatsSerialise(class DataSerialiser& ds);
#endif

View File

@@ -404,24 +404,6 @@ int32_t game_do_command_p(
// Second call to actually perform the operation
new_game_command_table[command](eax, ebx, ecx, edx, esi, edi, ebp);
if (replayManager != nullptr)
{
bool recordCommand = false;
bool commandExecutes = (flags & GAME_COMMAND_FLAG_APPLY) && (flags & GAME_COMMAND_FLAG_GHOST) == 0
&& (flags & GAME_COMMAND_FLAG_NO_SPEND) == 0;
if (replayManager->IsRecording() && commandExecutes)
recordCommand = true;
else if (replayManager->IsNormalising() && commandExecutes && (flags & GAME_COMMAND_FLAG_REPLAY) != 0)
recordCommand = true;
if (recordCommand && gGameCommandNestLevel == 1)
{
replayManager->AddGameCommand(
gCurrentTicks, *eax, original_ebx, *ecx, original_edx, original_esi, original_edi, original_ebp, 0);
}
}
*edx = *ebx;
if (*edx != MONEY32_UNDEFINED && *edx < cost)

View File

@@ -37,40 +37,21 @@
namespace OpenRCT2
{
// NOTE: This is currently very close to what the network version uses.
// Should be refactored once the old game commands are gone.
struct ReplayCommand
{
uint32_t tick = 0;
GameAction::Ptr action;
uint32_t commandIndex = 0;
ReplayCommand() = default;
ReplayCommand(uint32_t t, uint32_t* args, uint8_t cb, uint32_t id)
{
tick = t;
eax = args[0];
ebx = args[1];
ecx = args[2];
edx = args[3];
esi = args[4];
edi = args[5];
ebp = args[6];
callback = cb;
action = nullptr;
commandIndex = id;
}
ReplayCommand(uint32_t t, std::unique_ptr<GameAction>&& ga, uint32_t id)
{
tick = t;
action = std::move(ga);
commandIndex = id;
}
: tick(t)
, action(std::move(ga))
, commandIndex(id)
uint32_t tick = 0;
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0;
GameAction::Ptr action;
uint8_t playerid = 0;
uint8_t callback = 0;
uint32_t commandIndex = 0;
{
}
bool operator<(const ReplayCommand& comp) const
{
@@ -101,6 +82,7 @@ namespace OpenRCT2
MemoryStream parkData;
MemoryStream spriteSpatialData;
MemoryStream parkParams;
MemoryStream cheatData;
std::string name; // Name of play
std::string filePath; // File path of replay.
uint64_t timeRecorded; // Posix Time.
@@ -113,7 +95,7 @@ namespace OpenRCT2
class ReplayManager final : public IReplayManager
{
static constexpr uint16_t ReplayVersion = 2;
static constexpr uint16_t ReplayVersion = 3;
static constexpr uint32_t ReplayMagic = 0x5243524F; // ORCR.
static constexpr int ReplayCompressionLevel = 9;
@@ -145,25 +127,6 @@ namespace OpenRCT2
return _mode == ReplayMode::NORMALISATION;
}
virtual void AddGameCommand(
uint32_t tick, uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi, uint32_t edi, uint32_t ebp,
uint8_t callback) override
{
if (_currentRecording == nullptr)
return;
uint32_t args[7];
args[0] = eax;
args[1] = ebx;
args[2] = ecx;
args[3] = edx;
args[4] = esi;
args[5] = edi;
args[6] = ebp;
_currentRecording->commands.emplace(gCurrentTicks, args, callback, _commandId++);
}
virtual void AddGameAction(uint32_t tick, const GameAction* action) override
{
if (_currentRecording == nullptr)
@@ -266,8 +229,11 @@ namespace OpenRCT2
replayData->spriteSpatialData.Write(gSpriteSpatialIndex, sizeof(gSpriteSpatialIndex));
replayData->timeRecorded = std::chrono::seconds(std::time(nullptr)).count();
DataSerialiser parkParams(true, replayData->parkParams);
SerialiseParkParameters(parkParams);
DataSerialiser parkParamsDs(true, replayData->parkParams);
SerialiseParkParameters(parkParamsDs);
DataSerialiser cheatDataDs(true, replayData->cheatData);
SerialiseCheats(cheatDataDs);
if (_mode != ReplayMode::NORMALISATION)
_mode = ReplayMode::RECORDING;
@@ -381,12 +347,6 @@ namespace OpenRCT2
return false;
}
if (!TranslateDeprecatedGameCommands(*replayData))
{
log_error("Unable to translate deprecated game commands.");
return false;
}
if (!LoadReplayDataMap(*replayData))
{
log_error("Unable to load map.");
@@ -461,144 +421,6 @@ namespace OpenRCT2
}
private:
bool ConvertDeprecatedGameCommand(const ReplayCommand& command, ReplayCommand& result)
{
// NOTE: If game actions are being ported it is required to implement temporarily
// a mapping from game command to game action. This will allow the normalisation
// stage to save a new replay file with the game action being used instead of the
// old game command. Once normalised the code will be no longer required.
/* Example case
case GAME_COMMAND_RAISE_WATER:
{
uint32_t param1 = command.ebp;
uint32_t param2 = command.edi;
result.action = std::make_unique<LandRaiseWaterAction>(param1, param2, ...);
}
*/
switch (command.esi)
{
case GAME_COMMAND_COUNT: // prevent default without case warning.
break;
case GAME_COMMAND_PLACE_TRACK:
{
ride_id_t rideId = command.edx & 0xFF;
int32_t trackType = (command.edx >> 8) & 0xFF;
CoordsXYZD origin = { (int32_t)(command.eax & 0xFFFF), (int32_t)(command.ecx & 0xFFFF),
(int32_t)(command.edi & 0xFFFF), (uint8_t)((command.ebx >> 8) & 0xFF) };
int32_t brakeSpeed = (command.edi >> 16) & 0xFF;
int32_t colour = (command.edi >> 24) & 0x0F;
int32_t seatRotation = (command.edi >> 28) & 0x0F;
int32_t liftHillAndAlternativeState = (command.edx >> 16);
result.action = std::make_unique<TrackPlaceAction>(
rideId, trackType, origin, brakeSpeed, colour, seatRotation, liftHillAndAlternativeState);
result.action->SetFlags(command.ebx & 0xFF);
break;
}
case GAME_COMMAND_SET_RIDE_SETTING:
{
ride_id_t rideId = command.edx & 0xFF;
RideSetSetting setting = static_cast<RideSetSetting>((command.edx >> 8) & 0xFF);
uint8_t value = (command.ebx >> 8) & 0xFF;
result.action = std::make_unique<RideSetSettingAction>(rideId, setting, value);
result.action->SetFlags(command.ebx & 0xFF);
break;
}
case GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT:
{
CoordsXY loc = { (int32_t)(command.eax & 0xFFFF), (int32_t)(command.ecx & 0xFFFF) };
Direction direction = (command.ebx >> 8) & 0xFF;
ride_id_t rideId = command.edx & 0xFF;
uint8_t stationNum = command.edi & 0xFF;
bool isExit = ((command.edx >> 8) & 0xFF) != 0;
result.action = std::make_unique<RideEntranceExitPlaceAction>(loc, direction, rideId, stationNum, isExit);
result.action->SetFlags(command.ebx & 0xFF);
break;
}
case GAME_COMMAND_PLACE_PATH:
{
CoordsXYZ loc = { (int32_t)(command.eax & 0xFFFF), (int32_t)(command.ecx & 0xFFFF),
(int32_t)(command.edx & 0xFF) * 8 };
uint8_t slope = (command.ebx >> 8) & 0xFF;
uint8_t type = (command.edx >> 8) & 0xFF;
result.action = std::make_unique<FootpathPlaceAction>(loc, slope, type);
result.action->SetFlags(command.ebx & 0xFF);
break;
}
case GAME_COMMAND_CHEAT:
{
int32_t param1 = command.edx;
int32_t param2 = command.edi;
CheatType cheatType = static_cast<CheatType>(command.ecx);
result.action = std::make_unique<SetCheatAction>(cheatType, param1, param2);
result.action->SetFlags(command.ebx & 0xFF);
break;
}
case GAME_COMMAND_MODIFY_TILE:
{
int32_t param1 = command.edx;
int32_t param2 = command.edi;
CoordsXY loc = { static_cast<int16_t>((command.ecx & 0xFF) * 32),
static_cast<int16_t>(((command.ecx >> 8) & 0xFF) * 32) };
TileModifyType type = static_cast<TileModifyType>(command.eax & 0xFF);
if (type == TileModifyType::AnyPaste)
{
TileElement copiedElement{};
uint32_t data[2] = { command.edx, command.edi };
std::memcpy(&copiedElement, &data[0], 8);
result.action = std::make_unique<TileModifyAction>(loc, type, 0, 0, copiedElement);
}
else
{
result.action = std::make_unique<TileModifyAction>(loc, type, param1, param2);
}
result.action->SetFlags(command.ebx & 0xFF);
break;
}
default:
throw std::runtime_error("Deprecated game command requires replay translation.");
}
return true;
}
bool TranslateDeprecatedGameCommands(ReplayRecordData& data)
{
for (auto it = data.commands.begin(); it != data.commands.end(); it++)
{
const ReplayCommand& replayCommand = *it;
if (replayCommand.action == nullptr)
{
// Check if we can create a game action with the command id.
uint32_t commandId = replayCommand.esi;
if (GameActions::IsValidId(commandId))
{
// Convert
ReplayCommand converted;
converted.commandIndex = replayCommand.commandIndex;
if (!ConvertDeprecatedGameCommand(replayCommand, converted))
{
return false;
}
// Remove deprecated command.
data.commands.erase(it);
// Insert new game action, iterator points to the replaced element.
it = data.commands.emplace(std::move(converted));
}
}
}
return true;
}
bool LoadReplayDataMap(ReplayRecordData& data)
{
try
@@ -623,8 +445,14 @@ namespace OpenRCT2
std::memcpy(gSpriteSpatialIndex, data.spriteSpatialData.GetData(), data.spriteSpatialData.GetLength());
// Load all map global variables.
DataSerialiser parkParams(false, data.parkParams);
SerialiseParkParameters(parkParams);
DataSerialiser parkParamsDs(false, data.parkParams);
SerialiseParkParameters(parkParamsDs);
// New cheats might not be serialised, make sure they are using their defaults.
CheatsReset();
DataSerialiser cheatDataDs(false, data.cheatData);
SerialiseCheats(cheatDataDs);
game_load_init();
fix_invalid_vehicle_sprite_sizes();
@@ -729,36 +557,39 @@ namespace OpenRCT2
// Reset position of all streams.
data.parkData.SetPosition(0);
data.parkParams.SetPosition(0);
data.cheatData.SetPosition(0);
data.spriteSpatialData.SetPosition(0);
return true;
}
bool SerialiseCheats(DataSerialiser& serialiser)
{
CheatsSerialise(serialiser);
return true;
}
bool SerialiseParkParameters(DataSerialiser& serialiser)
{
serialiser << _guestGenerationProbability;
serialiser << _suggestedGuestMaximum;
serialiser << gCheatsSandboxMode;
serialiser << gCheatsDisableClearanceChecks;
serialiser << gCheatsDisableSupportLimits;
serialiser << gCheatsDisableTrainLengthLimit;
serialiser << gCheatsEnableChainLiftOnAllTrack;
serialiser << gCheatsShowAllOperatingModes;
serialiser << gCheatsShowVehiclesFromOtherTrackTypes;
serialiser << gCheatsFastLiftHill;
serialiser << gCheatsDisableBrakesFailure;
serialiser << gCheatsDisableAllBreakdowns;
serialiser << gCheatsBuildInPauseMode;
serialiser << gCheatsIgnoreRideIntensity;
serialiser << gCheatsDisableVandalism;
serialiser << gCheatsDisableLittering;
serialiser << gCheatsNeverendingMarketing;
serialiser << gCheatsFreezeWeather;
serialiser << gCheatsDisablePlantAging;
serialiser << gCheatsAllowArbitraryRideTypeChanges;
serialiser << gCheatsDisableRideValueAging;
serialiser << gConfigGeneral.show_real_names_of_guests;
serialiser << gCheatsIgnoreResearchStatus;
// To make this a little bit less volatile against updates
// we reserve some space for future additions.
uint64_t tempStorage = 0;
// If another park parameter has to be added simply swap tempStorage.
// and ensure the length read/write will stay uint64_t
serialiser << tempStorage;
serialiser << tempStorage;
serialiser << tempStorage;
serialiser << tempStorage;
serialiser << tempStorage;
serialiser << tempStorage;
serialiser << tempStorage;
serialiser << tempStorage;
return true;
}
@@ -768,47 +599,27 @@ namespace OpenRCT2
serialiser << command.tick;
serialiser << command.commandIndex;
bool isGameAction = false;
uint32_t actionType = 0;
if (serialiser.IsSaving())
{
isGameAction = command.action != nullptr;
actionType = command.action->GetType();
}
serialiser << isGameAction;
serialiser << actionType;
if (isGameAction)
if (serialiser.IsLoading())
{
uint32_t actionType = 0;
if (serialiser.IsSaving())
{
actionType = command.action->GetType();
}
serialiser << actionType;
if (serialiser.IsLoading())
{
command.action = GameActions::Create(actionType);
Guard::Assert(command.action != nullptr);
}
command.action->Serialise(serialiser);
}
else
{
serialiser << command.eax;
serialiser << command.ebx;
serialiser << command.ecx;
serialiser << command.edx;
serialiser << command.esi;
serialiser << command.edi;
serialiser << command.ebp;
serialiser << command.callback;
command.action = GameActions::Create(actionType);
Guard::Assert(command.action != nullptr);
}
command.action->Serialise(serialiser);
return true;
}
bool Compatible(ReplayRecordData& data)
{
return data.version == 1 && ReplayVersion == 2;
return data.version == ReplayVersion;
}
bool Serialise(DataSerialiser& serialiser, ReplayRecordData& data)
@@ -841,6 +652,7 @@ namespace OpenRCT2
serialiser << data.timeRecorded;
serialiser << data.parkData;
serialiser << data.parkParams;
serialiser << data.cheatData;
serialiser << data.spriteSpatialData;
serialiser << data.tickStart;
serialiser << data.tickEnd;
@@ -946,26 +758,13 @@ namespace OpenRCT2
bool isPositionValid = false;
if (command.action != nullptr)
{
GameAction* action = command.action.get();
action->SetFlags(action->GetFlags() | GAME_COMMAND_FLAG_REPLAY);
GameAction* action = command.action.get();
action->SetFlags(action->GetFlags() | GAME_COMMAND_FLAG_REPLAY);
GameActionResult::Ptr result = GameActions::Execute(action);
if (result->Error == GA_ERROR::OK)
{
isPositionValid = true;
}
}
else
GameActionResult::Ptr result = GameActions::Execute(action);
if (result->Error == GA_ERROR::OK)
{
uint32_t flags = command.ebx | GAME_COMMAND_FLAG_REPLAY;
int32_t res = game_do_command(
command.eax, flags, command.ecx, command.edx, command.esi, command.edi, command.ebp);
if (res != MONEY32_UNDEFINED)
{
isPositionValid = true;
}
isPositionValid = true;
}
// Focus camera on event.

View File

@@ -43,11 +43,6 @@ namespace OpenRCT2
virtual bool IsRecording() const = 0;
virtual bool IsNormalising() const = 0;
// NOTE: Will become obsolete eventually once all game actions are done.
virtual void AddGameCommand(
uint32_t tick, uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi, uint32_t edi, uint32_t ebp,
uint8_t callback)
= 0;
virtual void AddGameAction(uint32_t tick, const GameAction* action) = 0;
virtual bool StartRecording(const std::string& name, uint32_t maxTicks = k_MaxReplayTicks) = 0;

View File

@@ -106,7 +106,7 @@ namespace GameActions
action->Serialise(dsOut);
// Serialise into new action.
MemoryStream& stream = dsOut.GetStream();
IStream& stream = dsOut.GetStream();
stream.SetPosition(0);
DataSerialiser dsIn(false, stream);

View File

@@ -17,23 +17,23 @@ class DataSerialiser
{
private:
MemoryStream _stream;
IStream* _activeStream = nullptr;
IStream& _activeStream;
bool _isSaving = false;
bool _isLogging = false;
public:
DataSerialiser(bool isSaving)
: _isSaving(isSaving)
: _activeStream(_stream)
, _isSaving(isSaving)
, _isLogging(false)
{
_activeStream = &_stream;
}
DataSerialiser(bool isSaving, IStream& stream, bool isLogging = false)
: _isSaving(isSaving)
: _activeStream(stream)
, _isSaving(isSaving)
, _isLogging(isLogging)
{
_activeStream = &stream;
}
bool IsSaving() const
@@ -46,9 +46,9 @@ public:
return !_isSaving;
}
MemoryStream& GetStream()
IStream& GetStream()
{
return _stream;
return _activeStream;
}
template<typename T> DataSerialiser& operator<<(const T& data)
@@ -56,13 +56,13 @@ public:
if (!_isLogging)
{
if (_isSaving)
DataSerializerTraits<T>::encode(_activeStream, data);
DataSerializerTraits<T>::encode(&_activeStream, data);
else
DataSerializerTraits<T>::decode(_activeStream, const_cast<T&>(data));
DataSerializerTraits<T>::decode(&_activeStream, const_cast<T&>(data));
}
else
{
DataSerializerTraits<T>::log(_activeStream, data);
DataSerializerTraits<T>::log(&_activeStream, data);
}
return *this;
@@ -73,13 +73,13 @@ public:
if (!_isLogging)
{
if (_isSaving)
DataSerializerTraits<DataSerialiserTag<T>>::encode(_activeStream, data);
DataSerializerTraits<DataSerialiserTag<T>>::encode(&_activeStream, data);
else
DataSerializerTraits<DataSerialiserTag<T>>::decode(_activeStream, data);
DataSerializerTraits<DataSerialiserTag<T>>::decode(&_activeStream, data);
}
else
{
DataSerializerTraits<DataSerialiserTag<T>>::log(_activeStream, data);
DataSerializerTraits<DataSerialiserTag<T>>::log(&_activeStream, data);
}
return *this;

View File

@@ -214,4 +214,9 @@ public:
size_t readBytes = fread(buffer, 1, (size_t)length, _file);
return readBytes;
}
const void* GetData() const override
{
return nullptr;
}
};

View File

@@ -49,6 +49,8 @@ interface IStream
virtual uint64_t TryRead(void* buffer, uint64_t length) abstract;
virtual const void* GetData() const abstract;
///////////////////////////////////////////////////////////////////////////
// Helper methods
///////////////////////////////////////////////////////////////////////////

View File

@@ -42,7 +42,7 @@ public:
MemoryStream& operator=(MemoryStream&& mv);
const void* GetData() const;
const void* GetData() const override;
void* GetDataCopy() const;
void* TakeData();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.