aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/autojump.c2
-rw-r--r--src/build/gluegen.c3
-rw-r--r--src/con_.c55
-rw-r--r--src/con_.h52
-rw-r--r--src/fixes.c29
-rw-r--r--src/fov.c17
-rw-r--r--src/inputhud.c14
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) {
diff --git a/src/con_.c b/src/con_.c
index b2d7e29..d0ad7ce 100644
--- a/src/con_.c
+++ b/src/con_.c
@@ -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)
diff --git a/src/con_.h b/src/con_.h
index b491aad..c2c0cce 100644
--- a/src/con_.h
+++ b/src/con_.h
@@ -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
diff --git a/src/fov.c b/src/fov.c
index bfef858..2ef13e9 100644
--- a/src/fov.c
+++ b/src/fov.c
@@ -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;