summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-03-24 02:06:28 +0000
committerMichael Smith <mikesmiffy128@gmail.com>2022-03-24 04:38:25 +0000
commit00ad7cdd3d05d09a43bda972c823fdc440feabb9 (patch)
tree7f9725341e598f273fc1fb6ca0803c794bb67698 /src
parentb18326a75078530df7712667f41b4ea354e1da3e (diff)
Clean up gameinfo_init() and other random stuff
- Just ask the engine for the game directory instead of doing the stupid argv sniffing hacks from the early days of trying to get the damn thing working. - Also add some other path variables, functions and whatnot, and do some other minor tidying up. - Also also, another damn copyright year, somebody please help me. Unfortunate negative effect off this change: con_init() no longer reports the game name, because it has to happen before gameinfo_init(). I've decided I don't really care, though.
Diffstat (limited to 'src')
-rw-r--r--src/con_.c8
-rw-r--r--src/gameinfo.c212
-rw-r--r--src/gameinfo.h14
-rw-r--r--src/gametype.h17
-rw-r--r--src/hook.c4
-rw-r--r--src/os-unix.h11
-rw-r--r--src/os-win32.h13
-rw-r--r--src/os.h1
-rw-r--r--src/sst.c21
9 files changed, 145 insertions, 156 deletions
diff --git a/src/con_.c b/src/con_.c
index ab1cd1e..925eafb 100644
--- a/src/con_.c
+++ b/src/con_.c
@@ -23,7 +23,6 @@
#include "abi.h"
#include "con_.h"
#include "extmalloc.h"
-#include "gameinfo.h"
#include "gametype.h"
#include "mem.h"
#include "os.h"
@@ -427,9 +426,6 @@ bool con_init(void *(*f)(const char *, int *), int plugin_ver) {
// (which for some other reason also has some vtable changes)
if (VCALL(_con_iface, FindVar, "avatarbasemodel")) {
_gametype_tag |= _gametype_tag_L4DS;
- // stupid hack: gameinfo.txt still just says Left 4 Dead 2 but
- // this is _not_ Left 4 Dead 2, dammit
- gameinfo_title = "Left 4 Dead: Survivors";
}
else {
_gametype_tag |= _gametype_tag_L4D2;
@@ -441,8 +437,7 @@ bool con_init(void *(*f)(const char *, int *), int plugin_ver) {
_gametype_tag |= _gametype_tag_L4D1;
}
else {
- con_warn("sst: error: game \"%s\" is unsupported (using "
- "VEngineCvar007)\n", gameinfo_title);
+ con_warn("sst: error: game is unsupported (using VEngineCvar007)\n");
ifacever = 7;
goto e;
}
@@ -478,7 +473,6 @@ warnoe: con_warn("sst: error: old engine console support is not implemented\n");
e: con_msg("\n\n");
con_msg("-- Please include ALL of the following if asking for help:\n");
con_msg("-- plugin: " LONGNAME " v" VERSION "\n");
- con_msg("-- game: %s\n", gameinfo_title);
con_msg("-- interfaces: %d/%d\n", plugin_ver, ifacever);
con_msg("\n\n");
return false;
diff --git a/src/gameinfo.c b/src/gameinfo.c
index 7dfcc53..42bf3b4 100644
--- a/src/gameinfo.c
+++ b/src/gameinfo.c
@@ -22,40 +22,41 @@
#endif
#include "con_.h"
+#include "gametype.h"
#include "intdefs.h"
#include "kv.h"
#include "os.h"
+#include "vcall.h"
-// Formatting for os_char * -> char * (or vice versa) - needed for con_warn()s
-// with file paths, etc
#ifdef _WIN32
#define fS "S" // os string (wide string) to regular string
#define Fs L"S" // regular string to os string (wide string)
+#define PATHSEP L"\\" // for joining. could just be / but \ is more consistent
#else
// everything is just a regular string already
#define fS "s"
#define Fs "s"
+#define PATHSEP "/"
#endif
-static os_char exedir[PATH_MAX];
-static os_char gamedir[PATH_MAX];
-static char _gameinfo_title[64] = {0};
-const char *gameinfo_title = _gameinfo_title;
-static os_char _gameinfo_clientlib[PATH_MAX] = {0};
-const os_char *gameinfo_clientlib = _gameinfo_clientlib;
-static os_char _gameinfo_serverlib[PATH_MAX] = {0};
-const os_char *gameinfo_serverlib = _gameinfo_serverlib;
+// TODO(opt): get rid of the rest of the snprintf and strcpy, some day
-// magical argc/argv grabber so we don't have to go through procfs
-#ifdef __linux__
-static const char *const *prog_argv;
-static int storeargs(int argc, char *argv[]) {
- prog_argv = (const char *const *)argv;
- return 0;
-}
-__attribute__((used, section(".init_array")))
-static void *pstoreargs = (void *)&storeargs;
+static os_char bindir[PATH_MAX] = {0};
+#ifdef _WIN32
+static os_char gamedir[PATH_MAX] = {0};
+#endif
+static os_char clientlib[PATH_MAX] = {0};
+static os_char serverlib[PATH_MAX] = {0};
+static char title[64] = {0};
+
+const os_char *gameinfo_bindir = bindir;
+const os_char *gameinfo_gamedir
+#ifdef _WIN32
+ = gamedir; // on linux, the pointer gets directly set in gameinfo_init()
#endif
+const os_char *gameinfo_clientlib = clientlib;
+const os_char *gameinfo_serverlib = serverlib;
+const char *gameinfo_title = title;
// case insensitive substring match, expects s2 to be lowercase already!
// note: in theory this shouldn't need to be case sensitive, but I've seen mods
@@ -65,7 +66,7 @@ static bool matchtok(const char *s1, const char *s2, usize sz) {
return true;
}
-static void try_gamelib(const os_char *path, os_char *outpath) {
+static void trygamelib(const os_char *path, os_char *outpath) {
// _technically_ this is toctou, but I don't think that matters here
if (os_access(path, F_OK) != -1) {
os_strcpy(outpath, path);
@@ -77,13 +78,14 @@ static void try_gamelib(const os_char *path, os_char *outpath) {
}
// note: p and len are a non-null-terminated string
-static inline void do_gamelib_search(const char *p, uint len, bool isgamebin) {
+static inline void dolibsearch(const char *p, uint len, bool isgamebin,
+ const os_char *cwd) {
// sanity check: don't do a bunch of work for no reason
if (len >= PATH_MAX - 1 - (sizeof("client" OS_DLSUFFIX) - 1)) goto toobig;
os_char bindir[PATH_MAX];
os_char *outp = bindir;
// this should really be an snprintf, meh whatever
- os_strcpy(bindir, exedir);
+ os_strcpy(bindir, cwd);
outp = bindir + os_strlen(bindir);
// quick note about windows encoding conversion: this MIGHT clobber the
// encoding of non-ascii mod names, but it's unclear if/how source handles
@@ -136,17 +138,18 @@ toobig: con_warn("gameinfo: skipping an overly long search path\n");
outp += ret;
if (!*gameinfo_clientlib) {
os_strcpy(outp, OS_LIT("client" OS_DLSUFFIX));
- try_gamelib(bindir, _gameinfo_clientlib);
+ trygamelib(bindir, clientlib);
}
if (!*gameinfo_serverlib) {
os_strcpy(outp, OS_LIT("server" OS_DLSUFFIX));
- try_gamelib(bindir, _gameinfo_serverlib);
+ trygamelib(bindir, serverlib);
}
}
-// state for the callback below to keep it somewhat reentrant-ish (except where
-// it isn't because I got lazy and wrote some spaghetti)
+// state for the callback below to keep it somewhat reentrant (except where
+// it's not because I got lazy and wrote some spaghetti)
struct kv_parsestate {
+ const os_char *cwd;
// after parsing a key we *don't* care about, how many nested subkeys have
// we come across?
short dontcarelvl;
@@ -208,21 +211,21 @@ static void kv_cb(enum kv_token type, const char *p, uint len, void *_ctxt) {
break;
case KV_VAL: case KV_VAL_QUOTED:
if (ctxt->dontcarelvl) break;
- if (ctxt->matchtype == mt_title) {
+ // dumb hack: ignore Survivors title (they left it set to "Left 4
+ // Dead 2" but it clearly isn't Left 4 Dead 2)
+ if (ctxt->matchtype == mt_title && !GAMETYPE_MATCHES(L4DS)) {
// title really shouldn't get this long, but truncate just to
// avoid any trouble...
// also note: leaving 1 byte of space for null termination (the
// buffer is already zeroed initially)
- if (len > sizeof(_gameinfo_title) - 1) {
- len = sizeof(_gameinfo_title) - 1;
- }
- memcpy(_gameinfo_title, p, len);
+ if (len > sizeof(title) - 1) len = sizeof(title) - 1;
+ memcpy(title, p, len);
}
else if (ctxt->matchtype == mt_game ||
ctxt->matchtype == mt_gamebin) {
// if we already have everything, we can just stop!
if (*gameinfo_clientlib && *gameinfo_serverlib) break;
- do_gamelib_search(p, len, ctxt->matchtype == mt_gamebin);
+ dolibsearch(p, len, ctxt->matchtype == mt_gamebin, ctxt->cwd);
}
ctxt->matchtype = mt_none;
break;
@@ -236,112 +239,67 @@ static void kv_cb(enum kv_token type, const char *p, uint len, void *_ctxt) {
#undef MATCH
}
-bool gameinfo_init(void) {
- const os_char *modname = OS_LIT("hl2");
-#ifdef _WIN32
- int len = GetModuleFileNameW(0, exedir, PATH_MAX);
- if (!len) {
- char err[128];
- OS_WINDOWS_ERROR(err);
- con_warn("gameinfo: couldn't get EXE path: %s\n", err);
- return false;
- }
- // if the buffer is full and has no null, it's truncated
- if (len == PATH_MAX && exedir[len - 1] != L'\0') {
- con_warn("gameinfo: EXE path is too long!\n");
- return false;
+bool gameinfo_init(void *(*ifacef)(const char *, int *)) {
+ typedef char *(*VCALLCONV GetGameDirectory_func)(void *this);
+ GetGameDirectory_func **engclient;
+ int off;
+ if (engclient = ifacef("VEngineClient014", 0)) { // bms, l4d2 2000
+ off = 36;
}
-#else
- int len = readlink("/proc/self/exe", exedir, PATH_MAX);
- if (len == -1) {
- con_warn("gameinfo: couldn't get program path: %s\n", strerror(errno));
- return false;
+ else if (engclient = ifacef("VEngineClient013", 0)) { // ...most things?
+ if (GAMETYPE_MATCHES(L4D2)) off = 36; // they changed it BACK?!?
+ else off = 35;
}
- // if the buffer is full at all, it's truncated (readlink never writes \0)
- if (len == PATH_MAX) {
- con_warn("gameinfo: program path is too long!\n");
- return false;
+ else if (engclient = ifacef("VEngineClient012", 0)) { // dmomm, ep1, ...
+ off = 37;
}
else {
- exedir[len] = '\0';
+ con_warn("gameinfo: unsupported VEngineClient interface\n");
+ return false;
}
-#endif
- // find the last slash
- os_char *p;
- for (p = exedir + len - 1; *p != OS_LIT('/')
-#ifdef _WIN32
- && *p != L'\\'
-#endif
- ; --p);
- // ... and split on it
- *p = 0;
- const os_char *exename = p + 1;
-#ifdef _WIN32
- // try and infer the default mod name (when -game isn't given) from the exe
- // name for a few known games
- if (!_wcsicmp(exename, L"left4dead2.exe")) modname = L"left4dead2";
- else if (!_wcsicmp(exename, L"left4dead.exe")) modname = L"left4dead";
- else if (!_wcsicmp(exename, L"portal2.exe")) modname = L"portal2";
+ GetGameDirectory_func GetGameDirectory = (*engclient)[off];
- const ushort *args = GetCommandLineW();
- const ushort *argp = args;
- ushort modbuf[PATH_MAX];
- // have to take the _last_ occurence of -game because sourcemods get the
- // flag twice, for some reason
- while (argp = wcsstr(argp, L" -game ")) {
- argp += 7;
- while (*argp == L' ') ++argp;
- ushort sep = L' ';
- // WARNING: not handling escaped quotes and such nonsense, since you
- // can't have quotes in filepaths anyway outside of UNC and I'm just
- // assuming there's no way Source could even be started with such an
- // insanely named mod. We'll see how this assumption holds up!
- if (*argp == L'"') {
- ++argp;
- sep = L'"';
- }
- ushort *bufp = modbuf;
- for (; *argp != L'\0' && *argp != sep; ++argp, ++bufp) {
- if (bufp - modbuf == PATH_MAX - 1) {
- con_warn("gameinfo: mod name parameter is too long\n");
- return false;
- }
- *bufp = *argp;
- }
- *bufp = L'\0';
- modname = modbuf;
+ // engine always calls chdir() with its own base path on startup, so engine
+ // base dir is just cwd
+ os_char cwd[PATH_MAX];
+ if (!os_getcwd(cwd, sizeof(cwd) / sizeof(*cwd))) {
+ con_warn("gameinfo: couldn't get working directory: %s\n",
+ strerror(errno));
+ return false;
}
- bool isrelative = PathIsRelativeW(modname);
-#else
- // also do the executable name check just for portal2_linux
- if (!strcmp(exename, "portal2_linux")) modname = "portal2";
- // ah, the sane, straightforward world of unix command line arguments :)
- for (const char *const *pp = prog_argv + 1; *pp; ++pp) {
- if (!strcmp(*pp, "-game")) {
- if (!*++pp) break;
- modname = *pp;
- }
+ int len = os_strlen(cwd);
+ if (len + sizeof("/bin") > sizeof(bindir) / sizeof(*bindir)) {
+ con_warn("gameinfo: working directory path is too long!\n");
+ return false;
}
- // ah, the sane, straightforward world of unix paths :)
- bool isrelative = modname[0] != '/';
-#endif
+ memcpy(bindir, cwd, len * sizeof(*cwd));
+ memcpy(bindir + len, PATHSEP OS_LIT("bin"), 5 * sizeof(os_char));
- int ret = isrelative ?
- os_snprintf(gamedir, PATH_MAX, OS_LIT("%s/%s"), exedir, modname) :
- // mod name might actually be an absolute (if installed in steam
- // sourcemods for example)
- os_snprintf(gamedir, PATH_MAX, OS_LIT("%s"), modname);
- if (ret >= PATH_MAX) {
- con_warn("gameinfo: game directory path is too long!\n");
+#ifdef _WIN32
+ int gamedirlen = _snwprintf(gamedir, sizeof(gamedir) / sizeof(*gamedir),
+ L"%S", GetGameDirectory(engclient));
+ if (gamedirlen < 0) { // encoding error??? ugh...
+ con_warn("gameinfo: invalid game directory path!\n");
return false;
}
- os_char gameinfopath[PATH_MAX];
- if (os_snprintf(gameinfopath, PATH_MAX, OS_LIT("%s/gameinfo.txt"),
- gamedir) >= PATH_MAX) {
- con_warn("gameinfo: gameinfo.txt path is too long!\n");
+ // immediately bounds check /gameinfo as we cat that into an equal sized
+ // buffer down below :^)
+ if (gamedirlen + sizeof("/gameinfo.txt") > sizeof(gamedir) /
+ sizeof(*gamedir)) {
+ con_warn("gameinfo: game directory path is too long!\n");
return false;
}
+#else
+ // no need to munge charset, use the string pointer directly
+ gameinfo_gamedir = GetGameDirectory(engclient);
+ int gamedirlen = strlen(gameinfo_gamedir);
+#endif
+ os_char gameinfopath[PATH_MAX];
+ memcpy(gameinfopath, gameinfo_gamedir, gamedirlen *
+ sizeof(*gameinfo_gamedir));
+ memcpy(gameinfopath + gamedirlen, PATHSEP OS_LIT("gameinfo.txt"),
+ 14 * sizeof(os_char));
int fd = os_open(gameinfopath, O_RDONLY);
if (fd == -1) {
con_warn("gameinfo: couldn't open gameinfo.txt: %s\n", strerror(errno));
@@ -349,7 +307,7 @@ bool gameinfo_init(void) {
}
char buf[1024];
struct kv_parser kvp = {0};
- struct kv_parsestate ctxt = {0};
+ struct kv_parsestate ctxt = {.cwd = cwd};
int nread;
while (nread = read(fd, buf, sizeof(buf))) {
if (nread == -1) {
@@ -360,8 +318,10 @@ bool gameinfo_init(void) {
if (!kv_parser_feed(&kvp, buf, nread, &kv_cb, &ctxt)) goto ep;
}
if (!kv_parser_done(&kvp)) goto ep;
-
close(fd);
+
+ // dumb hack pt2, see also kv callback above
+ if (GAMETYPE_MATCHES(L4DS)) gameinfo_title = "Left 4 Dead: Survivors";
return true;
ep: con_warn("gameinfo: couldn't parse gameinfo.txt (%d:%d): %s\n",
diff --git a/src/gameinfo.h b/src/gameinfo.h
index d94b117..eac5009 100644
--- a/src/gameinfo.h
+++ b/src/gameinfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2021 Michael Smith <mikesmiffy128@gmail.com>
+ * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,20 +17,24 @@
#ifndef INC_GAMEINFO_H
#define INC_GAMEINFO_H
+#include <stdio.h>
+
#include "intdefs.h"
#include "os.h"
/* These variables are only set after calling gameinfo_init(). */
-extern const char *gameinfo_title; /* Name of the game (window title) */
-extern const os_char *gameinfo_clientlib; /* Path to the client library */
-extern const os_char *gameinfo_serverlib; /* Path to the server library */
+extern const os_char *gameinfo_bindir; /* Absolute path to top-level bin/ */
+extern const os_char *gameinfo_gamedir; /* Absolute path to game directory */
+extern const char *gameinfo_title; /* Name of the game (window title) */
+extern const os_char *gameinfo_clientlib; /* Absolute path to the client lib */
+extern const os_char *gameinfo_serverlib; /* Absolute path to the server lib */
/*
* This function is called early in the plugin load and does a whole bunch of
* spaghetti magic to figure out which game/engine we're in and where its
* libraries (which we want to hook) are located.
*/
-bool gameinfo_init(void);
+bool gameinfo_init(void *(*ifacef)(const char *, int *));
#endif
diff --git a/src/gametype.h b/src/gametype.h
index c8bdf8a..fbf8db2 100644
--- a/src/gametype.h
+++ b/src/gametype.h
@@ -22,18 +22,23 @@
extern u32 _gametype_tag;
#define _gametype_tag_OE 1
-#define _gametype_tag_OrangeBox 2
-#define _gametype_tag_L4D1 4
-#define _gametype_tag_L4D2 8
-#define _gametype_tag_L4DS 16
-#define _gametype_tag_Portal2 32
-#define _gametype_tag_2013 64
+// TODO(compat): detect in con_init, even if just to fail (VEngineServer broke)
+// TODO(compat): buy dmomm in a steam sale to implement and test the above, lol
+#define _gametype_tag_DMoMM 2
+#define _gametype_tag_OrangeBox 4
+#define _gametype_tag_L4D1 8
+#define _gametype_tag_L4D2 16
+#define _gametype_tag_L4DS 32
+#define _gametype_tag_Portal2 64
+#define _gametype_tag_2013 128
#define _gametype_tag_L4D (_gametype_tag_L4D1 | _gametype_tag_L4D2)
// XXX: *stupid* naming, refactor later (damn Survivors ruining everything)
#define _gametype_tag_L4D2x (_gametype_tag_L4D2 | _gametype_tag_L4DS)
#define _gametype_tag_L4Dbased \
(_gametype_tag_L4D1 | _gametype_tag_L4D2x | _gametype_tag_Portal2)
+#define _gametype_tag_OrangeBoxbased \
+ (_gametype_tag_OrangeBox | _gametype_tag_2013)
#define GAMETYPE_MATCHES(x) !!(_gametype_tag & (_gametype_tag_##x))
diff --git a/src/hook.c b/src/hook.c
index 61cf614..6b9036c 100644
--- a/src/hook.c
+++ b/src/hook.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2021 Michael Smith <mikesmiffy128@gmail.com>
+ * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
* Copyright © 2022 Willian Henrique <wsimanbrazil@yahoo.com.br>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -97,7 +97,7 @@ void unhook_inline(void *orig) {
int len = p[-1];
int off = mem_load32(p + len + 1);
uchar *q = p + off + 5;
- memcpy(q, p, 5); // XXX not atomic atm! (does any of it even need to be?)
+ memcpy(q, p, 5); // XXX: not atomic atm! (does any of it even need to be?)
FlushInstructionCache(GetCurrentProcess(), q, 5);
}
diff --git a/src/os-unix.h b/src/os-unix.h
index 3b63bcc..6522029 100644
--- a/src/os-unix.h
+++ b/src/os-unix.h
@@ -35,6 +35,7 @@ typedef char os_char;
#define os_access access
#define os_stat stat
#define os_getenv getenv
+#define os_getcwd getcwd
#define OS_DLSUFFIX ".so"
@@ -42,6 +43,16 @@ typedef char os_char;
#define os_dlsym dlsym
+static inline bool os_dlfile(void *m, char *buf, int sz) {
+ // NOTE: this might be linux/glibc-specific (I haven't checked every
+ // implementation). this is fine as we don't use it in any build-time code,
+ // only in the plugin itself. just keep it in mind!
+ struct link_map *lm = m;
+ ssz len = strlen(lm->l_name) + 1;
+ if (ssz > sz) { errno = ENAMETOOLONG; return false; }
+ memcpy(buf, lm->l_name, ssz); return true;
+}
+
// unix mprot flags are much nicer but cannot be defined in terms of the windows
// ones, so we use the windows ones and define them in terms of the unix ones.
// another victory for stupid!
diff --git a/src/os-win32.h b/src/os-win32.h
index fb31d67..c7c0bae 100644
--- a/src/os-win32.h
+++ b/src/os-win32.h
@@ -41,6 +41,7 @@ typedef unsigned short os_char;
#define _stat64(path, buf) _wstat64(path, buf)
#define os_stat _stat64
#define os_getenv _wgetenv
+#define os_getcwd _wgetcwd
#define OS_DLSUFFIX ".dll"
@@ -50,6 +51,18 @@ static inline void *os_dlsym(void *m, const char *s) {
return (void *)GetProcAddress(m, s);
}
+static inline bool os_dlfile(void *m, unsigned short *buf, int sz) {
+ unsigned int n = GetModuleFileNameW(m, buf, sz);
+ if (n == 0 || n == sz) return false;
+ // get the canonical capitalisation, as for some reason GetModuleFileName()
+ // returns all lowercase. this doesn't really matter except it looks nicer
+ GetLongPathNameW(buf, buf, n + 1);
+ // the drive letter will also be lower case, if it is an actual drive letter
+ // of course. it should be; I'm not gonna lose sleep over UNC paths and such
+ if (buf[0] >= L'a' && buf[0] <= L'z' && buf[1] == L':') buf[0] &= ~32u;
+ return true;
+}
+
static inline bool os_mprot(void *addr, int len, int fl) {
unsigned long old;
return !!VirtualProtect(addr, len, fl, &old);
diff --git a/src/os.h b/src/os.h
index 5d62c2a..0e30005 100644
--- a/src/os.h
+++ b/src/os.h
@@ -42,6 +42,7 @@
#else
#include <dlfcn.h>
#include <limits.h>
+#include <link.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
diff --git a/src/sst.c b/src/sst.c
index aeb7f4c..1d0d18a 100644
--- a/src/sst.c
+++ b/src/sst.c
@@ -35,7 +35,7 @@
u32 _gametype_tag = 0; // spaghetti: no point making a .c file for 1 variable
-static int plugin_ver;
+static int ifacever;
// this is where we start dynamically adding virtual functions, see vtable[]
// array below
static const void **vtable_firstdiff;
@@ -75,6 +75,11 @@ static bool has_demorec_custom = false;
static bool has_rinput = false;
#endif
+// since this is static/global, it only becomes false again when the plugin SO
+// is unloaded/reloaded
+static bool already_loaded = false;
+static bool skip_unload = false;
+
// HACK: later versions of L4D2 show an annoying dialog on every plugin_load.
// We can suppress this by catching the message string that's passed from
// engine.dll to gameui.dll through KeyValuesSystem in vstdlib.dll and just
@@ -147,7 +152,8 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {
#ifndef __linux__
void *clientlib = 0;
#endif
- if (!gameinfo_init() || !con_init(enginef, plugin_ver)) return false;
+ if (!con_init(enginef, ifacever)) return false;
+ if (!gameinfo_init(enginef)) { con_disconnect(); return false; }
const void **p = vtable_firstdiff;
if (GAMETYPE_MATCHES(Portal2)) *p++ = (void *)&nop_p_v; // ClientFullyConnect
*p++ = (void *)&nop_p_v; // ClientDisconnect
@@ -155,9 +161,9 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {
*p++ = (void *)&SetCommandClient; // SetCommandClient
*p++ = (void *)&nop_p_v; // ClientSettingsChanged
*p++ = (void *)&nop_5pi_i; // ClientConnect
- *p++ = plugin_ver > 1 ? (void *)&nop_pp_i : (void *)&nop_p_i; // ClientCommand
- *p++ = (void *)&nop_pp_i; // NetworkIDValidated
+ *p++ = ifacever > 1 ? (void *)&nop_pp_i : (void *)&nop_p_i; // ClientCommand
// remaining stuff here is backwards compatible, so added unconditionally
+ *p++ = (void *)&nop_pp_i; // NetworkIDValidated
*p++ = (void *)&nop_ipipp_v; // OnQueryCvarValueFinished (002+)
*p++ = (void *)&nop_p_v; // OnEdictAllocated
*p = (void *)&nop_p_v; // OnEdictFreed
@@ -248,11 +254,6 @@ static void do_unload(void) {
}
}
-// since this is static/global, it only becomes false again when the plugin SO
-// is unloaded/reloaded
-static bool already_loaded = false;
-static bool skip_unload = false;
-
static bool VCALLCONV Load(void *this, ifacefactory enginef,
ifacefactory serverf) {
if (already_loaded) {
@@ -316,7 +317,7 @@ EXPORT const void *CreateInterface(const char *name, int *ret) {
if (!strncmp(name, "ISERVERPLUGINCALLBACKS00", 24)) {
if ((name[24] >= '1' || name[24] <= '3') && name[25] == '\0') {
if (ret) *ret = 0;
- plugin_ver = name[24] - '0';
+ ifacever = name[24] - '0';
return &plugin_obj;
}
}