1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-17 20:13:07 +01:00

Merge pull request #15378 from ZehMatt/refactor/object-importexport

Refactor object storage in s6
This commit is contained in:
ζeh Matt
2021-09-11 07:48:36 -07:00
committed by GitHub
5 changed files with 85 additions and 65 deletions

View File

@@ -137,28 +137,6 @@ void get_type_entry_index(size_t index, ObjectType* outObjectType, ObjectEntryIn
*outEntryIndex = static_cast<ObjectEntryIndex>(index);
}
const rct_object_entry* get_loaded_object_entry(size_t index)
{
ObjectType objectType;
ObjectEntryIndex entryIndex;
get_type_entry_index(index, &objectType, &entryIndex);
auto obj = object_entry_get_object(objectType, entryIndex);
if (obj == nullptr)
{
return nullptr;
}
return obj->GetObjectEntry();
}
void* get_loaded_object_chunk(size_t index)
{
ObjectType objectType;
ObjectEntryIndex entryIndex;
get_type_entry_index(index, &objectType, &entryIndex);
return object_entry_get_chunk(objectType, entryIndex);
}
void object_entry_get_name_fixed(utf8* buffer, size_t bufferSize, const rct_object_entry* entry)
{
bufferSize = std::min(static_cast<size_t>(DAT_NAME_LENGTH) + 1, bufferSize);
@@ -168,20 +146,13 @@ void object_entry_get_name_fixed(utf8* buffer, size_t bufferSize, const rct_obje
void* object_entry_get_chunk(ObjectType objectType, ObjectEntryIndex index)
{
ObjectEntryIndex objectIndex = index;
for (int32_t i = 0; i < EnumValue(objectType); i++)
{
objectIndex += object_entry_group_counts[i];
}
void* result = nullptr;
auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objectMgr.GetLoadedObject(objectIndex);
if (obj != nullptr)
auto* object = objectMgr.GetLoadedObject(objectType, index);
if (object != nullptr)
{
result = obj->GetLegacyData();
return object->GetLegacyData();
}
return result;
return nullptr;
}
const Object* object_entry_get_object(ObjectType objectType, ObjectEntryIndex index)

View File

@@ -18,5 +18,3 @@
#include "ObjectLimits.h"
void get_type_entry_index(size_t index, ObjectType* outObjectType, ObjectEntryIndex* outEntryIndex);
const rct_object_entry* get_loaded_object_entry(size_t index);
void* get_loaded_object_chunk(size_t index);

View File

@@ -836,7 +836,24 @@ struct rct_s6_data
// packed objects
// SC6[3]
rct_object_entry objects[RCT2_OBJECT_ENTRY_COUNT];
union
{
rct_object_entry Objects[RCT2_OBJECT_ENTRY_COUNT];
struct
{
rct_object_entry RideObjects[RCT12_MAX_RIDE_OBJECTS];
rct_object_entry SceneryObjects[RCT2_MAX_SMALL_SCENERY_OBJECTS];
rct_object_entry LargeSceneryObjects[RCT2_MAX_LARGE_SCENERY_OBJECTS];
rct_object_entry WallSceneryObjects[RCT2_MAX_WALL_SCENERY_OBJECTS];
rct_object_entry BannerObjects[RCT2_MAX_BANNER_OBJECTS];
rct_object_entry PathObjects[RCT2_MAX_PATH_OBJECTS];
rct_object_entry PathAdditionObjects[RCT2_MAX_PATH_ADDITION_OBJECTS];
rct_object_entry SceneryGroupObjects[RCT2_MAX_SCENERY_GROUP_OBJECTS];
rct_object_entry ParkEntranceObjects[RCT2_MAX_PARK_ENTRANCE_OBJECTS];
rct_object_entry WaterObjects[RCT2_MAX_WATER_OBJECTS];
rct_object_entry ScenarioTextObjects[RCT2_MAX_SCENARIO_TEXT_OBJECTS];
};
};
// SC6[4]
uint16_t elapsed_months;

View File

@@ -120,7 +120,7 @@ void S6Exporter::Save(OpenRCT2::IStream* stream, bool isScenario)
}
// 3: Write available objects chunk
chunkWriter.WriteChunk(_s6.objects, sizeof(_s6.objects), SAWYER_ENCODING::ROTATE);
chunkWriter.WriteChunk(_s6.Objects, sizeof(_s6.Objects), SAWYER_ENCODING::ROTATE);
// 4: Misc fields (data, rand...) chunk
chunkWriter.WriteChunk(&_s6.elapsed_months, 16, SAWYER_ENCODING::RLECOMPRESSED);
@@ -255,6 +255,26 @@ static void scenario_fix_ghosts(rct_s6_data* s6)
}
}
template<ObjectType TObjectType, size_t TMaxEntries, typename T>
static void ExportObjectList(IObjectManager& objMgr, T& objects)
{
for (size_t i = 0; i < TMaxEntries; i++)
{
auto& dst = objects[i];
const auto* object = objMgr.GetLoadedObject(TObjectType, i);
if (object == nullptr || object->GetObjectEntry() == nullptr)
{
// The sv6 format expects null/invalid entries to be filled with 0xFF.
std::memset(&dst, 0xFF, sizeof(dst));
}
else
{
dst = *object->GetObjectEntry();
}
}
}
void S6Exporter::Export()
{
_s6.info = {};
@@ -278,20 +298,18 @@ void S6Exporter::Export()
uint32_t researchedTrackPiecesA[128] = {};
uint32_t researchedTrackPiecesB[128] = {};
for (int32_t i = 0; i < RCT2_OBJECT_ENTRY_COUNT; i++)
{
const rct_object_entry* entry = get_loaded_object_entry(i);
void* entryData = get_loaded_object_chunk(i);
// RCT2 uses (void *)-1 to mark NULL. Make sure it's written in a vanilla-compatible way.
if (entry == nullptr || entryData == nullptr || entryData == reinterpret_cast<void*>(-1))
{
std::memset(&_s6.objects[i], 0xFF, sizeof(rct_object_entry));
}
else
{
_s6.objects[i] = *entry;
}
}
auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager();
ExportObjectList<ObjectType::Ride, RCT12_MAX_RIDE_OBJECTS>(objectMgr, _s6.RideObjects);
ExportObjectList<ObjectType::SmallScenery, RCT2_MAX_SMALL_SCENERY_OBJECTS>(objectMgr, _s6.SceneryObjects);
ExportObjectList<ObjectType::LargeScenery, RCT2_MAX_LARGE_SCENERY_OBJECTS>(objectMgr, _s6.LargeSceneryObjects);
ExportObjectList<ObjectType::Walls, RCT2_MAX_WALL_SCENERY_OBJECTS>(objectMgr, _s6.WallSceneryObjects);
ExportObjectList<ObjectType::Banners, RCT2_MAX_BANNER_OBJECTS>(objectMgr, _s6.BannerObjects);
ExportObjectList<ObjectType::Paths, RCT2_MAX_PATH_OBJECTS>(objectMgr, _s6.PathObjects);
ExportObjectList<ObjectType::PathBits, RCT2_MAX_PATH_ADDITION_OBJECTS>(objectMgr, _s6.PathAdditionObjects);
ExportObjectList<ObjectType::SceneryGroup, RCT2_MAX_SCENERY_GROUP_OBJECTS>(objectMgr, _s6.SceneryGroupObjects);
ExportObjectList<ObjectType::ParkEntrance, RCT2_MAX_PARK_ENTRANCE_OBJECTS>(objectMgr, _s6.ParkEntranceObjects);
ExportObjectList<ObjectType::Water, RCT2_MAX_WATER_OBJECTS>(objectMgr, _s6.WaterObjects);
ExportObjectList<ObjectType::ScenarioText, RCT2_MAX_SCENARIO_TEXT_OBJECTS>(objectMgr, _s6.ScenarioTextObjects);
_s6.elapsed_months = static_cast<uint16_t>(gDateMonthsElapsed);
_s6.current_day = gDateMonthTicks;

View File

@@ -169,9 +169,10 @@ public:
_isSV7 = _stricmp(extension, ".sv7") == 0;
}
chunkReader.ReadChunk(&_s6.Objects, sizeof(_s6.Objects));
if (isScenario)
{
chunkReader.ReadChunk(&_s6.objects, sizeof(_s6.objects));
chunkReader.ReadChunk(&_s6.elapsed_months, 16);
chunkReader.ReadChunk(&_s6.tile_elements, sizeof(_s6.tile_elements));
chunkReader.ReadChunk(&_s6.next_free_tile_element_pointer_index, 2560076);
@@ -185,7 +186,6 @@ public:
}
else
{
chunkReader.ReadChunk(&_s6.objects, sizeof(_s6.objects));
chunkReader.ReadChunk(&_s6.elapsed_months, 16);
chunkReader.ReadChunk(&_s6.tile_elements, sizeof(_s6.tile_elements));
chunkReader.ReadChunk(&_s6.next_free_tile_element_pointer_index, 3048816);
@@ -1563,25 +1563,41 @@ public:
return justText.data();
}
std::vector<rct_object_entry> GetRequiredObjects()
template<size_t TInternalLimit, typename T>
static void AddRequiredObjects(std::vector<rct_object_entry>& required, const T& list)
{
std::vector<rct_object_entry> result;
rct_object_entry nullEntry = {};
std::memset(&nullEntry, 0xFF, sizeof(nullEntry));
int objectIt = 0;
for (int16_t objectType = EnumValue(ObjectType::Ride); objectType <= EnumValue(ObjectType::Water); objectType++)
for (const auto& entry : list)
{
for (int16_t i = 0; i < rct2_object_entry_group_counts[objectType]; i++, objectIt++)
{
result.push_back(_s6.objects[objectIt]);
}
for (int16_t i = rct2_object_entry_group_counts[objectType]; i < object_entry_group_counts[objectType]; i++)
{
result.push_back(nullEntry);
}
required.push_back(entry);
}
// NOTE: The segment of this object type needs to be filled to the internal limit
// the object manager currently expects this.
for (size_t i = std::size(list); i < TInternalLimit; i++)
{
required.push_back(nullEntry);
}
}
std::vector<rct_object_entry> GetRequiredObjects()
{
std::vector<rct_object_entry> result;
AddRequiredObjects<MAX_RIDE_OBJECTS>(result, _s6.RideObjects);
AddRequiredObjects<MAX_SMALL_SCENERY_OBJECTS>(result, _s6.SceneryObjects);
AddRequiredObjects<MAX_LARGE_SCENERY_OBJECTS>(result, _s6.LargeSceneryObjects);
AddRequiredObjects<MAX_WALL_SCENERY_OBJECTS>(result, _s6.WallSceneryObjects);
AddRequiredObjects<MAX_BANNER_OBJECTS>(result, _s6.BannerObjects);
AddRequiredObjects<MAX_PATH_OBJECTS>(result, _s6.PathObjects);
AddRequiredObjects<MAX_PATH_ADDITION_OBJECTS>(result, _s6.PathAdditionObjects);
AddRequiredObjects<MAX_SCENERY_GROUP_OBJECTS>(result, _s6.SceneryGroupObjects);
AddRequiredObjects<MAX_PARK_ENTRANCE_OBJECTS>(result, _s6.ParkEntranceObjects);
AddRequiredObjects<MAX_WATER_OBJECTS>(result, _s6.WaterObjects);
AddRequiredObjects<MAX_SCENARIO_TEXT_OBJECTS>(result, _s6.ScenarioTextObjects);
return result;
}
};