summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/settings.cpp189
-rw-r--r--src/settings_internal.h5
2 files changed, 96 insertions, 98 deletions
diff --git a/src/settings.cpp b/src/settings.cpp
index f5d4a9660..8bdfced96 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -446,33 +446,22 @@ static const void *StringToVal(const SettingDesc *desc, const char *orig_str)
}
/**
- * Set the value of a setting and if needed clamp the value to
- * the preset minimum and maximum.
- * @param ptr the variable itself
- * @param sd pointer to the 'information'-database of the variable
- * @param val signed long version of the new value
- * @pre SettingDesc is of type SDT_BOOLX, SDT_NUMX,
- * SDT_ONEOFMANY or SDT_MANYOFMANY. Other types are not supported as of now
- */
-static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
-{
- const SettingDesc *sdb = sd;
-
- if (sdb->cmd != SDT_BOOLX &&
- sdb->cmd != SDT_NUMX &&
- sdb->cmd != SDT_ONEOFMANY &&
- sdb->cmd != SDT_MANYOFMANY) {
- return;
- }
+ * Set the value of a setting and if needed clamp the value to the preset minimum and maximum.
+ * @param object The object the setting is to be saved in.
+ * @param val Signed version of the new value.
+ */
+void IntSettingDesc::Write_ValidateSetting(const void *object, int32 val) const
+{
+ void *ptr = GetVariableAddress(object, &this->save);
/* We cannot know the maximum value of a bitset variable, so just have faith */
- if (sdb->cmd != SDT_MANYOFMANY) {
+ if (this->cmd != SDT_MANYOFMANY) {
/* We need to take special care of the uint32 type as we receive from the function
* a signed integer. While here also bail out on 64-bit settings as those are not
* supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed
* 32-bit variable
* TODO: Support 64-bit settings/variables */
- switch (GetVarMemType(sd->save.conv)) {
+ switch (GetVarMemType(this->save.conv)) {
case SLE_VAR_NULL: return;
case SLE_VAR_BL:
case SLE_VAR_I8:
@@ -481,13 +470,13 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
case SLE_VAR_U16:
case SLE_VAR_I32: {
/* Override the minimum value. No value below sdb->min, except special value 0 */
- if (!(sdb->flags & SGF_0ISDISABLED) || val != 0) {
- if (!(sdb->flags & SGF_MULTISTRING)) {
+ if (!(this->flags & SGF_0ISDISABLED) || val != 0) {
+ if (!(this->flags & SGF_MULTISTRING)) {
/* Clamp value-type setting to its valid range */
- val = Clamp(val, sdb->min, sdb->max);
- } else if (val < sdb->min || val > (int32)sdb->max) {
+ val = Clamp(val, this->min, this->max);
+ } else if (val < this->min || val > (int32)this->max) {
/* Reset invalid discrete setting (where different values change gameplay) to its default value */
- val = (int32)(size_t)sdb->def;
+ val = (int32)(size_t)this->def;
}
}
break;
@@ -495,13 +484,13 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
case SLE_VAR_U32: {
/* Override the minimum value. No value below sdb->min, except special value 0 */
uint32 uval = (uint32)val;
- if (!(sdb->flags & SGF_0ISDISABLED) || uval != 0) {
- if (!(sdb->flags & SGF_MULTISTRING)) {
+ if (!(this->flags & SGF_0ISDISABLED) || uval != 0) {
+ if (!(this->flags & SGF_MULTISTRING)) {
/* Clamp value-type setting to its valid range */
- uval = ClampU(uval, sdb->min, sdb->max);
- } else if (uval < (uint)sdb->min || uval > sdb->max) {
+ uval = ClampU(uval, this->min, this->max);
+ } else if (uval < (uint)this->min || uval > this->max) {
/* Reset invalid discrete setting to its default value */
- uval = (uint32)(size_t)sdb->def;
+ uval = (uint32)(size_t)this->def;
}
}
WriteValue(ptr, SLE_VAR_U32, (int64)uval);
@@ -513,7 +502,7 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
}
}
- WriteValue(ptr, sd->save.conv, (int64)val);
+ WriteValue(ptr, this->save.conv, (int64)val);
}
/**
@@ -610,7 +599,7 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co
case SDT_NUMX:
case SDT_ONEOFMANY:
case SDT_MANYOFMANY:
- Write_ValidateSetting(ptr, sd.get(), (int32)(size_t)p);
+ sd->AsIntSetting()->Write_ValidateSetting(object, (int32)(size_t)p);
break;
case SDT_STDSTRING:
@@ -846,6 +835,24 @@ SettingType SettingDesc::GetType() const
return (this->save.conv & SLF_NOT_IN_SAVE) ? ST_CLIENT : ST_GAME;
}
+/**
+ * Check whether this setting is an integer type setting.
+ * @return True when the underlying type is an integer.
+ */
+bool SettingDesc::IsIntSetting() const {
+ return this->cmd == SDT_BOOLX || this->cmd == SDT_NUMX || this->cmd == SDT_ONEOFMANY || this->cmd == SDT_MANYOFMANY;
+}
+
+/**
+ * Get the setting description of this setting as an integer setting.
+ * @return The integer setting description.
+ */
+const IntSettingDesc *SettingDesc::AsIntSetting() const
+{
+ assert(this->IsIntSetting());
+ return static_cast<const IntSettingDesc *>(this);
+}
+
/* Begin - Callback Functions for the various settings. */
/** Reposition the main toolbar as the setting changed. */
@@ -1451,8 +1458,8 @@ static void HandleOldDiffCustom(bool savegame)
const SettingDesc *sd = GetSettingDescription(i);
/* Skip deprecated options */
if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
- void *var = GetVariableAddress(savegame ? &_settings_game : &_settings_newgame, &sd->save);
- Write_ValidateSetting(var, sd, (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i]));
+ int32 value = (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i]);
+ sd->AsIntSetting()->Write_ValidateSetting(savegame ? &_settings_game : &_settings_newgame, value);
}
}
@@ -1880,6 +1887,40 @@ void DeleteGRFPresetFromConfig(const char *config_name)
}
/**
+ * Handle changing a value. This performs validation of the input value and
+ * calls the appropriate callbacks, and saves it when the value is changed.
+ * @param object The object the setting is in.
+ * @param newval The new value for the setting.
+ */
+void IntSettingDesc::ChangeValue(const void *object, int32 newval) const
+{
+ void *var = GetVariableAddress(object, &this->save);
+
+ int32 oldval = (int32)ReadValue(var, this->save.conv);
+
+ this->Write_ValidateSetting(object, newval);
+ newval = (int32)ReadValue(var, this->save.conv);
+
+ if (oldval == newval) return;
+
+ if (this->proc != nullptr && !this->proc(newval)) {
+ /* The change was not allowed, so revert. */
+ WriteValue(var, this->save.conv, (int64)oldval);
+ return;
+ }
+
+ if (this->flags & SGF_NO_NETWORK) {
+ GamelogStartAction(GLAT_SETTING);
+ GamelogSetting(this->name, oldval, newval);
+ GamelogStopAction();
+ }
+
+ SetWindowClassesDirty(WC_GAME_OPTIONS);
+
+ if (_save_config) SaveToConfig();
+}
+
+/**
* Network-safe changing of settings (server-only).
* @param tile unused
* @param flags operation to perform
@@ -1896,34 +1937,12 @@ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
if (sd == nullptr) return CMD_ERROR;
if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) return CMD_ERROR;
+ if (!sd->IsIntSetting()) return CMD_ERROR;
if (!sd->IsEditable(true)) return CMD_ERROR;
if (flags & DC_EXEC) {
- void *var = GetVariableAddress(&GetGameSettings(), &sd->save);
-
- int32 oldval = (int32)ReadValue(var, sd->save.conv);
- int32 newval = (int32)p2;
-
- Write_ValidateSetting(var, sd, newval);
- newval = (int32)ReadValue(var, sd->save.conv);
-
- if (oldval == newval) return CommandCost();
-
- if (sd->proc != nullptr && !sd->proc(newval)) {
- WriteValue(var, sd->save.conv, (int64)oldval);
- return CommandCost();
- }
-
- if (sd->flags & SGF_NO_NETWORK) {
- GamelogStartAction(GLAT_SETTING);
- GamelogSetting(sd->name, oldval, newval);
- GamelogStopAction();
- }
-
- SetWindowClassesDirty(WC_GAME_OPTIONS);
-
- if (_save_config) SaveToConfig();
+ sd->AsIntSetting()->ChangeValue(&GetGameSettings(), p2);
}
return CommandCost();
@@ -1943,24 +1962,10 @@ CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32
{
const SettingDesc *sd = GetCompanySettingDescription(p1);
if (sd == nullptr) return CMD_ERROR;
+ if (!sd->IsIntSetting()) return CMD_ERROR;
if (flags & DC_EXEC) {
- void *var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save);
-
- int32 oldval = (int32)ReadValue(var, sd->save.conv);
- int32 newval = (int32)p2;
-
- Write_ValidateSetting(var, sd, newval);
- newval = (int32)ReadValue(var, sd->save.conv);
-
- if (oldval == newval) return CommandCost();
-
- if (sd->proc != nullptr && !sd->proc(newval)) {
- WriteValue(var, sd->save.conv, (int64)oldval);
- return CommandCost();
- }
-
- SetWindowClassesDirty(WC_GAME_OPTIONS);
+ sd->AsIntSetting()->ChangeValue(&Company::Get(_current_company)->settings, p2);
}
return CommandCost();
@@ -2013,14 +2018,13 @@ static uint GetCompanySettingIndex(const SettingDesc *sd)
*/
bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame)
{
- if ((sd->flags & SGF_PER_COMPANY) != 0) {
+ const IntSettingDesc *setting = sd->AsIntSetting();
+ if ((setting->flags & SGF_PER_COMPANY) != 0) {
if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
- return DoCommandP(0, GetCompanySettingIndex(sd), value, CMD_CHANGE_COMPANY_SETTING);
+ return DoCommandP(0, GetCompanySettingIndex(setting), value, CMD_CHANGE_COMPANY_SETTING);
}
- void *var = GetVariableAddress(&_settings_client.company, &sd->save);
- Write_ValidateSetting(var, sd, value);
- if (sd->proc != nullptr) sd->proc((int32)ReadValue(var, sd->save.conv));
+ setting->ChangeValue(&_settings_client.company, value);
return true;
}
@@ -2028,33 +2032,22 @@ bool SetSettingValue(const SettingDesc *sd, int32 value, bool force_newgame)
* (if any) to change. Also *hack*hack* we update the _newgame version
* of settings because changing a company-based setting in a game also
* changes its defaults. At least that is the convention we have chosen */
- if (sd->save.conv & SLF_NO_NETWORK_SYNC) {
- void *var = GetVariableAddress(&GetGameSettings(), &sd->save);
- Write_ValidateSetting(var, sd, value);
-
+ if (setting->save.conv & SLF_NO_NETWORK_SYNC) {
if (_game_mode != GM_MENU) {
- void *var2 = GetVariableAddress(&_settings_newgame, &sd->save);
- Write_ValidateSetting(var2, sd, value);
+ setting->ChangeValue(&_settings_newgame, value);
}
- if (sd->proc != nullptr) sd->proc((int32)ReadValue(var, sd->save.conv));
-
- SetWindowClassesDirty(WC_GAME_OPTIONS);
-
- if (_save_config) SaveToConfig();
+ setting->ChangeValue(&GetGameSettings(), value);
return true;
}
if (force_newgame) {
- void *var2 = GetVariableAddress(&_settings_newgame, &sd->save);
- Write_ValidateSetting(var2, sd, value);
-
- if (_save_config) SaveToConfig();
+ setting->ChangeValue(&_settings_newgame, value);
return true;
}
/* send non-company-based settings over the network */
if (!_networking || (_networking && _network_server)) {
- return DoCommandP(0, GetSettingIndex(sd), value, CMD_CHANGE_SETTING);
+ return DoCommandP(0, GetSettingIndex(setting), value, CMD_CHANGE_SETTING);
}
return false;
}
@@ -2066,8 +2059,8 @@ void SetDefaultCompanySettings(CompanyID cid)
{
Company *c = Company::Get(cid);
for (auto &sd : _company_settings) {
- void *var = GetVariableAddress(&c->settings, &sd->save);
- Write_ValidateSetting(var, sd.get(), (int32)(size_t)sd->def);
+ const IntSettingDesc *int_setting = sd->AsIntSetting();
+ int_setting->Write_ValidateSetting(&c->settings, (int32)(size_t)int_setting->def);
}
}
@@ -2256,7 +2249,7 @@ static void LoadSettings(const SettingTable &settings, void *object)
void *ptr = GetVariableAddress(object, sld);
if (!SlObjectMember(ptr, sld)) continue;
- if (IsNumericType(sld->conv)) Write_ValidateSetting(ptr, osd.get(), ReadValue(ptr, sld->conv));
+ if (osd->IsIntSetting()) osd->AsIntSetting()->Write_ValidateSetting(object, ReadValue(ptr, sld->conv));
}
}
diff --git a/src/settings_internal.h b/src/settings_internal.h
index ee8b59be1..7b37ac267 100644
--- a/src/settings_internal.h
+++ b/src/settings_internal.h
@@ -110,6 +110,8 @@ struct SettingDesc {
bool IsEditable(bool do_command = false) const;
SettingType GetType() const;
+ bool IsIntSetting() const;
+ const struct IntSettingDesc *AsIntSetting() const;
/**
* Format the value of the setting associated with this object.
@@ -129,6 +131,9 @@ struct IntSettingDesc : SettingDesc {
proc, many_cnvt, cat, startup) {}
virtual ~IntSettingDesc() {}
+ void ChangeValue(const void *object, int32 newvalue) const;
+ void Write_ValidateSetting(const void *object, int32 value) const;
+
void FormatValue(char *buf, const char *last, const void *object) const override;
};