1
0
Fork 0

Change: Remove the limit of 20 parameters to a Script Text string. (#14193)

pull/14199/head
Peter Nelson 2025-05-03 18:33:29 +01:00 committed by GitHub
parent 518a34c286
commit bd1a3fe0b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 59 additions and 25 deletions

View File

@ -9,6 +9,9 @@
GSBridge.GetBridgeID <- GSBridge.GetBridgeType;
/* Emulate old GSText parameter padding behaviour */
GSText.SCRIPT_TEXT_MAX_PARAMETERS <- 20;
class GSCompat14 {
function Text(text)
{

View File

@ -50,9 +50,9 @@ void GameInstance::RegisterAPI()
/* Register all classes */
SQGS_RegisterAll(*this->engine);
RegisterGameTranslation(*this->engine);
if (!this->LoadCompatibilityScripts(GAME_DIR, GameInfo::ApiVersions)) this->Died();
RegisterGameTranslation(*this->engine);
}
int GameInstance::GetSetting(const std::string &name)

View File

@ -370,6 +370,8 @@ void RegisterGameTranslation(Squirrel &engine)
sq_pop(vm, 2);
ScriptText::SetPadParameterCount(vm);
ReconsiderGameScriptLanguage();
}

View File

@ -57,7 +57,7 @@ ScriptText::ScriptText(HSQUIRRELVM vm)
SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm)
{
if (parameter >= SCRIPT_TEXT_MAX_PARAMETERS) return SQ_ERROR;
if (static_cast<size_t>(parameter) >= std::size(this->param)) this->param.resize(parameter + 1);
switch (sq_gettype(vm, -1)) {
case OT_STRING: {
@ -99,10 +99,13 @@ SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm)
break;
}
case OT_NULL:
this->param[parameter] = {};
break;
default: return SQ_ERROR;
}
if (this->paramc <= parameter) this->paramc = parameter + 1;
return 0;
}
@ -113,7 +116,6 @@ SQInteger ScriptText::SetParam(HSQUIRRELVM vm)
SQInteger k;
sq_getinteger(vm, 2, &k);
if (k > SCRIPT_TEXT_MAX_PARAMETERS) return SQ_ERROR;
if (k < 1) return SQ_ERROR;
k--;
@ -123,7 +125,7 @@ SQInteger ScriptText::SetParam(HSQUIRRELVM vm)
SQInteger ScriptText::AddParam(HSQUIRRELVM vm)
{
SQInteger res;
res = this->_SetParam(this->paramc, vm);
res = this->_SetParam(static_cast<int>(std::size(this->param)), vm);
if (res != 0) return res;
/* Push our own instance back on top of the stack */
@ -140,7 +142,7 @@ SQInteger ScriptText::_set(HSQUIRRELVM vm)
sq_getstring(vm, 2, view);
std::string str = StrMakeValid(view);
if (!str.starts_with("param_") || str.size() > 8) return SQ_ERROR;
if (!str.starts_with("param_")) return SQ_ERROR;
auto key = ParseInteger<int32_t>(str.substr(6));
if (!key.has_value()) return SQ_ERROR;
@ -153,13 +155,35 @@ SQInteger ScriptText::_set(HSQUIRRELVM vm)
return SQ_ERROR;
}
if (k > SCRIPT_TEXT_MAX_PARAMETERS) return SQ_ERROR;
if (k < 1) return SQ_ERROR;
k--;
return this->_SetParam(k, vm);
}
/**
* Set the number of padding parameters to use, for compatibility with old scripts.
* This is called during RegisterGameTranslation.
*/
void ScriptText::SetPadParameterCount(HSQUIRRELVM vm)
{
ScriptText::pad_parameter_count = 0;
SQInteger top = sq_gettop(vm);
sq_pushroottable(vm);
sq_pushstring(vm, "GSText", -1);
if (!SQ_FAILED(sq_get(vm, -2))) {
sq_pushstring(vm, "SCRIPT_TEXT_MAX_PARAMETERS", -1);
if (!SQ_FAILED(sq_get(vm, -2))) {
SQInteger value;
if (!SQ_FAILED(sq_getinteger(vm, -1, &value))) {
ScriptText::pad_parameter_count = value;
}
}
}
sq_pop(vm, top);
}
EncodedString ScriptText::GetEncodedText()
{
ScriptTextList seen_texts;
@ -169,7 +193,6 @@ EncodedString ScriptText::GetEncodedText()
StringBuilder builder(result);
this->_FillParamList(params, seen_texts);
this->_GetEncodedText(builder, param_count, params, true);
if (param_count > SCRIPT_TEXT_MAX_PARAMETERS) throw Script_FatalError(fmt::format("{}: Too many parameters", GetGameStringName(this->string)));
return ::EncodedString{std::move(result)};
}
@ -178,21 +201,21 @@ void ScriptText::_FillParamList(ParamList &params, ScriptTextList &seen_texts)
if (std::ranges::find(seen_texts, this) != seen_texts.end()) throw Script_FatalError(fmt::format("{}: Circular reference detected", GetGameStringName(this->string)));
seen_texts.push_back(this);
for (int i = 0; i < this->paramc; i++) {
Param *p = &this->param[i];
params.emplace_back(this->string, i, p);
if (!std::holds_alternative<ScriptTextRef>(*p)) continue;
std::get<ScriptTextRef>(*p)->_FillParamList(params, seen_texts);
for (int idx = 0; Param &p : this->param) {
params.emplace_back(this->string, idx, &p);
++idx;
if (!std::holds_alternative<ScriptTextRef>(p)) continue;
std::get<ScriptTextRef>(p)->_FillParamList(params, seen_texts);
}
seen_texts.pop_back();
/* Fill with dummy parameters to match FormatString() behaviour. */
if (seen_texts.empty()) {
static Param dummy = 0;
int nb_extra = SCRIPT_TEXT_MAX_PARAMETERS - (int)params.size();
for (int i = 0; i < nb_extra; i++)
params.emplace_back(StringIndexInTab(-1), i, &dummy);
/* Fill with dummy parameters to match old FormatString() compatibility behaviour. */
if (seen_texts.empty() && ScriptText::pad_parameter_count > 0) {
static Param dummy = {};
for (int idx = static_cast<int>(std::size(this->param)); idx < ScriptText::pad_parameter_count; ++idx) {
params.emplace_back(StringIndexInTab(-1), idx, &dummy);
}
}
}
@ -204,6 +227,8 @@ void ScriptText::ParamCheck::Encode(StringBuilder &builder, std::string_view cmd
struct visitor {
StringBuilder &builder;
void operator()(const std::monostate &) { }
void operator()(std::string value)
{
this->builder.PutUtf8(SCC_ENCODED_STRING);

View File

@ -75,8 +75,6 @@ private:
*/
class ScriptText : public Text {
public:
static const int SCRIPT_TEXT_MAX_PARAMETERS = 20; ///< The maximum amount of parameters you can give to one object.
#ifndef DOXYGEN_API
/**
* The constructor wrapper from Squirrel.
@ -128,10 +126,15 @@ public:
*/
EncodedString GetEncodedText() override;
/**
* @api -all
*/
static void SetPadParameterCount(HSQUIRRELVM vm);
private:
using ScriptTextRef = ScriptObjectRef<ScriptText>;
using ScriptTextList = std::vector<ScriptText *>;
using Param = std::variant<SQInteger, std::string, ScriptTextRef>;
using Param = std::variant<std::monostate, SQInteger, std::string, ScriptTextRef>;
struct ParamCheck {
StringIndexInTab owner;
@ -149,8 +152,9 @@ private:
using ParamSpan = std::span<ParamCheck>;
StringIndexInTab string;
std::array<Param, SCRIPT_TEXT_MAX_PARAMETERS> param = {};
int paramc = 0;
std::vector<Param> param{};
static inline int pad_parameter_count = 0; ///< Pad parameters for relaxed string validation.
/**
* Internal function to recursively fill a list of parameters.