diff --git a/src/openrct2/GameStateSnapshots.cpp b/src/openrct2/GameStateSnapshots.cpp index 17e713271f..d8f3252dbd 100644 --- a/src/openrct2/GameStateSnapshots.cpp +++ b/src/openrct2/GameStateSnapshots.cpp @@ -31,7 +31,8 @@ struct GameStateSnapshot_t MemoryStream storedSprites; MemoryStream parkParameters; - void SerialiseSprites(rct_sprite* sprites, const size_t numSprites, bool saving) + // Must pass a function that can access the sprite. + void SerialiseSprites(std::function getEntity, const size_t numSprites, bool saving) { const bool loading = !saving; @@ -47,7 +48,8 @@ struct GameStateSnapshot_t { for (size_t i = 0; i < numSprites; i++) { - if (sprites[i].generic.sprite_identifier == SPRITE_IDENTIFIER_NULL) + auto entity = getEntity(i); + if (entity == nullptr || entity->generic.sprite_identifier == SPRITE_IDENTIFIER_NULL) continue; indexTable.push_back(static_cast(i)); } @@ -66,7 +68,13 @@ struct GameStateSnapshot_t ds << indexTable[i]; const uint32_t spriteIdx = indexTable[i]; - rct_sprite& sprite = sprites[spriteIdx]; + rct_sprite* entity = getEntity(spriteIdx); + if (entity == nullptr) + { + log_error("Entity index corrupted!"); + return; + } + auto& sprite = *entity; ds << sprite.generic.sprite_identifier; @@ -132,8 +140,8 @@ struct GameStateSnapshots final : public IGameStateSnapshots virtual void Capture(GameStateSnapshot_t& snapshot) override final { - // TODO refactor to not use this as a proxy for getting a pointer to the sprite array - snapshot.SerialiseSprites(get_sprite(0), MAX_SPRITES, true); + snapshot.SerialiseSprites( + [](const size_t index) { return reinterpret_cast(GetEntity(index)); }, MAX_SPRITES, true); // log_info("Snapshot size: %u bytes", static_cast(snapshot.storedSprites.GetLength())); } @@ -167,7 +175,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots sprite.generic.sprite_identifier = SPRITE_IDENTIFIER_NULL; } - snapshot.SerialiseSprites(spriteList.data(), MAX_SPRITES, false); + snapshot.SerialiseSprites([&spriteList](const size_t index) { return &spriteList[index]; }, MAX_SPRITES, false); return spriteList; } diff --git a/src/openrct2/scripting/ScEntity.hpp b/src/openrct2/scripting/ScEntity.hpp index e331ff4bd7..2642f9d899 100644 --- a/src/openrct2/scripting/ScEntity.hpp +++ b/src/openrct2/scripting/ScEntity.hpp @@ -248,7 +248,7 @@ namespace OpenRCT2::Scripting private: Vehicle* GetVehicle() const { - return get_sprite(_id)->generic.As(); + return ::GetEntity(_id); } uint8_t rideObject_get() const diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp index 019eb7171b..aea46e019b 100644 --- a/src/openrct2/world/Sprite.cpp +++ b/src/openrct2/world/Sprite.cpp @@ -284,11 +284,12 @@ rct_sprite_checksum sprite_checksum() for (size_t i = 0; i < MAX_SPRITES; i++) { // TODO create a way to copy only the specific type - auto sprite = get_sprite(i); - if (sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_NULL - && sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_MISC) + auto sprite = GetEntity(i); + if (sprite != nullptr && sprite->sprite_identifier != SPRITE_IDENTIFIER_NULL + && sprite->sprite_identifier != SPRITE_IDENTIFIER_MISC) { - auto copy = *sprite; + // Upconvert it to rct_sprite so that the full size is copied. + auto copy = *reinterpret_cast(sprite); // Only required for rendering/invalidation, has no meaning to the game state. copy.generic.sprite_left = copy.generic.sprite_right = copy.generic.sprite_top = copy.generic.sprite_bottom = 0; diff --git a/test/tests/S6ImportExportTests.cpp b/test/tests/S6ImportExportTests.cpp index f5ebe358d4..4fae5db26e 100644 --- a/test/tests/S6ImportExportTests.cpp +++ b/test/tests/S6ImportExportTests.cpp @@ -108,7 +108,7 @@ static std::unique_ptr GetGameState(std::unique_ptr& cont std::unique_ptr res = std::make_unique(); for (size_t spriteIdx = 0; spriteIdx < MAX_SPRITES; spriteIdx++) { - rct_sprite* sprite = get_sprite(spriteIdx); + rct_sprite* sprite = reinterpret_cast(GetEntity(spriteIdx)); if (sprite == nullptr) res->sprites[spriteIdx].generic.sprite_identifier = SPRITE_IDENTIFIER_NULL; else