DaemonEngine / Daemon

The Dæmon game engine. With some bits of ioq3 and XreaL.
https://unvanquished.net
BSD 3-Clause "New" or "Revised" License
298 stars 61 forks source link

Normalize Cvar Values #1214

Open DolceTriade opened 3 months ago

DolceTriade commented 3 months ago

If I'm I'm setting a boolean cvar and do:

]/set g_bot_level4 0
CVAR VALUE CHANGED: g_bot_level4 = 0 (1) 
]/g_bot_level4 
"g_bot_level4" - "0" - bool - whether bots use Tyrant - default: "on" 
]/set g_bot_level4 off
CVAR VALUE CHANGED: g_bot_level4 = off (1) 
]/g_bot_level4 
"g_bot_level4" - "off" - bool - whether bots use Tyrant - default: "on"

0 and off are equivalent values yet a string compare won't catch them as such when doing Cvar::GetValue.

I'm sure similar problems exist for other cvar types too (maybe floating point?).

Currently, all of our normalization logic is only when you call the new C++ API in the engine.

We should normalize all cvars on set. I propose we do this by modifying the semantics of OnValueChanged to also return a normalized value and store that instead of the direct value the user passed in.

slipher commented 2 months ago

We should probably solve the float round trip problem first. You need a complicated algorithm to normalize a float without either losing precision or producing very ugly strings

    std::string SerializeCvarValue(float value) {
        // You'd need %.9g to guarantee a round trip but with 8 or 9 digits of precision you get
        // stuff like 0.65f -> "0.649999976"
        return Str::Format("%.7g", value);
    }

For the case of reading cvar values in Lua, I would suggest adding more APIs like Cvar.getBool, Cvar.getNumber in addition to the current one which gets a string. We don't have to care about the type, if any, the cvar is registered as; just parse it as the requested type. Similar to RocketConditionalElement

DolceTriade commented 2 months ago

Yes that's my workaround for now