nekiro / TFS-1.5-Downgrades

Alternative forgottenserver versions for older protocols support
72 stars 83 forks source link

Revscript Talkaction Params do not work #130

Open NRH-AA opened 2 years ago

NRH-AA commented 2 years ago

Protocol version All versions. This fix was added later in the 1.5 master branch

Describe the bug Talkactions with params do not work in revscript.

To Reproduce Steps to reproduce the behavior: Create a revscript talkaction that uses params: !deposit all / !deposit 1000 It will not work at all. If you type "!deposit" that will work fine but nothing with params.

Expected behavior Params should be registered and read.

Sorry I have no idea how to make a pull-request. Hopefully someone can.

Talkaction.cpp add

#include <boost/algorithm/algorithm.hpp>
#include <boost/algorithm/string.hpp>

Change TalkActionResult_t TalkActions::playerSaySpell(Player* player, SpeakClasses type, const std::string& words) const

TalkActionResult_t TalkActions::playerSaySpell(Player* player, SpeakClasses type, const std::string& words) const
{
    size_t wordsLength = words.length();
    for (auto it = talkActions.begin(); it != talkActions.end();) {
        const std::string& talkactionWords = it->first;
        if (!caseInsensitiveStartsWith(words, talkactionWords)) {
            ++it;
            continue;
        }

        std::string param;
        if (wordsLength != talkactionWords.size()) {
            param = words.substr(talkactionWords.size());
            if (param.front() != ' ') {
                ++it;
                continue;
            }
            boost::algorithm::trim_left(param);

            std::string separator = it->second.getSeparator();
            if (separator != " ") {
                if (!param.empty()) {
                    if (param != separator) {
                        ++it;
                        continue;
                    } else {
                        param.erase(param.begin());
                    }
                }
            }
        }

        if (it->second.fromLua) {
            if (it->second.getNeedAccess() && !player->getGroup()->access) {
                return TALKACTION_CONTINUE;
            }

            if (player->getAccountType() < it->second.getRequiredAccountType()) {
                return TALKACTION_CONTINUE;
            }
        }

        if (it->second.executeSay(player, talkactionWords, param, type)) {
            return TALKACTION_CONTINUE;
        }
        return TALKACTION_BREAK;
    }
    return TALKACTION_CONTINUE;
}

In tools.h Add all of this under generateToken

// checks that str1 is equivalent to str2 ignoring letter case
bool caseInsensitiveEqual(std::string_view str1, std::string_view str2);

// checks that str1 starts with str2 ignoring letter case
bool caseInsensitiveStartsWith(std::string_view str, std::string_view prefix);

void replaceString(std::string& str, const std::string& sought, const std::string& replacement);
void trim_right(std::string& source, char t);
void trim_left(std::string& source, char t);
void toLowerCaseString(std::string& source);
std::string asLowerCaseString(std::string source);
std::string asUpperCaseString(std::string source);

Tools.cpp

void replaceString(std::string& str, const std::string& sought, const std::string& replacement)
{
    size_t pos = 0;
    size_t start = 0;
    size_t soughtLen = sought.length();
    size_t replaceLen = replacement.length();

    while ((pos = str.find(sought, start)) != std::string::npos) {
        str = str.substr(0, pos) + replacement + str.substr(pos + soughtLen);
        start = pos + replaceLen;
    }
}

void trim_right(std::string& source, char t)
{
    source.erase(source.find_last_not_of(t) + 1);
}

void trim_left(std::string& source, char t)
{
    source.erase(0, source.find_first_not_of(t));
}

bool caseInsensitiveEqual(std::string_view str1, std::string_view str2)
{
    return str1.size() == str2.size() && std::equal(str1.begin(), str1.end(), str2.begin(), [](char a, char b) {
        return tolower(a) == tolower(b);
    });
}

bool caseInsensitiveStartsWith(std::string_view str, std::string_view prefix)
{
    return str.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), str.begin(), [](char a, char b) {
        return tolower(a) == tolower(b);
    });
}

void toLowerCaseString(std::string& source)
{
    std::transform(source.begin(), source.end(), source.begin(), tolower);
}

std::string asLowerCaseString(std::string source)
{
    toLowerCaseString(source);
    return source;
}

std::string asUpperCaseString(std::string source)
{
    std::transform(source.begin(), source.end(), source.begin(), toupper);
    return source;
}