mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-02-01 19:25:12 +01:00
improve object loading efficiency
This commit is contained in:
@@ -127,6 +127,7 @@
|
||||
<ClCompile Include="src\object\LargeSceneryObject.cpp" />
|
||||
<ClCompile Include="src\object\Object.cpp" />
|
||||
<ClCompile Include="src\object\ObjectFactory.cpp" />
|
||||
<ClCompile Include="src\object\ObjectManager.cpp" />
|
||||
<ClCompile Include="src\object\ObjectRepository.cpp" />
|
||||
<ClCompile Include="src\object\RideObject.cpp" />
|
||||
<ClCompile Include="src\object\SceneryGroupObject.cpp" />
|
||||
@@ -444,6 +445,7 @@
|
||||
<ClInclude Include="src\object\LargeSceneryObject.h" />
|
||||
<ClInclude Include="src\object\Object.h" />
|
||||
<ClInclude Include="src\object\ObjectFactory.h" />
|
||||
<ClInclude Include="src\object\ObjectManager.h" />
|
||||
<ClInclude Include="src\object\ObjectRepository.h" />
|
||||
<ClInclude Include="src\object\RideObject.h" />
|
||||
<ClInclude Include="src\object\SceneryGroupObject.h" />
|
||||
|
||||
@@ -114,7 +114,7 @@ int object_load_packed(SDL_RWops* rw);
|
||||
bool object_saved_packed(SDL_RWops* rw, const rct_object_entry * entry);
|
||||
void object_unload_all();
|
||||
|
||||
int check_object_entry(rct_object_entry *entry);
|
||||
int check_object_entry(const rct_object_entry *entry);
|
||||
bool object_load_chunk(int groupIndex, const rct_object_entry * entry, int * outGroupIndex);
|
||||
bool object_entry_compare(const rct_object_entry *a, const rct_object_entry *b);
|
||||
int object_calculate_checksum(const rct_object_entry * entry, const void * data, size_t dataLength);
|
||||
|
||||
299
src/object/ObjectManager.cpp
Normal file
299
src/object/ObjectManager.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include <array>
|
||||
#include <unordered_set>
|
||||
#include "../core/Console.hpp"
|
||||
#include "../core/Memory.hpp"
|
||||
#include "Object.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "ObjectRepository.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../object_list.h"
|
||||
}
|
||||
|
||||
class ObjectManager : public IObjectManager
|
||||
{
|
||||
private:
|
||||
IObjectRepository * _objectRepository;
|
||||
Object * * _loadedObjects = nullptr;
|
||||
|
||||
public:
|
||||
ObjectManager(IObjectRepository * objectRepository)
|
||||
{
|
||||
_objectRepository = objectRepository;
|
||||
}
|
||||
|
||||
~ObjectManager() override
|
||||
{
|
||||
SetNewLoadedObjectList(nullptr);
|
||||
}
|
||||
|
||||
Object * GetLoadedObject(size_t index) override
|
||||
{
|
||||
if (_loadedObjects == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return _loadedObjects[index];
|
||||
}
|
||||
|
||||
bool LoadObjects(const rct_object_entry * entries, size_t count) override
|
||||
{
|
||||
IObjectRepository * objectRepository = GetObjectRepository();
|
||||
|
||||
// Find all the required objects
|
||||
size_t numRequiredObjects;
|
||||
auto requiredObjects = new const ObjectRepositoryItem *[OBJECT_ENTRY_COUNT];
|
||||
if (!GetRequiredObjects(entries, requiredObjects, &numRequiredObjects))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a new list of loaded objects
|
||||
size_t numNewLoadedObjects;
|
||||
Object * * loadedObjects = LoadObjects(requiredObjects, &numNewLoadedObjects);
|
||||
|
||||
delete requiredObjects;
|
||||
|
||||
if (loadedObjects == nullptr)
|
||||
{
|
||||
UnloadAll();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNewLoadedObjectList(loadedObjects);
|
||||
UpdateLegacyLoadedObjectList();
|
||||
reset_type_to_ride_entry_index_map();
|
||||
Console::WriteLine("%u / %u new objects loaded", numNewLoadedObjects, numRequiredObjects);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void UnloadAll() override
|
||||
{
|
||||
if (_loadedObjects != nullptr)
|
||||
{
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
UnloadObject(_loadedObjects[i]);
|
||||
_loadedObjects[i] = nullptr;
|
||||
}
|
||||
}
|
||||
UpdateLegacyLoadedObjectList();
|
||||
reset_type_to_ride_entry_index_map();
|
||||
}
|
||||
|
||||
private:
|
||||
void SetNewLoadedObjectList(Object * * newLoadedObjects)
|
||||
{
|
||||
if (newLoadedObjects == nullptr)
|
||||
{
|
||||
UnloadAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
UnloadObjectsExcept(newLoadedObjects);
|
||||
}
|
||||
Memory::Free(_loadedObjects);
|
||||
_loadedObjects = newLoadedObjects;
|
||||
}
|
||||
|
||||
void UnloadObject(Object * object)
|
||||
{
|
||||
if (object != nullptr)
|
||||
{
|
||||
// TODO try to prevent doing a repository search
|
||||
const ObjectRepositoryItem * ori = _objectRepository->FindObject(object->GetObjectEntry());
|
||||
if (ori != nullptr)
|
||||
{
|
||||
_objectRepository->UnregisterLoadedObject(ori, object);
|
||||
}
|
||||
|
||||
object->Unload();
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
void UnloadObjectsExcept(Object * * newLoadedObjects)
|
||||
{
|
||||
if (_loadedObjects == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Build a hash set for quick checking
|
||||
auto exceptSet = std::unordered_set<Object *>();
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
Object * object = newLoadedObjects[i];
|
||||
if (object != nullptr)
|
||||
{
|
||||
exceptSet.insert(object);
|
||||
}
|
||||
}
|
||||
|
||||
// Unload objects that are not in the hash set
|
||||
size_t totalObjectsLoaded = 0;
|
||||
size_t numObjectsUnloaded = 0;
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
Object * object = _loadedObjects[i];
|
||||
if (object != nullptr)
|
||||
{
|
||||
totalObjectsLoaded++;
|
||||
if (exceptSet.find(object) == exceptSet.end())
|
||||
{
|
||||
UnloadObject(object);
|
||||
_loadedObjects[i] = nullptr;
|
||||
numObjectsUnloaded++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console::WriteLine("%u / %u objects unloaded", numObjectsUnloaded, totalObjectsLoaded);
|
||||
}
|
||||
|
||||
void UpdateLegacyLoadedObjectList()
|
||||
{
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
Object * loadedObject = nullptr;
|
||||
if (_loadedObjects != nullptr)
|
||||
{
|
||||
loadedObject = _loadedObjects[i];
|
||||
}
|
||||
|
||||
uint8 objectType, entryIndex;
|
||||
get_type_entry_index(i, &objectType, &entryIndex);
|
||||
|
||||
rct_object_entry_extended * legacyEntry = &object_entry_groups[objectType].entries[entryIndex];
|
||||
void * * legacyChunk = &object_entry_groups[objectType].chunks[entryIndex];
|
||||
if (loadedObject == nullptr)
|
||||
{
|
||||
Memory::Set(legacyEntry, 0xFF, sizeof(rct_object_entry_extended));
|
||||
*legacyChunk = (void *)-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
legacyEntry->entry = *loadedObject->GetObjectEntry();
|
||||
legacyEntry->chunk_size = 0;
|
||||
*legacyChunk = loadedObject->GetLegacyData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GetRequiredObjects(const rct_object_entry * entries,
|
||||
const ObjectRepositoryItem * * requiredObjects,
|
||||
size_t * outNumRequiredObjects)
|
||||
{
|
||||
bool missingObjects = false;
|
||||
size_t numRequiredObjects = 0;
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
const rct_object_entry * entry = &entries[i];
|
||||
const ObjectRepositoryItem * ori = nullptr;
|
||||
if (check_object_entry(entry))
|
||||
{
|
||||
ori = _objectRepository->FindObject(entry);
|
||||
if (ori == nullptr)
|
||||
{
|
||||
missingObjects = true;
|
||||
ReportMissingObject(entry);
|
||||
}
|
||||
numRequiredObjects++;
|
||||
}
|
||||
requiredObjects[i] = ori;
|
||||
}
|
||||
|
||||
if (outNumRequiredObjects != nullptr)
|
||||
{
|
||||
*outNumRequiredObjects = numRequiredObjects;
|
||||
}
|
||||
return !missingObjects;
|
||||
}
|
||||
|
||||
Object * * LoadObjects(const ObjectRepositoryItem * * requiredObjects, size_t * outNewObjectsLoaded)
|
||||
{
|
||||
size_t newObjectsLoaded = 0;
|
||||
Object * * loadedObjects = Memory::AllocateArray<Object *>(OBJECT_ENTRY_COUNT);
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
Object * loadedObject = nullptr;
|
||||
const ObjectRepositoryItem * ori = requiredObjects[i];
|
||||
if (ori != nullptr)
|
||||
{
|
||||
loadedObject = ori->LoadedObject;
|
||||
if (loadedObject == nullptr)
|
||||
{
|
||||
// Try to load object
|
||||
loadedObject = _objectRepository->LoadObject(ori);
|
||||
if (loadedObject == nullptr)
|
||||
{
|
||||
ReportObjectLoadProblem(&ori->ObjectEntry);
|
||||
Memory::Free(loadedObjects);
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadedObject->Load();
|
||||
newObjectsLoaded++;
|
||||
}
|
||||
|
||||
// Connect the ori to the registered object
|
||||
_objectRepository->RegisterLoadedObject(ori, loadedObject);
|
||||
}
|
||||
}
|
||||
loadedObjects[i] = loadedObject;
|
||||
}
|
||||
if (outNewObjectsLoaded != nullptr)
|
||||
{
|
||||
*outNewObjectsLoaded = newObjectsLoaded;
|
||||
}
|
||||
return loadedObjects;
|
||||
}
|
||||
|
||||
static void ReportMissingObject(const rct_object_entry * entry)
|
||||
{
|
||||
utf8 objName[9] = { 0 };
|
||||
Memory::Copy(objName, entry->name, 8);
|
||||
Console::Error::WriteFormat("[%s]: Object not found.", objName);
|
||||
Console::Error::WriteLine();
|
||||
}
|
||||
|
||||
static void ReportObjectLoadProblem(const rct_object_entry * entry)
|
||||
{
|
||||
utf8 objName[9] = { 0 };
|
||||
Memory::Copy(objName, entry->name, 8);
|
||||
Console::Error::WriteFormat("[%s]: Object could not be loaded.", objName);
|
||||
Console::Error::WriteLine();
|
||||
}
|
||||
};
|
||||
|
||||
ObjectManager * _objectManager;
|
||||
|
||||
IObjectManager * GetObjectManager()
|
||||
{
|
||||
if (_objectManager == nullptr)
|
||||
{
|
||||
IObjectRepository * objectRepository = GetObjectRepository();
|
||||
_objectManager = new ObjectManager(objectRepository);
|
||||
}
|
||||
return _objectManager;
|
||||
}
|
||||
40
src/object/ObjectManager.h
Normal file
40
src/object/ObjectManager.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include "../object.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
interface IObjectManager
|
||||
{
|
||||
virtual ~IObjectManager() { }
|
||||
|
||||
virtual Object * GetLoadedObject(size_t index) abstract;
|
||||
|
||||
virtual bool LoadObjects(const rct_object_entry * entries, size_t count) abstract;
|
||||
virtual void UnloadAll() abstract;
|
||||
};
|
||||
|
||||
IObjectManager * GetObjectManager();
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "../core/String.hpp"
|
||||
#include "Object.h"
|
||||
#include "ObjectFactory.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "ObjectRepository.h"
|
||||
#include "RideObject.h"
|
||||
#include "StexObject.h"
|
||||
@@ -39,6 +40,7 @@ extern "C"
|
||||
#include "../config.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../object.h"
|
||||
#include "../object_list.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../scenario.h"
|
||||
#include "../util/sawyercoding.h"
|
||||
@@ -87,6 +89,8 @@ struct ObjectEntryEqual
|
||||
|
||||
using ObjectEntryMap = std::unordered_map<rct_object_entry, size_t, ObjectEntryHash, ObjectEntryEqual>;
|
||||
|
||||
static void ReportMissingObject(const rct_object_entry * entry);
|
||||
|
||||
class ObjectRepository : public IObjectRepository
|
||||
{
|
||||
std::vector<ObjectRepositoryItem> _items;
|
||||
@@ -163,6 +167,23 @@ public:
|
||||
return object;
|
||||
}
|
||||
|
||||
void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override
|
||||
{
|
||||
ObjectRepositoryItem * item = &_items[ori->Id];
|
||||
|
||||
Guard::Assert(item->LoadedObject == nullptr);
|
||||
item->LoadedObject = object;
|
||||
}
|
||||
|
||||
void UnregisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override
|
||||
{
|
||||
ObjectRepositoryItem * item = &_items[ori->Id];
|
||||
if (item->LoadedObject == object)
|
||||
{
|
||||
item->LoadedObject = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AddObject(const rct_object_entry * objectEntry, const void * data, size_t dataSize) override
|
||||
{
|
||||
char objectName[9] = { 0 };
|
||||
@@ -364,8 +385,9 @@ private:
|
||||
const ObjectRepositoryItem * conflict = FindObject(&item->ObjectEntry);
|
||||
if (conflict == nullptr)
|
||||
{
|
||||
size_t index = _items.size();
|
||||
item->Id = index;
|
||||
_items.push_back(*item);
|
||||
size_t index = _items.size() - 1;
|
||||
_itemMap[item->ObjectEntry] = index;
|
||||
return true;
|
||||
}
|
||||
@@ -554,9 +576,7 @@ IObjectRepository * GetObjectRepository()
|
||||
return _objectRepository;
|
||||
}
|
||||
|
||||
Object * _loadedObjects[OBJECT_ENTRY_COUNT] = { nullptr };
|
||||
|
||||
int GetObjectEntryIndex(uint8 objectType, uint8 entryIndex)
|
||||
static int GetObjectEntryIndex(uint8 objectType, uint8 entryIndex)
|
||||
{
|
||||
int result = 0;
|
||||
for (uint8 i = 0; i < objectType; i++)
|
||||
@@ -590,95 +610,62 @@ extern "C"
|
||||
|
||||
bool object_load_chunk(int groupIndex, const rct_object_entry * entry, int * outGroupIndex)
|
||||
{
|
||||
IObjectRepository * objectRepository = GetObjectRepository();
|
||||
const ObjectRepositoryItem * ori = objectRepository->FindObject(entry);
|
||||
if (ori == nullptr)
|
||||
{
|
||||
utf8 objName[9] = { 0 };
|
||||
Memory::Copy(objName, ori->ObjectEntry.name, 8);
|
||||
Console::Error::WriteFormat("[%s]: Object not found.", objName);
|
||||
Console::Error::WriteLine();
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
Object * object = objectRepository->LoadObject(ori);
|
||||
if (object == nullptr)
|
||||
{
|
||||
utf8 objName[9] = { 0 };
|
||||
Memory::Copy(objName, ori->ObjectEntry.name, 8);
|
||||
Console::Error::WriteFormat("[%s]: Object could not be loaded.", objName);
|
||||
Console::Error::WriteLine();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 objectType = object->GetObjectType();
|
||||
void * * chunkList = object_entry_groups[objectType].chunks;
|
||||
if (groupIndex == -1)
|
||||
{
|
||||
for (groupIndex = 0; chunkList[groupIndex] != (void*)-1; groupIndex++)
|
||||
{
|
||||
if (groupIndex + 1 >= object_entry_group_counts[objectType])
|
||||
{
|
||||
log_error("Object Load failed due to too many objects of a certain type.");
|
||||
delete object;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
chunkList[groupIndex] = object->GetLegacyData();
|
||||
if (outGroupIndex != nullptr)
|
||||
{
|
||||
*outGroupIndex = groupIndex;
|
||||
}
|
||||
|
||||
rct_object_entry_extended * extendedEntry = &object_entry_groups[objectType].entries[groupIndex];
|
||||
Memory::Copy<void>(extendedEntry, object->GetObjectEntry(), sizeof(rct_object_entry));
|
||||
extendedEntry->chunk_size = 0;
|
||||
|
||||
int loadedObjectIndex = GetObjectEntryIndex(objectType, groupIndex);
|
||||
delete _loadedObjects[loadedObjectIndex];
|
||||
_loadedObjects[loadedObjectIndex] = object;
|
||||
return true;
|
||||
// IObjectRepository * objectRepository = GetObjectRepository();
|
||||
// const ObjectRepositoryItem * ori = objectRepository->FindObject(entry);
|
||||
// if (ori == nullptr)
|
||||
// {
|
||||
// ReportMissingObject(entry);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Object * object = objectRepository->LoadObject(ori);
|
||||
// if (object == nullptr)
|
||||
// {
|
||||
// utf8 objName[9] = { 0 };
|
||||
// Memory::Copy(objName, ori->ObjectEntry.name, 8);
|
||||
// Console::Error::WriteFormat("[%s]: Object could not be loaded.", objName);
|
||||
// Console::Error::WriteLine();
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// uint8 objectType = object->GetObjectType();
|
||||
// void * * chunkList = object_entry_groups[objectType].chunks;
|
||||
// if (groupIndex == -1)
|
||||
// {
|
||||
// for (groupIndex = 0; chunkList[groupIndex] != (void*)-1; groupIndex++)
|
||||
// {
|
||||
// if (groupIndex + 1 >= object_entry_group_counts[objectType])
|
||||
// {
|
||||
// log_error("Object Load failed due to too many objects of a certain type.");
|
||||
// delete object;
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// chunkList[groupIndex] = object->GetLegacyData();
|
||||
// if (outGroupIndex != nullptr)
|
||||
// {
|
||||
// *outGroupIndex = groupIndex;
|
||||
// }
|
||||
//
|
||||
// rct_object_entry_extended * extendedEntry = &object_entry_groups[objectType].entries[groupIndex];
|
||||
// Memory::Copy<void>(extendedEntry, object->GetObjectEntry(), sizeof(rct_object_entry));
|
||||
// extendedEntry->chunk_size = 0;
|
||||
//
|
||||
// int loadedObjectIndex = GetObjectEntryIndex(objectType, groupIndex);
|
||||
// delete _loadedObjects[loadedObjectIndex];
|
||||
// _loadedObjects[loadedObjectIndex] = object;
|
||||
// return true;
|
||||
}
|
||||
|
||||
bool object_load_entries(rct_object_entry * entries)
|
||||
{
|
||||
log_verbose("loading required objects");
|
||||
|
||||
object_unload_all();
|
||||
|
||||
bool loadFailed = false;
|
||||
|
||||
// Load each object
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
if (check_object_entry(&entries[i]))
|
||||
{
|
||||
// Get entry group index
|
||||
int entryGroupIndex = i;
|
||||
for (int j = 0; j < OBJECT_ENTRY_GROUP_COUNT; j++)
|
||||
{
|
||||
if (entryGroupIndex < object_entry_group_counts[j])
|
||||
{
|
||||
break;
|
||||
}
|
||||
entryGroupIndex -= object_entry_group_counts[j];
|
||||
}
|
||||
|
||||
// Load the obect
|
||||
if (!object_load_chunk(entryGroupIndex, &entries[i], NULL)) {
|
||||
// log_error("failed to load entry: %.8s", entries[i].name);
|
||||
// memcpy(gCommonFormatArgs, &entries[i], sizeof(rct_object_entry));
|
||||
loadFailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loadFailed)
|
||||
{
|
||||
object_unload_all();
|
||||
return false;
|
||||
}
|
||||
IObjectManager * objectManger = GetObjectManager();
|
||||
objectManger->LoadObjects(entries, OBJECT_ENTRY_COUNT);
|
||||
|
||||
log_verbose("finished loading required objects");
|
||||
return true;
|
||||
@@ -686,17 +673,20 @@ extern "C"
|
||||
|
||||
void reset_loaded_objects()
|
||||
{
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
Object * object = _loadedObjects[i];
|
||||
if (object != nullptr)
|
||||
{
|
||||
object->Unload();
|
||||
object->Load();
|
||||
}
|
||||
}
|
||||
|
||||
reset_type_to_ride_entry_index_map();
|
||||
// if (_loadedObjects != nullptr)
|
||||
// {
|
||||
// for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
// {
|
||||
// Object * object = _loadedObjects[i];
|
||||
// if (object != nullptr)
|
||||
// {
|
||||
// object->Unload();
|
||||
// object->Load();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// reset_type_to_ride_entry_index_map();
|
||||
}
|
||||
|
||||
void * object_repository_load_object(const rct_object_entry * objectEntry)
|
||||
@@ -717,25 +707,24 @@ extern "C"
|
||||
|
||||
void * object_repository_find_loaded_object(const rct_object_entry * objectEntry)
|
||||
{
|
||||
for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
Object * object = nullptr;
|
||||
|
||||
IObjectRepository * objectRepository = GetObjectRepository();
|
||||
const ObjectRepositoryItem * ori = objectRepository->FindObject(objectEntry);
|
||||
if (ori != nullptr)
|
||||
{
|
||||
Object * object = _loadedObjects[i];
|
||||
if (object != nullptr)
|
||||
{
|
||||
const rct_object_entry * entry = object->GetObjectEntry();
|
||||
if (memcmp(objectEntry->name, entry->name, 8) == 0)
|
||||
{
|
||||
return (void *)object;
|
||||
}
|
||||
}
|
||||
object = ori->LoadedObject;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
return (void *)object;
|
||||
}
|
||||
|
||||
void * object_repository_get_loaded_object(uint8 objectType, uint8 entryIndex)
|
||||
{
|
||||
int index = GetObjectEntryIndex(objectType, entryIndex);
|
||||
return (void *)_loadedObjects[index];
|
||||
|
||||
IObjectManager * objectManager = GetObjectManager();
|
||||
return (void *)objectManager->GetLoadedObject(index);
|
||||
}
|
||||
|
||||
void object_repository_unload(size_t itemIndex)
|
||||
@@ -745,24 +734,8 @@ extern "C"
|
||||
|
||||
void object_unload_all()
|
||||
{
|
||||
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
|
||||
{
|
||||
Object * object = _loadedObjects[i];
|
||||
if (object != nullptr)
|
||||
{
|
||||
object->Unload();
|
||||
delete object;
|
||||
_loadedObjects[i] = nullptr;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < OBJECT_ENTRY_GROUP_COUNT; i++)
|
||||
{
|
||||
for (int j = 0; j < object_entry_group_counts[i]; j++)
|
||||
{
|
||||
memset(&object_entry_groups[i].entries[j], 0xFF, sizeof(rct_object_entry_extended));
|
||||
object_entry_groups[i].chunks[j] = (uint8*)0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
IObjectManager * objectManager = GetObjectManager();
|
||||
objectManager->UnloadAll();
|
||||
}
|
||||
|
||||
void scenario_translate(scenario_index_entry * scenarioEntry, const rct_object_entry * stexObjectEntry)
|
||||
@@ -996,3 +969,11 @@ extern "C"
|
||||
return (int)checksum;
|
||||
}
|
||||
}
|
||||
|
||||
static void ReportMissingObject(const rct_object_entry * entry)
|
||||
{
|
||||
utf8 objName[9] = { 0 };
|
||||
Memory::Copy(objName, entry->name, 8);
|
||||
Console::Error::WriteFormat("[%s]: Object not found.", objName);
|
||||
Console::Error::WriteLine();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ extern "C"
|
||||
|
||||
typedef struct ObjectRepositoryItem
|
||||
{
|
||||
size_t Id;
|
||||
rct_object_entry ObjectEntry;
|
||||
utf8 * Path;
|
||||
utf8 * Name;
|
||||
@@ -67,6 +68,9 @@ interface IObjectRepository
|
||||
virtual const ObjectRepositoryItem * FindObject(const rct_object_entry * objectEntry) const abstract;
|
||||
|
||||
virtual Object * LoadObject(const ObjectRepositoryItem * ori) abstract;
|
||||
virtual void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) abstract;
|
||||
virtual void UnregisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) abstract;
|
||||
|
||||
virtual void AddObject(const rct_object_entry * objectEntry,
|
||||
const void * data,
|
||||
size_t dataSize) abstract;
|
||||
|
||||
@@ -91,7 +91,7 @@ const rct_object_entry_group object_entry_groups[] = {
|
||||
(void**)(gStexEntries ), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text 0x009ADAE4, 0xF4287C
|
||||
};
|
||||
|
||||
int check_object_entry(rct_object_entry *entry)
|
||||
int check_object_entry(const rct_object_entry *entry)
|
||||
{
|
||||
uint32 *dwords = (uint32*)entry;
|
||||
return (0xFFFFFFFF & dwords[0] & dwords[1] & dwords[2] & dwords[3]) + 1 != 0;
|
||||
|
||||
@@ -34,5 +34,6 @@
|
||||
#endif
|
||||
|
||||
void object_list_init();
|
||||
void get_type_entry_index(size_t index, uint8 * outObjectType, uint8 * outEntryIndex);
|
||||
const rct_object_entry * get_loaded_object_entry(size_t index);
|
||||
void * get_loaded_object_chunk(size_t index);
|
||||
|
||||
Reference in New Issue
Block a user