Codechange: make Write_ValidateSetting a function of IntSettingDesc

pull/332/head
rubidium42 3 years ago committed by rubidium42
parent 024e584904
commit be28c95b30

@ -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);
}
}
@ -1879,6 +1886,40 @@ void DeleteGRFPresetFromConfig(const char *config_name)
delete ini;
}
/**
* 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
@ -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));
}
}

@ -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;
};

Loading…
Cancel
Save