diff --git a/lib/modding/IdentifierStorage.cpp b/lib/modding/IdentifierStorage.cpp index d71afbe98..93fa074d5 100644 --- a/lib/modding/IdentifierStorage.cpp +++ b/lib/modding/IdentifierStorage.cpp @@ -102,7 +102,7 @@ void CIdentifierStorage::requestIdentifier(const ObjectCallback & callback) cons resolveIdentifier(callback); } -CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameWithType(const std::string & scope, const std::string & fullName, const std::function & callback, bool optional) +CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameWithType(const std::string & scope, const std::string & fullName, const std::function & callback, bool optional, bool caseSensitive) { assert(!scope.empty()); @@ -120,10 +120,11 @@ CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameW result.callback = callback; result.optional = optional; result.dynamicType = true; + result.caseSensitive = caseSensitive; return result; } -CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameAndType(const std::string & scope, const std::string & type, const std::string & fullName, const std::function & callback, bool optional, bool bypassDependenciesCheck) +CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameAndType(const std::string & scope, const std::string & type, const std::string & fullName, const std::function & callback, bool optional, bool bypassDependenciesCheck, bool caseSensitive) { assert(!scope.empty()); @@ -150,27 +151,28 @@ CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameA result.optional = optional; result.bypassDependenciesCheck = bypassDependenciesCheck; result.dynamicType = false; + result.caseSensitive = caseSensitive; return result; } void CIdentifierStorage::requestIdentifier(const std::string & scope, const std::string & type, const std::string & name, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameAndType(scope, type, name, callback, false, false)); + requestIdentifier(ObjectCallback::fromNameAndType(scope, type, name, callback, false, false, true)); } void CIdentifierStorage::requestIdentifier(const std::string & scope, const std::string & fullName, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameWithType(scope, fullName, callback, false)); + requestIdentifier(ObjectCallback::fromNameWithType(scope, fullName, callback, false, true)); } void CIdentifierStorage::requestIdentifier(const std::string & type, const JsonNode & name, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), callback, false, false)); + requestIdentifier(ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), callback, false, false, true)); } void CIdentifierStorage::requestIdentifier(const JsonNode & name, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameWithType(name.getModScope(), name.String(), callback, false)); + requestIdentifier(ObjectCallback::fromNameWithType(name.getModScope(), name.String(), callback, false, true)); } void CIdentifierStorage::requestIdentifierIfNotNull(const std::string & type, const JsonNode & name, const std::function & callback) const @@ -181,29 +183,29 @@ void CIdentifierStorage::requestIdentifierIfNotNull(const std::string & type, co void CIdentifierStorage::requestIdentifierIfFound(const std::string & type, const JsonNode & name, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), callback, false, true)); + requestIdentifier(ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), callback, false, true, true)); } void CIdentifierStorage::requestIdentifierIfFound(const std::string & scope, const std::string & type, const std::string & name, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameAndType(scope, type, name, callback, false, true)); + requestIdentifier(ObjectCallback::fromNameAndType(scope, type, name, callback, false, true, true)); } void CIdentifierStorage::tryRequestIdentifier(const std::string & scope, const std::string & type, const std::string & name, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameAndType(scope, type, name, callback, true, false)); + requestIdentifier(ObjectCallback::fromNameAndType(scope, type, name, callback, true, false, true)); } void CIdentifierStorage::tryRequestIdentifier(const std::string & type, const JsonNode & name, const std::function & callback) const { - requestIdentifier(ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), callback, true, false)); + requestIdentifier(ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), callback, true, false, true)); } std::optional CIdentifierStorage::getIdentifier(const std::string & scope, const std::string & type, const std::string & name, bool silent) const { //assert(state != ELoadingState::LOADING); - auto options = ObjectCallback::fromNameAndType(scope, type, name, std::function(), silent, false); + auto options = ObjectCallback::fromNameAndType(scope, type, name, std::function(), silent, false, true); return getIdentifierImpl(options, silent); } @@ -211,7 +213,7 @@ std::optional CIdentifierStorage::getIdentifier(const std::string & type, { assert(state != ELoadingState::LOADING); - auto options = ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), std::function(), silent, false); + auto options = ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), std::function(), silent, false, true); return getIdentifierImpl(options, silent); } @@ -220,7 +222,7 @@ std::optional CIdentifierStorage::getIdentifier(const JsonNode & name, boo { assert(state != ELoadingState::LOADING); - auto options = ObjectCallback::fromNameWithType(name.getModScope(), name.String(), std::function(), silent); + auto options = ObjectCallback::fromNameWithType(name.getModScope(), name.String(), std::function(), silent, true); return getIdentifierImpl(options, silent); } @@ -228,7 +230,13 @@ std::optional CIdentifierStorage::getIdentifier(const std::string & scope, { assert(state != ELoadingState::LOADING); - auto options = ObjectCallback::fromNameWithType(scope, fullName, std::function(), silent); + auto options = ObjectCallback::fromNameWithType(scope, fullName, std::function(), silent, true); + return getIdentifierImpl(options, silent); +} + +std::optional CIdentifierStorage::getIdentifierCaseInsensitive(const std::string & scope, const std::string & type, const std::string & name, bool silent) const +{ + auto options = ObjectCallback::fromNameAndType(scope, type, name, std::function(), silent, false, false); return getIdentifierImpl(options, silent); } @@ -336,6 +344,7 @@ void CIdentifierStorage::registerObject(const std::string & scope, const std::st { logMod->trace("registered '%s' as %s:%s", fullID, scope, identifier); registeredObjects.insert(mapping); + registeredObjectsCaseLookup[boost::algorithm::to_lower_copy(mapping.first)] = mapping.first; } else { @@ -409,8 +418,10 @@ std::vector CIdentifierStorage::getPossibleIdent } std::string fullID = request.type + '.' + request.name; + std::string fullIDCaseCorrected = request.caseSensitive ? fullID : registeredObjectsCaseLookup.at(boost::algorithm::to_lower_copy(fullID)); + + auto entries = registeredObjects.equal_range(fullIDCaseCorrected); - auto entries = registeredObjects.equal_range(fullID); if (entries.first != entries.second) { std::vector locatedIDs; diff --git a/lib/modding/IdentifierStorage.h b/lib/modding/IdentifierStorage.h index 51ab94c1f..826859cd0 100644 --- a/lib/modding/IdentifierStorage.h +++ b/lib/modding/IdentifierStorage.h @@ -34,12 +34,13 @@ class DLL_LINKAGE CIdentifierStorage bool optional; bool bypassDependenciesCheck; bool dynamicType; + bool caseSensitive; /// Builds callback from identifier in form "targetMod:type.name" - static ObjectCallback fromNameWithType(const std::string & scope, const std::string & fullName, const std::function & callback, bool optional); + static ObjectCallback fromNameWithType(const std::string & scope, const std::string & fullName, const std::function & callback, bool optional, bool caseSensitive); /// Builds callback from identifier in form "targetMod:name" - static ObjectCallback fromNameAndType(const std::string & scope, const std::string & type, const std::string & fullName, const std::function & callback, bool optional, bool bypassDependenciesCheck); + static ObjectCallback fromNameAndType(const std::string & scope, const std::string & type, const std::string & fullName, const std::function & callback, bool optional, bool bypassDependenciesCheck, bool caseSensitive); private: ObjectCallback() = default; @@ -57,6 +58,7 @@ class DLL_LINKAGE CIdentifierStorage }; std::multimap registeredObjects; + std::map registeredObjectsCaseLookup; mutable std::vector scheduledRequests; /// All non-optional requests that have failed to resolve, for debug & error reporting @@ -101,6 +103,7 @@ public: std::optional getIdentifier(const std::string & type, const JsonNode & name, bool silent = false) const; std::optional getIdentifier(const JsonNode & name, bool silent = false) const; std::optional getIdentifier(const std::string & scope, const std::string & fullName, bool silent = false) const; + std::optional getIdentifierCaseInsensitive(const std::string & scope, const std::string & type, const std::string & name, bool silent) const; /// registers new object void registerObject(const std::string & scope, const std::string & type, const std::string & name, si32 identifier); diff --git a/server/processors/PlayerMessageProcessor.cpp b/server/processors/PlayerMessageProcessor.cpp index 68dc10276..ae3b567cd 100644 --- a/server/processors/PlayerMessageProcessor.cpp +++ b/server/processors/PlayerMessageProcessor.cpp @@ -427,7 +427,7 @@ void PlayerMessageProcessor::cheatGiveArmy(PlayerColor player, const CGHeroInsta { } - std::optional creatureId = LIBRARY->identifiers()->getIdentifier(ModScope::scopeGame(), "creature", creatureIdentifier, false); + std::optional creatureId = LIBRARY->identifiers()->getIdentifierCaseInsensitive(ModScope::scopeGame(), "creature", creatureIdentifier, false); if(creatureId.has_value()) { @@ -468,7 +468,7 @@ void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHero { for (auto const & word : words) { - auto artID = LIBRARY->identifiers()->getIdentifier(ModScope::scopeGame(), "artifact", word, false); + auto artID = LIBRARY->identifiers()->getIdentifierCaseInsensitive(ModScope::scopeGame(), "artifact", word, false); if(artID && LIBRARY->arth->objects[*artID]) gameHandler->giveHeroNewArtifact(hero, ArtifactID(*artID), ArtifactPosition::FIRST_AVAILABLE); } @@ -727,7 +727,7 @@ void PlayerMessageProcessor::cheatSkill(PlayerColor player, const CGHeroInstance return; } - std::optional skillId = LIBRARY->identifiers()->getIdentifier(ModScope::scopeGame(), "skill", identifier, false); + std::optional skillId = LIBRARY->identifiers()->getIdentifierCaseInsensitive(ModScope::scopeGame(), "skill", identifier, false); if(!skillId.has_value()) return;