mirror of https://github.com/OpenTTD/OpenTTD
Fix: [Script] Don't kill GS misusing GSText (#12009)
parent
34b05465d5
commit
0858377e9e
|
@ -181,6 +181,15 @@ void ScriptText::_FillParamList(ParamList ¶ms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptText::ParamCheck::Encode(std::back_insert_iterator<std::string> &output)
|
||||||
|
{
|
||||||
|
if (this->used) return;
|
||||||
|
if (std::holds_alternative<std::string>(*this->param)) fmt::format_to(output, ":\"{}\"", std::get<std::string>(*this->param));
|
||||||
|
if (std::holds_alternative<SQInteger>(*this->param)) fmt::format_to(output, ":{:X}", std::get<SQInteger>(*this->param));
|
||||||
|
if (std::holds_alternative<ScriptTextRef>(*this->param)) fmt::format_to(output, ":{:X}", this->owner);
|
||||||
|
this->used = true;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output, int ¶m_count, StringIDList &seen_ids, ParamSpan args)
|
void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output, int ¶m_count, StringIDList &seen_ids, ParamSpan args)
|
||||||
{
|
{
|
||||||
const std::string &name = GetGameStringName(this->string);
|
const std::string &name = GetGameStringName(this->string);
|
||||||
|
@ -198,7 +207,7 @@ void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output,
|
||||||
if (idx >= args.size()) throw Script_FatalError(fmt::format("{}({}): Not enough parameters", name, param_count + 1));
|
if (idx >= args.size()) throw Script_FatalError(fmt::format("{}({}): Not enough parameters", name, param_count + 1));
|
||||||
ParamCheck &pc = args[idx++];
|
ParamCheck &pc = args[idx++];
|
||||||
if (pc.owner != this->string) ScriptLog::Warning(fmt::format("{}({}): Consumes {}({})", name, param_count + 1, GetGameStringName(pc.owner), pc.idx + 1));
|
if (pc.owner != this->string) ScriptLog::Warning(fmt::format("{}({}): Consumes {}({})", name, param_count + 1, GetGameStringName(pc.owner), pc.idx + 1));
|
||||||
return pc.param;
|
return &pc;
|
||||||
};
|
};
|
||||||
auto skip_args = [&](size_t nb) { idx += nb; };
|
auto skip_args = [&](size_t nb) { idx += nb; };
|
||||||
|
|
||||||
|
@ -209,19 +218,24 @@ void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StringParam::RAW_STRING: {
|
case StringParam::RAW_STRING: {
|
||||||
Param *p = get_next_arg();
|
ParamCheck &p = *get_next_arg();
|
||||||
if (!std::holds_alternative<std::string>(*p)) throw Script_FatalError(fmt::format("{}({}): {{{}}} expects a raw string", name, param_count + 1, cur_param.cmd));
|
if (!std::holds_alternative<std::string>(*p.param)) ScriptLog::Error(fmt::format("{}({}): {{{}}} expects a raw string", name, param_count + 1, cur_param.cmd));
|
||||||
fmt::format_to(output, ":\"{}\"", std::get<std::string>(*p));
|
p.Encode(output);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case StringParam::STRING: {
|
case StringParam::STRING: {
|
||||||
Param *p = get_next_arg();
|
ParamCheck &p = *get_next_arg();
|
||||||
if (!std::holds_alternative<ScriptTextRef>(*p)) throw Script_FatalError(fmt::format("{}({}): {{{}}} expects a GSText", name, param_count + 1, cur_param.cmd));
|
if (!std::holds_alternative<ScriptTextRef>(*p.param)){
|
||||||
|
ScriptLog::Error(fmt::format("{}({}): {{{}}} expects a GSText", name, param_count + 1, cur_param.cmd));
|
||||||
|
p.Encode(output);
|
||||||
|
break;
|
||||||
|
}
|
||||||
int count = 0;
|
int count = 0;
|
||||||
fmt::format_to(output, ":");
|
fmt::format_to(output, ":");
|
||||||
ScriptTextRef &ref = std::get<ScriptTextRef>(*p);
|
ScriptTextRef &ref = std::get<ScriptTextRef>(*p.param);
|
||||||
ref->_GetEncodedText(output, count, seen_ids, args.subspan(idx));
|
ref->_GetEncodedText(output, count, seen_ids, args.subspan(idx));
|
||||||
|
p.used = true;
|
||||||
if (++count != cur_param.consumes) {
|
if (++count != cur_param.consumes) {
|
||||||
ScriptLog::Error(fmt::format("{}({}): {{{}}} expects {} to be consumed, but {} consumes {}", name, param_count + 1, cur_param.cmd, cur_param.consumes - 1, GetGameStringName(ref->string), count - 1));
|
ScriptLog::Error(fmt::format("{}({}): {{{}}} expects {} to be consumed, but {} consumes {}", name, param_count + 1, cur_param.cmd, cur_param.consumes - 1, GetGameStringName(ref->string), count - 1));
|
||||||
/* Fill missing params if needed. */
|
/* Fill missing params if needed. */
|
||||||
|
@ -233,9 +247,9 @@ void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output,
|
||||||
|
|
||||||
default:
|
default:
|
||||||
for (int i = 0; i < cur_param.consumes; i++) {
|
for (int i = 0; i < cur_param.consumes; i++) {
|
||||||
Param *p = get_next_arg();
|
ParamCheck &p = *get_next_arg();
|
||||||
if (!std::holds_alternative<SQInteger>(*p)) throw Script_FatalError(fmt::format("{}({}): {{{}}} expects an integer", name, param_count + i + 1, cur_param.cmd));
|
if (!std::holds_alternative<SQInteger>(*p.param)) ScriptLog::Error(fmt::format("{}({}): {{{}}} expects an integer", name, param_count + i + 1, cur_param.cmd));
|
||||||
fmt::format_to(output, ":{:X}", std::get<SQInteger>(*p));
|
p.Encode(output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,8 +136,11 @@ private:
|
||||||
StringID owner;
|
StringID owner;
|
||||||
int idx;
|
int idx;
|
||||||
Param *param;
|
Param *param;
|
||||||
|
bool used;
|
||||||
|
|
||||||
ParamCheck(StringID owner, int idx, Param *param) : owner(owner), idx(idx), param(param) {}
|
ParamCheck(StringID owner, int idx, Param *param) : owner(owner), idx(idx), param(param), used(false) {}
|
||||||
|
|
||||||
|
void Encode(std::back_insert_iterator<std::string> &output);
|
||||||
};
|
};
|
||||||
|
|
||||||
using ParamList = std::vector<ParamCheck>;
|
using ParamList = std::vector<ParamCheck>;
|
||||||
|
|
Loading…
Reference in New Issue