1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-07-26 13:57:56 +01:00

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

Removes magic numbers, and simplifies compatibility. It is no longer necessary to provide values which won't be used.
This commit is contained in:
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

View File

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