diff options
-rw-r--r-- | src/autojump.c | 2 | ||||
-rw-r--r-- | src/build/gluegen.c | 3 | ||||
-rw-r--r-- | src/con_.c | 55 | ||||
-rw-r--r-- | src/con_.h | 52 | ||||
-rw-r--r-- | src/fixes.c | 29 | ||||
-rw-r--r-- | src/fov.c | 17 | ||||
-rw-r--r-- | src/inputhud.c | 14 |
7 files changed, 108 insertions, 64 deletions
diff --git a/src/autojump.c b/src/autojump.c index 2656796..eb0e34f 100644 --- a/src/autojump.c +++ b/src/autojump.c @@ -78,7 +78,7 @@ static bool unprot(struct CGameMovement *gm) { // reimplementing cheats check for dumb and bad reasons, see below static struct con_var *sv_cheats; static void cheatcb(struct con_var *this) { - if (this->ival) if_cold (!con_getvari(sv_cheats)) { + if (con_getvari(this)) if_cold (!con_getvari(sv_cheats)) { con_warn("Can't use cheat cvar sst_autojump, unless server has " "sv_cheats set to 1.\n"); con_setvari(this, 0); diff --git a/src/build/gluegen.c b/src/build/gluegen.c index bc973fb..e2bc2f3 100644 --- a/src/build/gluegen.c +++ b/src/build/gluegen.c @@ -869,7 +869,8 @@ _( "}") _( "") _( "static inline void freevars() {") for (int i = 1; i < ncvars; ++i) { -F( " extfree(%.*s->strval);", cvar_names[i].len, cvar_names[i].s) +F( " extfree(con_getvarcommon(%.*s)->strval);", + cvar_names[i].len, cvar_names[i].s) } _( "}") for (int i = 1; i < nevents; ++i) { @@ -65,8 +65,8 @@ struct ICvar *_con_iface; ConsoleColorPrintf_func _con_colourmsgf; static inline void initval(struct con_var *v) { - v->strval = extmalloc(v->strlen); // note: strlen is preset in _DEF_CVAR() - memcpy(v->strval, v->defaultval, v->strlen); + v->v2.strval = extmalloc(v->v2.strlen); // note: _DEF_CVAR() sets strlen + memcpy(v->v2.strval, v->v2.defaultval, v->v2.strlen); } static void VCALLCONV dtor(void *_) {} // we don't use constructors/destructors @@ -122,8 +122,14 @@ static void VCALLCONV Create_base(struct con_cmdbase *this, const char *name, static void VCALLCONV Init(struct con_cmdbase *this) {} // "" static bool VCALLCONV ClampValue(struct con_var *this, float *f) { - if (this->hasmin && this->minval > *f) { *f = this->minval; return true; } - if (this->hasmax && this->maxval < *f) { *f = this->maxval; return true; } + if (this->v2.hasmin && this->v2.minval > *f) { + *f = this->v2.minval; + return true; + } + if (this->v2.hasmax && this->v2.maxval < *f) { + *f = this->v2.maxval; + return true; + } return false; } @@ -141,14 +147,14 @@ void VCALLCONV Dispatch(struct con_cmd *this, const struct con_cmdargs *args) { static void VCALLCONV ChangeStringValue(struct con_var *this, const char *s, float oldf) { - char *old = alloca(this->strlen); - memcpy(old, this->strval, this->strlen); + char *old = alloca(this->v2.strlen); + memcpy(old, this->v2.strval, this->v2.strlen); int len = strlen(s) + 1; - if (len > this->strlen) { - this->strval = extrealloc(this->strval, len); - this->strlen = len; + if (len > this->v2.strlen) { + this->v2.strval = extrealloc(this->v2.strval, len); + this->v2.strlen = len; } - memcpy(this->strval, s, len); + memcpy(this->v2.strval, s, len); // callbacks don't matter as far as ABI compat goes (and thank goodness // because e.g. portal2 randomly adds a *list* of callbacks!?). however we // do need callbacks for at least one feature, so do our own minimal thing @@ -163,41 +169,39 @@ static void VCALLCONV ChangeStringValue(struct con_var *this, const char *s, // *should* be calling these internal things anyway. static void VCALLCONV InternalSetValue(struct con_var *this, const char *v) { - float oldf = this->fval; + float oldf = this->v2.fval; float newf = atof(v); char tmp[32]; - // NOTE: calling our own ClampValue and ChangeString, not bothering with - // vtable (it's internal anyway, so we're never calling into engine code) if (ClampValue(this, &newf)) { snprintf(tmp, sizeof(tmp), "%f", newf); v = tmp; } - this->fval = newf; - this->ival = (int)newf; + this->v2.fval = newf; + this->v2.ival = (int)newf; if (!(this->base.flags & CON_NOPRINT)) ChangeStringValue(this, v, oldf); } static void VCALLCONV InternalSetFloatValue(struct con_var *this, float v) { - if (v == this->fval) return; + if (v == this->v2.fval) return; ClampValue(this, &v); - float old = this->fval; - this->fval = v; this->ival = (int)this->fval; + float old = this->v2.fval; + this->v2.fval = v; this->v2.ival = (int)this->v2.fval; if (!(this->base.flags & CON_NOPRINT)) { char tmp[32]; - snprintf(tmp, sizeof(tmp), "%f", this->fval); + snprintf(tmp, sizeof(tmp), "%f", this->v2.fval); ChangeStringValue(this, tmp, old); } } static void VCALLCONV InternalSetIntValue(struct con_var *this, int v) { - if (v == this->ival) return; + if (v == this->v2.ival) return; float f = (float)v; if (ClampValue(this, &f)) v = (int)f; - float old = this->fval; - this->fval = f; this->ival = v; + float old = this->v2.fval; + this->v2.fval = f; this->v2.ival = v; if (!(this->base.flags & CON_NOPRINT)) { char tmp[32]; - snprintf(tmp, sizeof(tmp), "%f", this->fval); + snprintf(tmp, sizeof(tmp), "%f", this->v2.fval); ChangeStringValue(this, tmp, old); } } @@ -465,7 +469,10 @@ struct con_cmd *con_findcmd(const char *name) { // NOTE: getters here still go through the parent pointer although we stopped // doing that internally, just in case we run into parented cvars in the actual // engine. a little less efficient, but safest and simplest for now. -#define GETTER(T, N, M) T N(const struct con_var *v) { return v->parent->M; } +#define GETTER(T, N, M) \ + T N(const struct con_var *v) { \ + return v->v2.parent->v2.M; \ + } GETTER(const char *, con_getvarstr, strval) GETTER(float, con_getvarf, fval) GETTER(int, con_getvari, ival) @@ -117,9 +117,7 @@ struct con_cmd { // ConCommand in engine bool has_complcb : 1, use_newcb : 1, use_newcmdiface : 1; }; -struct con_var { // ConVar in engine - struct con_cmdbase base; - void **vtable_iconvar; // IConVar in engine (pure virtual) +struct con_var_common { struct con_var *parent; const char *defaultval; char *strval; @@ -131,8 +129,19 @@ struct con_var { // ConVar in engine float minval; bool hasmax; // just sticking to sdk position float maxval; +}; + +struct con_var { // ConVar in engine + struct con_cmdbase base; + union { + struct con_var_common v1; + struct { + void **vtable_iconvar; // IConVar in engine (pure virtual) + struct con_var_common v2; + }; + }; /* - * Our quickly-chucked-in optional callback - doesn't match the engine!! + * Our quickly-chucked-in optional callback - doesn't match the engine ABI! * Also has to be manually set in code, although that's probably fine anyway * as it's common to only want a cvar to do something if the feature * succesfully init-ed. @@ -143,13 +152,27 @@ struct con_var { // ConVar in engine /* The change callback used in most branches of Source. Takes an IConVar :) */ typedef void (*con_varcb)(void *v, const char *, float); + +/* Returns a registered variable with the given name, or null if not found. */ +struct con_var *con_findvar(const char *name); + +/* Returns a registered command with the given name, or null if not found. */ +struct con_cmd *con_findcmd(const char *name); + +/* + * Returns a pointer to the common (i.e. middle) part of a ConVar struct, the + * offset of which varies by engine version. This sub-struct contains + * essentially all the actual cvar-specific data. + */ +static inline struct con_var_common *con_getvarcommon(struct con_var *v) { + return &v->v2; +} + /* * These functions get and set the values of console variables in a * neatly-abstracted manner. Note: cvar values are always strings internally - * numerical values are just interpretations of the underlying value. */ -struct con_var *con_findvar(const char *name); -struct con_cmd *con_findcmd(const char *name); const char *con_getvarstr(const struct con_var *v); float con_getvarf(const struct con_var *v); int con_getvari(const struct con_var *v); @@ -236,13 +259,16 @@ extern struct _con_vtab_iconvar_wrap { .name = "" #name_, .help = "" desc, .flags = (flags_) \ }, \ .vtable_iconvar = _con_vtab_iconvar, \ - .parent = &_cvar_##name_, /* bizarre, but how the engine does it */ \ - .defaultval = _Generic(value, char *: value, int: #value, \ - double: #value), \ - .strlen = sizeof(_Generic(value, char *: value, default: #value)), \ - .fval = _Generic(value, char *: 0, int: value, double: value), \ - .ival = _Generic(value, char *: 0, int: value, double: (int)value), \ - .hasmin = hasmin_, .minval = (min), .hasmax = hasmax_, .maxval = (max) \ + .v2 = { \ + .parent = &_cvar_##name_, /* bizarre, but how the engine does it */ \ + .defaultval = _Generic(value, char *: value, int: #value, \ + double: #value), \ + .strlen = sizeof(_Generic(value, char *: value, default: #value)), \ + .fval = _Generic(value, char *: 0, int: value, double: value), \ + .ival = _Generic(value, char *: 0, int: value, double: (int)value), \ + .hasmin = hasmin_, .minval = (min), \ + .hasmax = hasmax_, .maxval = (max) \ + } \ }; \ struct con_var *name_ = &_cvar_##name_; diff --git a/src/fixes.c b/src/fixes.c index ea008e5..d4b5330 100644 --- a/src/fixes.c +++ b/src/fixes.c @@ -32,7 +32,10 @@ static void chflags(const char *name, int unset, int set) { struct con_var *v = con_findvar(name); - if (v) v->parent->base.flags = v->parent->base.flags & ~unset | set; + if (v) { + struct con_var *p = con_getvarcommon(v)->parent; + p->base.flags = p->base.flags & ~unset | set; + } } static inline void unhide(const char *name) { @@ -93,17 +96,19 @@ static void generalfixes() { // for L4D games, generally changing anything above normal limits is // disallowed, but externally capping FPS will always be possible so we // might as well allow lowering it ingame for convenience. - if (v->parent->base.flags & (CON_HIDDEN | CON_DEVONLY)) { - v->parent->base.flags &= ~(CON_HIDDEN | CON_DEVONLY); - v->parent->hasmax = true; v->parent->maxval = 300; + struct con_var *p = con_getvarcommon(v)->parent; + struct con_var_common *c = con_getvarcommon(p); + if (p->base.flags & (CON_HIDDEN | CON_DEVONLY)) { + p->base.flags &= ~(CON_HIDDEN | CON_DEVONLY); + c->hasmax = true; c->maxval = 300; } - else if (!v->parent->hasmax) { + else if (!c->hasmax) { // in TLS, this was made changeable, but still limit to 1000 to // prevent breaking the engine - v->parent->hasmax = true; v->parent->maxval = 1000; + c->hasmax = true; c->maxval = 1000; } // also show the lower limit in help, and prevent 0 (which is unlimited) - v->parent->hasmin = true; v->parent->minval = 30; + c->hasmin = true; c->minval = 30; con_setvarf(v, con_getvarf(v)); // hack: reapply limit if we loaded late } } @@ -128,11 +133,13 @@ static void l4d2specific() { // possible on these earlier versions (who knows if that breaks // something...). struct con_var *v = con_findvar("mat_queue_mode"); - if_hot (v && !(v->parent->base.flags & CON_ARCHIVE)) { // not already fixed - v->parent->base.flags = v->parent->base.flags & + struct con_var *p = con_getvarcommon(v)->parent; + if_hot (v && !(p->base.flags & CON_ARCHIVE)) { // not already fixed + struct con_var_common *c = con_getvarcommon(p); + p->base.flags = p->base.flags & ~(CON_HIDDEN | CON_DEVONLY) | CON_ARCHIVE; - v->parent->hasmin = true; v->parent->minval = -1; - v->parent->hasmax = true; v->parent->maxval = 0; + c->hasmin = true; c->minval = -1; + c->hasmax = true; c->maxval = 0; } #ifdef _WIN32 @@ -24,7 +24,6 @@ #include "ent.h" #include "event.h" #include "feature.h" -#include "gametype.h" #include "hook.h" #include "intdefs.h" #include "langext.h" @@ -88,8 +87,10 @@ INIT { if_cold (!cmd_fov) return FEAT_INCOMPAT; // shouldn't happen, but who knows! if (real_fov_desired = con_findvar("fov_desired")) { // latest steampipe already goes up to 120 fov - if (real_fov_desired->parent->maxval == 120) return FEAT_SKIP; - real_fov_desired->parent->maxval = 120; + struct con_var *p = con_getvarcommon(real_fov_desired)->parent; + struct con_var_common *c = con_getvarcommon(p); + if (c->maxval == 120) return FEAT_SKIP; + c->maxval = 120; } else { if (!has_ent) return FEAT_INCOMPAT; @@ -109,7 +110,7 @@ INIT { // we might not be using our cvar but simpler to do this unconditionally fov_desired->cb = &fovcb; - fov_desired->parent->base.flags &= ~CON_HIDDEN; + fov_desired->base.flags &= ~CON_HIDDEN; // hide the original fov command since we've effectively broken it anyway :) cmd_fov->base.flags |= CON_DEVONLY; return FEAT_OK; @@ -118,10 +119,10 @@ INIT { END { if_hot (!sst_userunloaded) return; if (real_fov_desired && real_fov_desired != fov_desired) { - real_fov_desired->parent->maxval = 90; - if (con_getvarf(real_fov_desired) > 90) { - con_setvarf(real_fov_desired, 90); // blegh. - } + struct con_var *p = con_getvarcommon(real_fov_desired)->parent; + struct con_var_common *c = con_getvarcommon(p); + c->maxval = 90; + if (c->fval > 90) con_setvarf(real_fov_desired, 90); // blegh. } else { void *player = ent_get(1); // also singleplayer only diff --git a/src/inputhud.c b/src/inputhud.c index fdefe6a..b93e9d8 100644 --- a/src/inputhud.c +++ b/src/inputhud.c @@ -432,14 +432,16 @@ INIT { // HL2 sprint HUD, so move it up. This is a bit yucky, but at least we don't // have to go through all the virtual setter crap twice... if (GAMETYPE_MATCHES(L4D)) { - sst_inputhud_y->defaultval = "0.82"; - sst_inputhud_y->fval = 0.82f; - sst_inputhud_y->ival = 0; + struct con_var_common *c = con_getvarcommon(sst_inputhud_y); + c->defaultval = "0.82"; + c->fval = 0.82f; + c->ival = 0; } else if (GAMETYPE_MATCHES(HL2series)) { - sst_inputhud_y->defaultval = "0.75"; - sst_inputhud_y->fval = 0.75f; - sst_inputhud_y->ival = 0; + struct con_var_common *c = con_getvarcommon(sst_inputhud_y); + c->defaultval = "0.75"; + c->fval = 0.75f; + c->ival = 0; } return FEAT_OK; |