mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #13379 from Gymnasiast/json-id-in-repo
Allow object lookup using new JSON id
This commit is contained in:
commit
3c1aaa97d7
|
@ -2340,7 +2340,7 @@ void NetworkBase::Client_Handle_OBJECTS_LIST(NetworkConnection& connection, Netw
|
|||
uint32_t flags = 0;
|
||||
packet >> checksum >> flags;
|
||||
|
||||
const auto* object = repo.FindObject(objectName);
|
||||
const auto* object = repo.FindObjectLegacy(objectName);
|
||||
// This could potentially request the object if checksums don't match, but since client
|
||||
// won't replace its version with server-provided one, we don't do that.
|
||||
if (object == nullptr)
|
||||
|
@ -2482,7 +2482,7 @@ void NetworkBase::Server_Handle_MAPREQUEST(NetworkConnection& connection, Networ
|
|||
// This is required, as packet does not have null terminator
|
||||
std::string s(name, name + 8);
|
||||
log_verbose("Client requested object %s", s.c_str());
|
||||
const ObjectRepositoryItem* item = repo.FindObject(s.c_str());
|
||||
const ObjectRepositoryItem* item = repo.FindObjectLegacy(s.c_str());
|
||||
if (item == nullptr)
|
||||
{
|
||||
log_warning("Client tried getting non-existent object %s from us.", s.c_str());
|
||||
|
|
|
@ -44,7 +44,7 @@ void BannerObject::ReadLegacy(IReadObjectContext* context, OpenRCT2::IStream* st
|
|||
auto identifier = GetLegacyIdentifier();
|
||||
|
||||
auto& objectRepository = context->GetObjectRepository();
|
||||
auto item = objectRepository.FindObject(identifier);
|
||||
auto item = objectRepository.FindObjectLegacy(identifier);
|
||||
if (item != nullptr)
|
||||
{
|
||||
auto sourceGame = item->GetFirstSourceGame();
|
||||
|
|
|
@ -48,7 +48,7 @@ void FootpathItemObject::ReadLegacy(IReadObjectContext* context, OpenRCT2::IStre
|
|||
auto identifier = GetLegacyIdentifier();
|
||||
|
||||
auto& objectRepository = context->GetObjectRepository();
|
||||
auto item = objectRepository.FindObject(identifier);
|
||||
auto item = objectRepository.FindObjectLegacy(identifier);
|
||||
if (item != nullptr)
|
||||
{
|
||||
auto sourceGame = item->GetFirstSourceGame();
|
||||
|
|
|
@ -101,10 +101,9 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
Object* LoadObject(const rct_object_entry* entry) override
|
||||
Object* RepositoryItemToObject(const ObjectRepositoryItem* ori)
|
||||
{
|
||||
Object* loadedObject = nullptr;
|
||||
const ObjectRepositoryItem* ori = _objectRepository.FindObject(entry);
|
||||
if (ori != nullptr)
|
||||
{
|
||||
loadedObject = ori->LoadedObject;
|
||||
|
@ -132,6 +131,18 @@ public:
|
|||
return loadedObject;
|
||||
}
|
||||
|
||||
Object* LoadObject(std::string_view identifier) override
|
||||
{
|
||||
const ObjectRepositoryItem* ori = _objectRepository.FindObject(identifier);
|
||||
return RepositoryItemToObject(ori);
|
||||
}
|
||||
|
||||
Object* LoadObject(const rct_object_entry* entry) override
|
||||
{
|
||||
const ObjectRepositoryItem* ori = _objectRepository.FindObject(entry);
|
||||
return RepositoryItemToObject(ori);
|
||||
}
|
||||
|
||||
void LoadObjects(const rct_object_entry* entries, size_t count) override
|
||||
{
|
||||
// Find all the required objects
|
||||
|
@ -222,52 +233,52 @@ public:
|
|||
// loaded RCT1 and RCT2 save files.
|
||||
|
||||
// Surfaces
|
||||
LoadObject("#RCT2SGR");
|
||||
LoadObject("#RCT2SSY");
|
||||
LoadObject("#RCT2SDI");
|
||||
LoadObject("#RCT2SRO");
|
||||
LoadObject("#RCT2SMA");
|
||||
LoadObject("#RCT2SCH");
|
||||
LoadObject("#RCT2SGC");
|
||||
LoadObject("#RCT2SIC");
|
||||
LoadObject("#RCT2SIR");
|
||||
LoadObject("#RCT2SIY");
|
||||
LoadObject("#RCT2SIP");
|
||||
LoadObject("#RCT2SIG");
|
||||
LoadObject("#RCT2SSR");
|
||||
LoadObject("#RCT2SSA");
|
||||
LoadObject("rct2.surface.grass");
|
||||
LoadObject("rct2.surface.sand");
|
||||
LoadObject("rct2.surface.dirt");
|
||||
LoadObject("rct2.surface.rock");
|
||||
LoadObject("rct2.surface.martian");
|
||||
LoadObject("rct2.surface.chequerboard");
|
||||
LoadObject("rct2.surface.grassclumps");
|
||||
LoadObject("rct2.surface.ice");
|
||||
LoadObject("rct2.surface.gridred");
|
||||
LoadObject("rct2.surface.gridyellow");
|
||||
LoadObject("rct2.surface.gridpurple");
|
||||
LoadObject("rct2.surface.gridgreen");
|
||||
LoadObject("rct2.surface.sandred");
|
||||
LoadObject("rct2.surface.sandbrown");
|
||||
|
||||
// Edges
|
||||
LoadObject("#RCT2ERO");
|
||||
LoadObject("#RCT2EWR");
|
||||
LoadObject("#RCT2EWB");
|
||||
LoadObject("#RCT2EIC");
|
||||
LoadObject("#RCT1EBR");
|
||||
LoadObject("#RCT1EIR");
|
||||
LoadObject("#RCT1EGY");
|
||||
LoadObject("#RCT1EYE");
|
||||
LoadObject("#RCT1ERE");
|
||||
LoadObject("#RCT1EPU");
|
||||
LoadObject("#RCT1EGR");
|
||||
LoadObject("#RCT1ESN");
|
||||
LoadObject("#RCT1ESG");
|
||||
LoadObject("#RCT1ESA");
|
||||
LoadObject("#RCT1ESB");
|
||||
LoadObject("rct2.edge.rock");
|
||||
LoadObject("rct2.edge.woodred");
|
||||
LoadObject("rct2.edge.woodblack");
|
||||
LoadObject("rct2.edge.ice");
|
||||
LoadObject("rct1.edge.brick");
|
||||
LoadObject("rct1.edge.iron");
|
||||
LoadObject("rct1.aa.edge.grey");
|
||||
LoadObject("rct1.aa.edge.yellow");
|
||||
LoadObject("rct1.aa.edge.red");
|
||||
LoadObject("rct1.ll.edge.purple");
|
||||
LoadObject("rct1.ll.edge.green");
|
||||
LoadObject("rct1.ll.edge.stonebrown");
|
||||
LoadObject("rct1.ll.edge.stonegrey");
|
||||
LoadObject("rct1.ll.edge.skyscrapera");
|
||||
LoadObject("rct1.ll.edge.skyscraperb");
|
||||
|
||||
// Stations
|
||||
LoadObject("#RCT2STN");
|
||||
LoadObject("#RCT2STW");
|
||||
LoadObject("#RCT2STV");
|
||||
LoadObject("#RCT2ST3");
|
||||
LoadObject("#RCT2ST4");
|
||||
LoadObject("#RCT2STJ");
|
||||
LoadObject("#RCT2STL");
|
||||
LoadObject("#RCT2STC");
|
||||
LoadObject("#RCT2STA");
|
||||
LoadObject("#RCT2STS");
|
||||
LoadObject("#RCT2STP");
|
||||
LoadObject("#RCT2STE");
|
||||
LoadObject("#ORCT2SN");
|
||||
LoadObject("rct2.station.plain");
|
||||
LoadObject("rct2.station.wooden");
|
||||
LoadObject("rct2.station.canvastent");
|
||||
LoadObject("rct2.station.castlegrey");
|
||||
LoadObject("rct2.station.castlebrown");
|
||||
LoadObject("rct2.station.jungle");
|
||||
LoadObject("rct2.station.log");
|
||||
LoadObject("rct2.station.classical");
|
||||
LoadObject("rct2.station.abstract");
|
||||
LoadObject("rct2.station.snow");
|
||||
LoadObject("rct2.station.pagoda");
|
||||
LoadObject("rct2.station.space");
|
||||
LoadObject("openrct2.station.noentrance");
|
||||
}
|
||||
|
||||
static rct_string_id GetObjectSourceGameString(const ObjectSourceGame sourceGame)
|
||||
|
@ -304,13 +315,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
Object* LoadObject(const std::string& name)
|
||||
{
|
||||
rct_object_entry entry{};
|
||||
std::copy_n(name.c_str(), 8, entry.name);
|
||||
return LoadObject(&entry);
|
||||
}
|
||||
|
||||
int32_t FindSpareSlot(uint8_t objectType)
|
||||
{
|
||||
size_t firstIndex = GetIndexFromTypeEntry(objectType, 0);
|
||||
|
|
|
@ -30,6 +30,7 @@ struct IObjectManager
|
|||
virtual ObjectEntryIndex GetLoadedObjectEntryIndex(const Object* object) abstract;
|
||||
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry* entries) abstract;
|
||||
|
||||
virtual Object* LoadObject(std::string_view identifier) abstract;
|
||||
virtual Object* LoadObject(const rct_object_entry* entry) abstract;
|
||||
virtual void LoadObjects(const rct_object_entry* entries, size_t count) abstract;
|
||||
virtual void LoadDefaultObjects() abstract;
|
||||
|
|
|
@ -68,13 +68,14 @@ struct ObjectEntryEqual
|
|||
}
|
||||
};
|
||||
|
||||
using ObjectIdentifierMap = std::unordered_map<std::string, size_t>;
|
||||
using ObjectEntryMap = std::unordered_map<rct_object_entry, size_t, ObjectEntryHash, ObjectEntryEqual>;
|
||||
|
||||
class ObjectFileIndex final : public FileIndex<ObjectRepositoryItem>
|
||||
{
|
||||
private:
|
||||
static constexpr uint32_t MAGIC_NUMBER = 0x5844494F; // OIDX
|
||||
static constexpr uint16_t VERSION = 21;
|
||||
static constexpr uint16_t VERSION = 22;
|
||||
static constexpr auto PATTERN = "*.dat;*.pob;*.json;*.parkobj";
|
||||
|
||||
IObjectRepository& _objectRepository;
|
||||
|
@ -111,6 +112,7 @@ public:
|
|||
if (object != nullptr)
|
||||
{
|
||||
ObjectRepositoryItem item = {};
|
||||
item.Identifier = object->GetIdentifier();
|
||||
item.ObjectEntry = *object->GetObjectEntry();
|
||||
item.Path = path;
|
||||
item.Name = object->GetName();
|
||||
|
@ -125,6 +127,7 @@ public:
|
|||
protected:
|
||||
void Serialise(IStream* stream, const ObjectRepositoryItem& item) const override
|
||||
{
|
||||
stream->WriteValue(item.Identifier);
|
||||
stream->WriteValue(item.ObjectEntry);
|
||||
stream->WriteString(item.Path);
|
||||
stream->WriteString(item.Name);
|
||||
|
@ -170,6 +173,7 @@ protected:
|
|||
{
|
||||
ObjectRepositoryItem item;
|
||||
|
||||
item.Identifier = stream->ReadStdString();
|
||||
item.ObjectEntry = stream->ReadValue<rct_object_entry>();
|
||||
item.Path = stream->ReadStdString();
|
||||
item.Name = stream->ReadStdString();
|
||||
|
@ -227,6 +231,7 @@ class ObjectRepository final : public IObjectRepository
|
|||
std::shared_ptr<IPlatformEnvironment> const _env;
|
||||
ObjectFileIndex const _fileIndex;
|
||||
std::vector<ObjectRepositoryItem> _items;
|
||||
ObjectIdentifierMap _newItemMap;
|
||||
ObjectEntryMap _itemMap;
|
||||
|
||||
public:
|
||||
|
@ -266,7 +271,7 @@ public:
|
|||
return _items.data();
|
||||
}
|
||||
|
||||
const ObjectRepositoryItem* FindObject(const std::string_view& legacyIdentifier) const override
|
||||
const ObjectRepositoryItem* FindObjectLegacy(const std::string_view& legacyIdentifier) const override
|
||||
{
|
||||
rct_object_entry entry = {};
|
||||
entry.SetName(legacyIdentifier);
|
||||
|
@ -279,6 +284,16 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const ObjectRepositoryItem* FindObject(std::string_view identifier) const override final
|
||||
{
|
||||
auto kvp = _newItemMap.find(std::string(identifier));
|
||||
if (kvp != _newItemMap.end())
|
||||
{
|
||||
return &_items[kvp->second];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const override final
|
||||
{
|
||||
auto kvp = _itemMap.find(*objectEntry);
|
||||
|
@ -408,6 +423,7 @@ private:
|
|||
void ClearItems()
|
||||
{
|
||||
_items.clear();
|
||||
_newItemMap.clear();
|
||||
_itemMap.clear();
|
||||
}
|
||||
|
||||
|
@ -425,10 +441,15 @@ private:
|
|||
|
||||
// Rebuild item map
|
||||
_itemMap.clear();
|
||||
_newItemMap.clear();
|
||||
for (size_t i = 0; i < _items.size(); i++)
|
||||
{
|
||||
rct_object_entry entry = _items[i].ObjectEntry;
|
||||
_itemMap[entry] = i;
|
||||
if (!_items[i].Identifier.empty())
|
||||
{
|
||||
_newItemMap[_items[i].Identifier] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,6 +478,10 @@ private:
|
|||
auto copy = item;
|
||||
copy.Id = index;
|
||||
_items.push_back(copy);
|
||||
if (!item.Identifier.empty())
|
||||
{
|
||||
_newItemMap[item.Identifier] = index;
|
||||
}
|
||||
_itemMap[item.ObjectEntry] = index;
|
||||
return true;
|
||||
}
|
||||
|
@ -746,7 +771,7 @@ const ObjectRepositoryItem* object_repository_find_object_by_entry(const rct_obj
|
|||
const ObjectRepositoryItem* object_repository_find_object_by_name(const char* name)
|
||||
{
|
||||
auto& objectRepository = GetContext()->GetObjectRepository();
|
||||
return objectRepository.FindObject(name);
|
||||
return objectRepository.FindObjectLegacy(name);
|
||||
}
|
||||
|
||||
bool object_entry_compare(const rct_object_entry* a, const rct_object_entry* b)
|
||||
|
|
|
@ -37,6 +37,7 @@ struct rct_drawpixelinfo;
|
|||
struct ObjectRepositoryItem
|
||||
{
|
||||
size_t Id;
|
||||
std::string Identifier; // e.g. rct2.c3d
|
||||
rct_object_entry ObjectEntry;
|
||||
std::string Path;
|
||||
std::string Name;
|
||||
|
@ -71,7 +72,8 @@ struct IObjectRepository
|
|||
virtual void Construct(int32_t language) abstract;
|
||||
virtual size_t GetNumObjects() const abstract;
|
||||
virtual const ObjectRepositoryItem* GetObjects() const abstract;
|
||||
virtual const ObjectRepositoryItem* FindObject(const std::string_view& legacyIdentifier) const abstract;
|
||||
virtual const ObjectRepositoryItem* FindObjectLegacy(const std::string_view& legacyIdentifier) const abstract;
|
||||
virtual const ObjectRepositoryItem* FindObject(std::string_view identifier) const abstract;
|
||||
virtual const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const abstract;
|
||||
|
||||
virtual std::unique_ptr<Object> LoadObject(const ObjectRepositoryItem* ori) abstract;
|
||||
|
|
|
@ -526,7 +526,7 @@ private:
|
|||
for (const char* objectName : objects)
|
||||
{
|
||||
auto& objectRepository = OpenRCT2::GetContext()->GetObjectRepository();
|
||||
auto foundObject = objectRepository.FindObject(objectName);
|
||||
auto foundObject = objectRepository.FindObjectLegacy(objectName);
|
||||
if (foundObject != nullptr)
|
||||
{
|
||||
uint8_t objectType = foundObject->ObjectEntry.GetType();
|
||||
|
|
|
@ -143,22 +143,22 @@ namespace RCT1
|
|||
{
|
||||
static constexpr const uint8_t map[] =
|
||||
{
|
||||
TERRAIN_EDGE_ROCK, // #RCT2ERO
|
||||
TERRAIN_EDGE_BRICK, // #RCT1EBR
|
||||
TERRAIN_EDGE_IRON, // #RCT1EIR
|
||||
TERRAIN_EDGE_WOOD_RED, // #RCT2EWR
|
||||
TERRAIN_EDGE_GREY, // #RCT1EGY
|
||||
TERRAIN_EDGE_YELLOW, // #RCT1EYE
|
||||
TERRAIN_EDGE_WOOD_BLACK, // #RCT2EWB
|
||||
TERRAIN_EDGE_RED, // #RCT1ERE
|
||||
TERRAIN_EDGE_ICE, // #RCT2EIC
|
||||
TERRAIN_EDGE_PURPLE, // #RCT2EIC
|
||||
TERRAIN_EDGE_GREEN, // #RCT1EGR
|
||||
TERRAIN_EDGE_STONE_BROWN, // #RCT1ESN
|
||||
TERRAIN_EDGE_STONE_GREY, // #RCT1ESG
|
||||
TERRAIN_EDGE_SKYSCRAPER_A, // #RCT1ESA
|
||||
TERRAIN_EDGE_SKYSCRAPER_B, // #RCT1ESB
|
||||
TERRAIN_EDGE_ROCK // #RCT2ERO (Unused)
|
||||
TERRAIN_EDGE_ROCK, // rct2.edge.rock
|
||||
TERRAIN_EDGE_BRICK, // rct1.edge.brick
|
||||
TERRAIN_EDGE_IRON, // rct1.edge.iron
|
||||
TERRAIN_EDGE_WOOD_RED, // rct2.edge.woodred
|
||||
TERRAIN_EDGE_GREY, // rct1.aa.edge.grey
|
||||
TERRAIN_EDGE_YELLOW, // rct1.aa.edge.yellow
|
||||
TERRAIN_EDGE_WOOD_BLACK, // rct2.edge.woodblack
|
||||
TERRAIN_EDGE_RED, // rct1.aa.edge.red
|
||||
TERRAIN_EDGE_ICE, // rct2.edge.ice
|
||||
TERRAIN_EDGE_PURPLE, // rct1.ll.edge.purple
|
||||
TERRAIN_EDGE_GREEN, // rct1.ll.edge.green
|
||||
TERRAIN_EDGE_STONE_BROWN, // rct1.ll.edge.stonebrown
|
||||
TERRAIN_EDGE_STONE_GREY, // rct1.ll.edge.stonegrey
|
||||
TERRAIN_EDGE_SKYSCRAPER_A, // rct1.ll.edge.skyscrapera
|
||||
TERRAIN_EDGE_SKYSCRAPER_B, // rct1.ll.edge.skyscraperb
|
||||
TERRAIN_EDGE_ROCK // rct2.edge.rock (Unused)
|
||||
};
|
||||
Guard::ArgumentInRange<size_t>(terrainEdge, 0, std::size(map), "Unsupported RCT1 terrain edge.");
|
||||
return map[terrainEdge];
|
||||
|
|
|
@ -164,7 +164,7 @@ public:
|
|||
bool entryIsNotSeparate = false;
|
||||
if (entry.empty())
|
||||
{
|
||||
const ObjectRepositoryItem* ori = repo.FindObject(item.ObjectEntry.c_str());
|
||||
const ObjectRepositoryItem* ori = repo.FindObjectLegacy(item.ObjectEntry.c_str());
|
||||
|
||||
if (ori == nullptr || !RideTypeDescriptors[rideType].HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY))
|
||||
entryIsNotSeparate = true;
|
||||
|
@ -198,7 +198,7 @@ public:
|
|||
bool entryIsNotSeparate = false;
|
||||
if (entry.empty())
|
||||
{
|
||||
const ObjectRepositoryItem* ori = repo.FindObject(item.ObjectEntry.c_str());
|
||||
const ObjectRepositoryItem* ori = repo.FindObjectLegacy(item.ObjectEntry.c_str());
|
||||
|
||||
if (ori == nullptr || !RideTypeDescriptors[rideType].HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY))
|
||||
entryIsNotSeparate = true;
|
||||
|
|
Loading…
Reference in New Issue