1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

case insensitive cheat identifier

This commit is contained in:
Laserlicht
2025-07-20 02:44:09 +02:00
parent 7fcb0246fb
commit 3975cc3ada
3 changed files with 52 additions and 20 deletions

View File

@@ -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<void(si32)> & callback, bool optional)
CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameWithType(const std::string & scope, const std::string & fullName, const std::function<void(si32)> & 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<void(si32)> & 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<void(si32)> & callback, bool optional, bool bypassDependenciesCheck, bool caseSensitive)
{
assert(!scope.empty());
@@ -150,6 +151,7 @@ CIdentifierStorage::ObjectCallback CIdentifierStorage::ObjectCallback::fromNameA
result.optional = optional;
result.bypassDependenciesCheck = bypassDependenciesCheck;
result.dynamicType = false;
result.caseSensitive = caseSensitive;
return result;
}
@@ -199,36 +201,36 @@ void CIdentifierStorage::tryRequestIdentifier(const std::string & type, const Js
requestIdentifier(ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), callback, true, false));
}
std::optional<si32> CIdentifierStorage::getIdentifier(const std::string & scope, const std::string & type, const std::string & name, bool silent) const
std::optional<si32> CIdentifierStorage::getIdentifier(const std::string & scope, const std::string & type, const std::string & name, bool silent, bool caseSensitive) const
{
//assert(state != ELoadingState::LOADING);
auto options = ObjectCallback::fromNameAndType(scope, type, name, std::function<void(si32)>(), silent, false);
auto options = ObjectCallback::fromNameAndType(scope, type, name, std::function<void(si32)>(), silent, false, caseSensitive);
return getIdentifierImpl(options, silent);
}
std::optional<si32> CIdentifierStorage::getIdentifier(const std::string & type, const JsonNode & name, bool silent) const
std::optional<si32> CIdentifierStorage::getIdentifier(const std::string & type, const JsonNode & name, bool silent, bool caseSensitive) const
{
assert(state != ELoadingState::LOADING);
auto options = ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), std::function<void(si32)>(), silent, false);
auto options = ObjectCallback::fromNameAndType(name.getModScope(), type, name.String(), std::function<void(si32)>(), silent, false, caseSensitive);
return getIdentifierImpl(options, silent);
}
std::optional<si32> CIdentifierStorage::getIdentifier(const JsonNode & name, bool silent) const
std::optional<si32> CIdentifierStorage::getIdentifier(const JsonNode & name, bool silent, bool caseSensitive) const
{
assert(state != ELoadingState::LOADING);
auto options = ObjectCallback::fromNameWithType(name.getModScope(), name.String(), std::function<void(si32)>(), silent);
auto options = ObjectCallback::fromNameWithType(name.getModScope(), name.String(), std::function<void(si32)>(), silent, caseSensitive);
return getIdentifierImpl(options, silent);
}
std::optional<si32> CIdentifierStorage::getIdentifier(const std::string & scope, const std::string & fullName, bool silent) const
std::optional<si32> CIdentifierStorage::getIdentifier(const std::string & scope, const std::string & fullName, bool silent, bool caseSensitive) const
{
assert(state != ELoadingState::LOADING);
auto options = ObjectCallback::fromNameWithType(scope, fullName, std::function<void(si32)>(), silent);
auto options = ObjectCallback::fromNameWithType(scope, fullName, std::function<void(si32)>(), silent, caseSensitive);
return getIdentifierImpl(options, silent);
}
@@ -343,6 +345,34 @@ void CIdentifierStorage::registerObject(const std::string & scope, const std::st
}
}
template <typename MultiMap>
std::pair<typename MultiMap::const_iterator, typename MultiMap::const_iterator>
caseInsensitiveEqualRange(const MultiMap& mmap, const std::string& key)
{
using ConstIt = typename MultiMap::const_iterator;
std::string loweredKey = boost::algorithm::to_lower_copy(key);
ConstIt first = mmap.end();
ConstIt last = mmap.end();
for (ConstIt it = mmap.begin(); it != mmap.end(); ++it)
{
std::string loweredItKey = boost::algorithm::to_lower_copy(it->first);
if (loweredItKey == loweredKey)
{
if (first == mmap.end())
first = it;
last = std::next(it);
} else if (first != mmap.end())
// We've already found the matching range and now it's over
break;
}
return { first, last };
}
std::vector<CIdentifierStorage::ObjectData> CIdentifierStorage::getPossibleIdentifiers(const ObjectCallback & request) const
{
std::set<std::string> allowedScopes;
@@ -410,7 +440,8 @@ std::vector<CIdentifierStorage::ObjectData> CIdentifierStorage::getPossibleIdent
std::string fullID = request.type + '.' + request.name;
auto entries = registeredObjects.equal_range(fullID);
auto entries = request.caseSensitive ? registeredObjects.equal_range(fullID) : caseInsensitiveEqualRange(registeredObjects, fullID);
if (entries.first != entries.second)
{
std::vector<ObjectData> locatedIDs;

View File

@@ -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<void(si32)> & callback, bool optional);
static ObjectCallback fromNameWithType(const std::string & scope, const std::string & fullName, const std::function<void(si32)> & callback, bool optional, bool caseSensitive = true);
/// 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<void(si32)> & callback, bool optional, bool bypassDependenciesCheck);
static ObjectCallback fromNameAndType(const std::string & scope, const std::string & type, const std::string & fullName, const std::function<void(si32)> & callback, bool optional, bool bypassDependenciesCheck, bool caseSensitive = true);
private:
ObjectCallback() = default;
@@ -97,10 +98,10 @@ public:
void tryRequestIdentifier(const std::string & type, const JsonNode & name, const std::function<void(si32)> & callback) const;
/// get identifier immediately. If identifier is not know and not silent call will result in error message
std::optional<si32> getIdentifier(const std::string & scope, const std::string & type, const std::string & name, bool silent = false) const;
std::optional<si32> getIdentifier(const std::string & type, const JsonNode & name, bool silent = false) const;
std::optional<si32> getIdentifier(const JsonNode & name, bool silent = false) const;
std::optional<si32> getIdentifier(const std::string & scope, const std::string & fullName, bool silent = false) const;
std::optional<si32> getIdentifier(const std::string & scope, const std::string & type, const std::string & name, bool silent = false, bool caseSensitive = true) const;
std::optional<si32> getIdentifier(const std::string & type, const JsonNode & name, bool silent = false, bool caseSensitive = true) const;
std::optional<si32> getIdentifier(const JsonNode & name, bool silent = false, bool caseSensitive = true) const;
std::optional<si32> getIdentifier(const std::string & scope, const std::string & fullName, bool silent = false, bool caseSensitive = true) const;
/// registers new object
void registerObject(const std::string & scope, const std::string & type, const std::string & name, si32 identifier);

View File

@@ -428,7 +428,7 @@ void PlayerMessageProcessor::cheatGiveArmy(PlayerColor player, const CGHeroInsta
{
}
std::optional<int32_t> creatureId = LIBRARY->identifiers()->getIdentifier(ModScope::scopeGame(), "creature", creatureIdentifier, false);
std::optional<int32_t> creatureId = LIBRARY->identifiers()->getIdentifier(ModScope::scopeGame(), "creature", creatureIdentifier, false, false);
if(creatureId.has_value())
{
@@ -469,7 +469,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()->getIdentifier(ModScope::scopeGame(), "artifact", word, false, false);
if(artID && LIBRARY->arth->objects[*artID])
gameHandler->giveHeroNewArtifact(hero, ArtifactID(*artID), ArtifactPosition::FIRST_AVAILABLE);
}
@@ -728,7 +728,7 @@ void PlayerMessageProcessor::cheatSkill(PlayerColor player, const CGHeroInstance
return;
}
std::optional<int32_t> skillId = LIBRARY->identifiers()->getIdentifier(ModScope::scopeGame(), "skill", identifier, false);
std::optional<int32_t> skillId = LIBRARY->identifiers()->getIdentifier(ModScope::scopeGame(), "skill", identifier, false, false);
if(!skillId.has_value())
return;