1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

Refactor containers names in CObjectClassesHandler

This commit is contained in:
MichalZr6
2024-08-17 01:19:42 +02:00
parent 5de5ac5eb5
commit 568a792f88
2 changed files with 75 additions and 70 deletions

View File

@@ -120,7 +120,7 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData()
legacyTemplates.insert(std::make_pair(key, tmpl)); legacyTemplates.insert(std::make_pair(key, tmpl));
} }
objects.resize(256); mapObjectTypes.resize(256);
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
assert(dataSize == 256); assert(dataSize == 256);
@@ -162,39 +162,39 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData()
return ret; return ret;
} }
void CObjectClassesHandler::loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj) void CObjectClassesHandler::loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * baseObject)
{ {
auto object = loadSubObjectFromJson(scope, identifier, entry, obj, obj->objects.size()); auto subObject = loadSubObjectFromJson(scope, identifier, entry, baseObject, baseObject->objectTypeHandlers.size());
assert(object); assert(subObject);
obj->objects.push_back(object); baseObject->objectTypeHandlers.push_back(subObject);
registerObject(scope, obj->getJsonKey(), object->getSubTypeName(), object->subtype); registerObject(scope, baseObject->getJsonKey(), subObject->getSubTypeName(), subObject->subtype);
for(const auto & compatID : entry["compatibilityIdentifiers"].Vector()) for(const auto & compatID : entry["compatibilityIdentifiers"].Vector())
registerObject(scope, obj->getJsonKey(), compatID.String(), object->subtype); registerObject(scope, baseObject->getJsonKey(), compatID.String(), subObject->subtype);
} }
void CObjectClassesHandler::loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index) void CObjectClassesHandler::loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * baseObject, size_t index)
{ {
auto object = loadSubObjectFromJson(scope, identifier, entry, obj, index); auto subObject = loadSubObjectFromJson(scope, identifier, entry, baseObject, index);
assert(object); assert(subObject);
if (obj->objects.at(index) != nullptr) if (baseObject->objectTypeHandlers.at(index) != nullptr)
throw std::runtime_error("Attempt to load already loaded object:" + identifier); throw std::runtime_error("Attempt to load already loaded object:" + identifier);
obj->objects.at(index) = object; baseObject->objectTypeHandlers.at(index) = subObject;
registerObject(scope, obj->getJsonKey(), object->getSubTypeName(), object->subtype); registerObject(scope, baseObject->getJsonKey(), subObject->getSubTypeName(), subObject->subtype);
for(const auto & compatID : entry["compatibilityIdentifiers"].Vector()) for(const auto & compatID : entry["compatibilityIdentifiers"].Vector())
registerObject(scope, obj->getJsonKey(), compatID.String(), object->subtype); registerObject(scope, baseObject->getJsonKey(), compatID.String(), subObject->subtype);
} }
TObjectTypeHandler CObjectClassesHandler::loadSubObjectFromJson(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index) TObjectTypeHandler CObjectClassesHandler::loadSubObjectFromJson(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * baseObject, size_t index)
{ {
assert(identifier.find(':') == std::string::npos); assert(identifier.find(':') == std::string::npos);
assert(!scope.empty()); assert(!scope.empty());
std::string handler = obj->handlerName; std::string handler = baseObject->handlerName;
if(!handlerConstructors.count(handler)) if(!handlerConstructors.count(handler))
{ {
logMod->error("Handler with name %s was not found!", handler); logMod->error("Handler with name %s was not found!", handler);
@@ -206,10 +206,10 @@ TObjectTypeHandler CObjectClassesHandler::loadSubObjectFromJson(const std::strin
auto createdObject = handlerConstructors.at(handler)(); auto createdObject = handlerConstructors.at(handler)();
createdObject->modScope = scope; createdObject->modScope = scope;
createdObject->typeName = obj->identifier; createdObject->typeName = baseObject->identifier;
createdObject->subTypeName = identifier; createdObject->subTypeName = identifier;
createdObject->type = obj->id; createdObject->type = baseObject->id;
createdObject->subtype = index; createdObject->subtype = index;
createdObject->init(entry); createdObject->init(entry);
@@ -223,7 +223,7 @@ TObjectTypeHandler CObjectClassesHandler::loadSubObjectFromJson(const std::strin
} }
} }
auto range = legacyTemplates.equal_range(std::make_pair(obj->id, index)); auto range = legacyTemplates.equal_range(std::make_pair(baseObject->id, index));
for (auto & templ : boost::make_iterator_range(range.first, range.second)) for (auto & templ : boost::make_iterator_range(range.first, range.second))
{ {
if (staticObject) if (staticObject)
@@ -238,7 +238,7 @@ TObjectTypeHandler CObjectClassesHandler::loadSubObjectFromJson(const std::strin
} }
legacyTemplates.erase(range.first, range.second); legacyTemplates.erase(range.first, range.second);
logGlobal->debug("Loaded object %s(%d)::%s(%d)", obj->getJsonKey(), obj->id, identifier, index); logGlobal->debug("Loaded object %s(%d)::%s(%d)", baseObject->getJsonKey(), baseObject->id, identifier, index);
return createdObject; return createdObject;
} }
@@ -263,17 +263,17 @@ std::string ObjectClass::getNameTranslated() const
std::unique_ptr<ObjectClass> CObjectClassesHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index) std::unique_ptr<ObjectClass> CObjectClassesHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index)
{ {
auto obj = std::make_unique<ObjectClass>(); auto newObject = std::make_unique<ObjectClass>();
obj->modScope = scope; newObject->modScope = scope;
obj->identifier = name; newObject->identifier = name;
obj->handlerName = json["handler"].String(); newObject->handlerName = json["handler"].String();
obj->base = json["base"]; newObject->base = json["base"];
obj->id = index; newObject->id = index;
VLC->generaltexth->registerString(scope, obj->getNameTextID(), json["name"].String()); VLC->generaltexth->registerString(scope, newObject->getNameTextID(), json["name"].String());
obj->objects.resize(json["lastReservedIndex"].Float() + 1); newObject->objectTypeHandlers.resize(json["lastReservedIndex"].Float() + 1);
for (auto subData : json["types"].Struct()) for (auto subData : json["types"].Struct())
{ {
@@ -284,68 +284,73 @@ std::unique_ptr<ObjectClass> CObjectClassesHandler::loadFromJson(const std::stri
if ( subMeta == "core") if ( subMeta == "core")
{ {
size_t subIndex = subData.second["index"].Integer(); size_t subIndex = subData.second["index"].Integer();
loadSubObject(subData.second.getModScope(), subData.first, subData.second, obj.get(), subIndex); loadSubObject(subData.second.getModScope(), subData.first, subData.second, newObject.get(), subIndex);
} }
else else
{ {
logMod->error("Object %s:%s.%s - attempt to load object with preset index! This option is reserved for built-in mod", subMeta, name, subData.first ); logMod->error("Object %s:%s.%s - attempt to load object with preset index! This option is reserved for built-in mod", subMeta, name, subData.first );
loadSubObject(subData.second.getModScope(), subData.first, subData.second, obj.get()); loadSubObject(subData.second.getModScope(), subData.first, subData.second, newObject.get());
} }
} }
else else
loadSubObject(subData.second.getModScope(), subData.first, subData.second, obj.get()); loadSubObject(subData.second.getModScope(), subData.first, subData.second, newObject.get());
} }
if (obj->id == MapObjectID::MONOLITH_TWO_WAY) if (newObject->id == MapObjectID::MONOLITH_TWO_WAY)
generateExtraMonolithsForRMG(obj.get()); generateExtraMonolithsForRMG(newObject.get());
return obj; return newObject;
} }
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data) void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
{ {
objects.push_back(loadFromJson(scope, data, name, objects.size())); mapObjectTypes.push_back(loadFromJson(scope, data, name, mapObjectTypes.size()));
VLC->identifiersHandler->registerObject(scope, "object", name, objects.back()->id); VLC->identifiersHandler->registerObject(scope, "object", name, mapObjectTypes.back()->id);
} }
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
{ {
assert(objects.at(index) == nullptr); // ensure that this id was not loaded before assert(mapObjectTypes.at(index) == nullptr); // ensure that this id was not loaded before
objects.at(index) = loadFromJson(scope, data, name, index); mapObjectTypes.at(index) = loadFromJson(scope, data, name, index);
VLC->identifiersHandler->registerObject(scope, "object", name, objects.at(index)->id); VLC->identifiersHandler->registerObject(scope, "object", name, mapObjectTypes.at(index)->id);
} }
#pragma optimize("", off)
void CObjectClassesHandler::loadSubObject(const std::string & identifier, JsonNode config, MapObjectID ID, MapObjectSubID subID) void CObjectClassesHandler::loadSubObject(const std::string & identifier, JsonNode config, MapObjectID ID, MapObjectSubID subID)
{ {
config.setType(JsonNode::JsonType::DATA_STRUCT); // ensure that input is not NULL config.setType(JsonNode::JsonType::DATA_STRUCT); // ensure that input is not NULL
assert(objects.at(ID.getNum())); if (identifier == "ranger")
logGlobal->warn("subID of rangers: "+ std::to_string(subID.getNum()));
assert(mapObjectTypes.at(ID.getNum()));
if ( subID.getNum() >= objects.at(ID.getNum())->objects.size()) if (subID.getNum() >= mapObjectTypes.at(ID.getNum())->objectTypeHandlers.size())
objects.at(ID.getNum())->objects.resize(subID.getNum()+1); {
mapObjectTypes.at(ID.getNum())->objectTypeHandlers.resize(subID.getNum() + 1);
}
JsonUtils::inherit(config, objects.at(ID.getNum())->base); JsonUtils::inherit(config, mapObjectTypes.at(ID.getNum())->base);
loadSubObject(config.getModScope(), identifier, config, objects.at(ID.getNum()).get(), subID.getNum()); loadSubObject(config.getModScope(), identifier, config, mapObjectTypes.at(ID.getNum()).get(), subID.getNum());
} }
void CObjectClassesHandler::removeSubObject(MapObjectID ID, MapObjectSubID subID) void CObjectClassesHandler::removeSubObject(MapObjectID ID, MapObjectSubID subID)
{ {
assert(objects.at(ID.getNum())); assert(mapObjectTypes.at(ID.getNum()));
objects.at(ID.getNum())->objects.at(subID.getNum()) = nullptr; mapObjectTypes.at(ID.getNum())->objectTypeHandlers.at(subID.getNum()) = nullptr;
} }
TObjectTypeHandler CObjectClassesHandler::getHandlerFor(MapObjectID type, MapObjectSubID subtype) const TObjectTypeHandler CObjectClassesHandler::getHandlerFor(MapObjectID type, MapObjectSubID subtype) const
{ {
try try
{ {
if (objects.at(type.getNum()) == nullptr) if (mapObjectTypes.at(type.getNum()) == nullptr)
return objects.front()->objects.front(); return mapObjectTypes.front()->objectTypeHandlers.front();
auto subID = subtype.getNum(); auto subID = subtype.getNum();
if (type == Obj::PRISON) if (type == Obj::PRISON)
subID = 0; subID = 0;
auto result = objects.at(type.getNum())->objects.at(subID); auto result = mapObjectTypes.at(type.getNum())->objectTypeHandlers.at(subID);
if (result != nullptr) if (result != nullptr)
return result; return result;
@@ -365,11 +370,11 @@ TObjectTypeHandler CObjectClassesHandler::getHandlerFor(const std::string & scop
std::optional<si32> id = VLC->identifiers()->getIdentifier(scope, "object", type); std::optional<si32> id = VLC->identifiers()->getIdentifier(scope, "object", type);
if(id) if(id)
{ {
const auto & object = objects.at(id.value()); const auto & object = mapObjectTypes.at(id.value());
std::optional<si32> subID = VLC->identifiers()->getIdentifier(scope, object->getJsonKey(), subtype); std::optional<si32> subID = VLC->identifiers()->getIdentifier(scope, object->getJsonKey(), subtype);
if (subID) if (subID)
return object->objects.at(subID.value()); return object->objectTypeHandlers.at(subID.value());
} }
std::string errorString = "Failed to find object of type " + type + "::" + subtype; std::string errorString = "Failed to find object of type " + type + "::" + subtype;
@@ -386,7 +391,7 @@ std::set<MapObjectID> CObjectClassesHandler::knownObjects() const
{ {
std::set<MapObjectID> ret; std::set<MapObjectID> ret;
for(auto & entry : objects) for(auto & entry : mapObjectTypes)
if (entry) if (entry)
ret.insert(entry->id); ret.insert(entry->id);
@@ -397,13 +402,13 @@ std::set<MapObjectSubID> CObjectClassesHandler::knownSubObjects(MapObjectID prim
{ {
std::set<MapObjectSubID> ret; std::set<MapObjectSubID> ret;
if (!objects.at(primaryID.getNum())) if (!mapObjectTypes.at(primaryID.getNum()))
{ {
logGlobal->error("Failed to find object %d", primaryID); logGlobal->error("Failed to find object %d", primaryID);
return ret; return ret;
} }
for(const auto & entry : objects.at(primaryID.getNum())->objects) for(const auto & entry : mapObjectTypes.at(primaryID.getNum())->objectTypeHandlers)
if (entry) if (entry)
ret.insert(entry->subtype); ret.insert(entry->subtype);
@@ -436,12 +441,12 @@ void CObjectClassesHandler::beforeValidate(JsonNode & object)
void CObjectClassesHandler::afterLoadFinalization() void CObjectClassesHandler::afterLoadFinalization()
{ {
for(auto & entry : objects) for(auto & entry : mapObjectTypes)
{ {
if (!entry) if (!entry)
continue; continue;
for(const auto & obj : entry->objects) for(const auto & obj : entry->objectTypeHandlers)
{ {
if (!obj) if (!obj)
continue; continue;
@@ -456,7 +461,7 @@ void CObjectClassesHandler::afterLoadFinalization()
void CObjectClassesHandler::generateExtraMonolithsForRMG(ObjectClass * container) void CObjectClassesHandler::generateExtraMonolithsForRMG(ObjectClass * container)
{ {
//duplicate existing two-way portals to make reserve for RMG //duplicate existing two-way portals to make reserve for RMG
auto& portalVec = container->objects; auto& portalVec = container->objectTypeHandlers;
//FIXME: Monoliths in this vector can be already not useful for every terrain //FIXME: Monoliths in this vector can be already not useful for every terrain
const size_t portalCount = portalVec.size(); const size_t portalCount = portalVec.size();
@@ -500,10 +505,10 @@ std::string CObjectClassesHandler::getObjectName(MapObjectID type, MapObjectSubI
if (handler && handler->hasNameTextID()) if (handler && handler->hasNameTextID())
return handler->getNameTranslated(); return handler->getNameTranslated();
if (objects.at(type.getNum())) if (mapObjectTypes.at(type.getNum()))
return objects.at(type.getNum())->getNameTranslated(); return mapObjectTypes.at(type.getNum())->getNameTranslated();
return objects.front()->getNameTranslated(); return mapObjectTypes.front()->getNameTranslated();
} }
SObjectSounds CObjectClassesHandler::getObjectSounds(MapObjectID type, MapObjectSubID subtype) const SObjectSounds CObjectClassesHandler::getObjectSounds(MapObjectID type, MapObjectSubID subtype) const
@@ -515,27 +520,27 @@ SObjectSounds CObjectClassesHandler::getObjectSounds(MapObjectID type, MapObject
if(type == Obj::PRISON || type == Obj::HERO || type == Obj::SPELL_SCROLL) if(type == Obj::PRISON || type == Obj::HERO || type == Obj::SPELL_SCROLL)
subtype = 0; subtype = 0;
if(objects.at(type.getNum())) if(mapObjectTypes.at(type.getNum()))
return getHandlerFor(type, subtype)->getSounds(); return getHandlerFor(type, subtype)->getSounds();
else else
return objects.front()->objects.front()->getSounds(); return mapObjectTypes.front()->objectTypeHandlers.front()->getSounds();
} }
std::string CObjectClassesHandler::getObjectHandlerName(MapObjectID type) const std::string CObjectClassesHandler::getObjectHandlerName(MapObjectID type) const
{ {
if (objects.at(type.getNum())) if (mapObjectTypes.at(type.getNum()))
return objects.at(type.getNum())->handlerName; return mapObjectTypes.at(type.getNum())->handlerName;
else else
return objects.front()->handlerName; return mapObjectTypes.front()->handlerName;
} }
std::string CObjectClassesHandler::getJsonKey(MapObjectID type) const std::string CObjectClassesHandler::getJsonKey(MapObjectID type) const
{ {
if (objects.at(type.getNum()) != nullptr) if (mapObjectTypes.at(type.getNum()) != nullptr)
return objects.at(type.getNum())->getJsonKey(); return mapObjectTypes.at(type.getNum())->getJsonKey();
logGlobal->warn("Unknown object of type %d!", type); logGlobal->warn("Unknown object of type %d!", type);
return objects.front()->getJsonKey(); return mapObjectTypes.front()->getJsonKey();
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@@ -55,7 +55,7 @@ public:
std::string handlerName; // ID of handler that controls this object, should be determined using handlerConstructor map std::string handlerName; // ID of handler that controls this object, should be determined using handlerConstructor map
JsonNode base; JsonNode base;
std::vector<TObjectTypeHandler> objects; std::vector<TObjectTypeHandler> objectTypeHandlers;
ObjectClass(); ObjectClass();
~ObjectClass(); ~ObjectClass();
@@ -69,7 +69,7 @@ public:
class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase, boost::noncopyable class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase, boost::noncopyable
{ {
/// list of object handlers, each of them handles only one type /// list of object handlers, each of them handles only one type
std::vector< std::unique_ptr<ObjectClass> > objects; std::vector< std::unique_ptr<ObjectClass> > mapObjectTypes;
/// map that is filled during construction with all known handlers. Not serializeable due to usage of std::function /// map that is filled during construction with all known handlers. Not serializeable due to usage of std::function
std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors; std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;