1
0
Fork 0

Change: Use enum/bitset to track which script configuration items are defined. (#14150)

Removes magic numbers, and simplifies compatibility. It is no longer necessary to provide values which won't be used.
pull/14156/head
Peter Nelson 2025-04-28 23:07:57 +01:00 committed by GitHub
parent b20b56d5fc
commit 13fcc0900e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 28 additions and 20 deletions

View File

@ -83,10 +83,21 @@ bool ScriptInfo::GetSettings()
return this->engine->CallMethod(this->SQ_instance, "GetSettings", nullptr, MAX_GET_SETTING_OPS);
}
enum class ScriptConfigItemKey : uint8_t {
Name,
Description,
MinValue,
MaxValue,
MediumValue,
DefaultValue,
Flags,
};
using ScriptConfigItemKeys = EnumBitSet<ScriptConfigItemKey, uint8_t>;
SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm)
{
ScriptConfigItem config;
uint items = 0;
ScriptConfigItemKeys present{};
int medium_value = INT32_MIN;
@ -106,40 +117,38 @@ SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm)
auto replace_with_underscore = [](auto c) { return c == '=' || c == ','; };
config.name = StrMakeValid(sqvalue);
std::replace_if(config.name.begin(), config.name.end(), replace_with_underscore, '_');
items |= 0x001;
present.Set(ScriptConfigItemKey::Name);
} else if (key == "description") {
const SQChar *sqdescription;
if (SQ_FAILED(sq_getstring(vm, -1, &sqdescription))) return SQ_ERROR;
config.description = StrMakeValid(sqdescription);
items |= 0x002;
present.Set(ScriptConfigItemKey::Description);
} else if (key == "min_value") {
SQInteger res;
if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
config.min_value = ClampTo<int32_t>(res);
items |= 0x004;
present.Set(ScriptConfigItemKey::MinValue);
} else if (key == "max_value") {
SQInteger res;
if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
config.max_value = ClampTo<int32_t>(res);
items |= 0x008;
present.Set(ScriptConfigItemKey::MaxValue);
} else if (key == "easy_value") {
/* No longer parsed. */
items |= 0x010;
} else if (key == "medium_value") {
SQInteger res;
if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
medium_value = ClampTo<int32_t>(res);
items |= 0x020;
present.Set(ScriptConfigItemKey::MediumValue);
} else if (key == "hard_value") {
/* No longer parsed. */
items |= 0x040;
} else if (key == "custom_value") {
/* No longer parsed. */
} else if (key == "default_value") {
SQInteger res;
if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
config.default_value = ClampTo<int32_t>(res);
items |= 0x080;
present.Set(ScriptConfigItemKey::DefaultValue);
} else if (key == "random_deviation") {
/* No longer parsed. */
} else if (key == "step_size") {
@ -149,8 +158,8 @@ SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm)
} else if (key == "flags") {
SQInteger res;
if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
config.flags = (ScriptConfigFlags)res;
items |= 0x100;
config.flags = static_cast<ScriptConfigFlags>(res);
present.Set(ScriptConfigItemKey::Flags);
} else {
this->engine->ThrowError(fmt::format("unknown setting property '{}'", key));
return SQ_ERROR;
@ -163,23 +172,22 @@ SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm)
/* Check if default_value is set. Although required, this was changed with
* 14.0, and as such, older AIs don't use it yet. So we convert the older
* values into a default_value. */
if ((items & 0x080) == 0) {
if (!present.Test(ScriptConfigItemKey::DefaultValue)) {
/* Easy/medium/hard should all three be defined. */
if ((items & 0x010) == 0 || (items & 0x020) == 0 || (items & 0x040) == 0) {
if (!present.Test(ScriptConfigItemKey::MediumValue)) {
this->engine->ThrowError("please define all properties of a setting (min/max not allowed for booleans)");
return SQ_ERROR;
}
config.default_value = medium_value;
items |= 0x080;
} else {
/* For compatibility, also act like the default sets the easy/medium/hard. */
items |= 0x010 | 0x020 | 0x040;
present.Set(ScriptConfigItemKey::DefaultValue);
}
/* Make sure all properties are defined */
uint mask = config.flags.Test(ScriptConfigFlag::Boolean) ? 0x1F3 : 0x1FF;
if (items != mask) {
/* Make sure all required properties are defined */
ScriptConfigItemKeys required = {ScriptConfigItemKey::Name, ScriptConfigItemKey::Description, ScriptConfigItemKey::DefaultValue, ScriptConfigItemKey::Flags};
if (!config.flags.Test(ScriptConfigFlag::Boolean)) required.Set({ScriptConfigItemKey::MinValue, ScriptConfigItemKey::MaxValue});
if (!present.All(required)) {
this->engine->ThrowError("please define all properties of a setting (min/max not allowed for booleans)");
return SQ_ERROR;
}