diff --git a/metamod/src/conf_meta.cpp b/metamod/src/conf_meta.cpp index ef10dce..8a5058f 100644 --- a/metamod/src/conf_meta.cpp +++ b/metamod/src/conf_meta.cpp @@ -1,7 +1,8 @@ #include "precompiled.h" -MConfig::MConfig() : m_debuglevel(0), m_plugins_file(nullptr), m_exec_cfg(nullptr), m_list(nullptr), m_filename(nullptr) +MConfig::MConfig() : m_debuglevel(0), m_gamedll(nullptr), m_exec_cfg(nullptr), m_list(nullptr), m_filename(nullptr) { + set_directory(); } // Initialize default values from the stored options struct. Has to happen @@ -17,7 +18,7 @@ option_t *MConfig::find(const char* lookup) const { for (auto optp = m_list; optp->name; optp++) { - if (!strcmp(optp->name, lookup)) { + if (!Q_strcmp(optp->name, lookup)) { return optp; } } @@ -36,7 +37,7 @@ bool MConfig::set(const char* key, const char* value) const bool MConfig::set(option_t* setp, const char* setstr) { - char pathbuf[PATH_MAX ]; + char pathbuf[PATH_MAX]; int* optval = (int *) setp->dest; char** optstr = (char **) setp->dest; // cvar_t *optcvar = (cvar_t *) setp->dest; @@ -97,7 +98,7 @@ bool MConfig::set(option_t* setp, const char* setstr) bool MConfig::load(const char* fn) { FILE* fp; - char loadfile[PATH_MAX ]; + char loadfile[PATH_MAX]; char line[MAX_CONF_LEN]; char *optname, *optval; option_t* optp; @@ -178,3 +179,27 @@ void MConfig::show() const } } } + +void MConfig::set_directory() +{ +#ifdef _WIN32 + HMODULE hModule = NULL; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)GiveFnptrsToDll, &hModule); + GetModuleFileName(hModule, m_directory, sizeof m_directory); +#else + Dl_info addrInfo; + if (dladdr((void *)GiveFnptrsToDll, &addrInfo)) + { + Q_strncpy(m_directory, addrInfo.dli_fname, sizeof m_directory - 1); + m_directory[sizeof m_directory - 1] = '\0'; + } +#endif + + normalize_pathname(m_directory); + + // get directory + char *dir = Q_strrchr(m_directory, '/'); + if (dir) { + *dir = '\0'; + } +} diff --git a/metamod/src/conf_meta.h b/metamod/src/conf_meta.h index 1028a64..30da64f 100644 --- a/metamod/src/conf_meta.h +++ b/metamod/src/conf_meta.h @@ -30,14 +30,17 @@ public: bool load(const char *filename); bool set(const char *key, const char *value) const; void show() const; + void set_directory(); + const char *directory() const; int m_debuglevel; // to use for meta_debug - char *m_plugins_file; // ie metamod.ini, plugins.ini - char *m_exec_cfg; // ie metaexec.cfg, exec.cfg + char *m_gamedll; // string if specified in config.ini + char *m_exec_cfg; // ie exec.cfg private: option_t *m_list; char *m_filename; + char m_directory[MAX_PATH]; option_t *find(const char *lookup) const; static bool set(option_t *setp, const char *value); @@ -46,3 +49,8 @@ private: void operator=(const MConfig &src); MConfig(const MConfig &src); }; + +inline const char *MConfig::directory() const +{ + return m_directory; +} diff --git a/metamod/src/game_support.cpp b/metamod/src/game_support.cpp index 500f9e5..ecdfa12 100644 --- a/metamod/src/game_support.cpp +++ b/metamod/src/game_support.cpp @@ -11,7 +11,7 @@ const game_modinfo_t g_known_games[] = { // separate file, generated based on game information stored in a // convenient db. { "cstrike", "cs.so", "mp.dll", "Counter-Strike" }, - { "czero", "cs.so", "mp.dll", "Counter-Strike:Condition Zero" }, + { "czero", "cs.so", "mp.dll", "Counter-Strike:Condition Zero" }, // End of list terminator: { NULL, NULL, NULL, NULL } @@ -90,15 +90,10 @@ bool install_gamedll(char *from, const char *to) // - ME_NOTFOUND couldn't recognize game bool setup_gamedll(gamedll_t *gamedll) { + bool override = false; const game_modinfo_t *known; const char *knownfn = nullptr; - // Check for old-style "metagame.ini" file and complain. - if (valid_gamedir_file(OLD_GAMEDLL_TXT)) - { - META_WARNING("File '%s' is no longer supported; instead, specify override gamedll in %s or with '+localinfo mm_gamedll '", OLD_GAMEDLL_TXT, CONFIG_INI); - } - // First, look for a known game, based on gamedir. if ((known = lookup_game(gamedll->name))) { @@ -107,25 +102,46 @@ bool setup_gamedll(gamedll_t *gamedll) #else knownfn = known->linux_so; #endif + } - META_DEBUG(4, "Checking for old version game DLL name '%s'.\n", knownfn); - Q_snprintf(gamedll->pathname, sizeof gamedll->pathname, "dlls/%s", knownfn); + // Neither override nor known-list found a gamedll. + if (!known && !g_config->m_gamedll) + return false; - // Check if the gamedll file exists. If not, try to install it from the cache. - if (!valid_gamedir_file(gamedll->pathname)) + // Use override-dll if specified. + if (g_config->m_gamedll) + { + Q_strncpy(gamedll->pathname, g_config->m_gamedll, sizeof gamedll->pathname - 1); + gamedll->pathname[sizeof gamedll->pathname - 1] = '\0'; + + // If the path is relative, the gamedll file will be missing and + // it might be found in the cache file. + if (!is_absolute_path(gamedll->pathname)) { - Q_snprintf(gamedll->real_pathname, sizeof gamedll->real_pathname, "%s/dlls/%s", gamedll->gamedir, knownfn); - install_gamedll(gamedll->pathname, gamedll->real_pathname); + char szInstallPath[MAX_PATH]; + Q_snprintf(szInstallPath, sizeof(szInstallPath), "%s/%s", gamedll->gamedir, gamedll->pathname); + + // If we could successfully install the gamedll from the cache we + // rectify the pathname to be a full pathname. + if (install_gamedll(gamedll->pathname, szInstallPath)) + { + Q_strncpy(gamedll->pathname, szInstallPath, sizeof(gamedll->pathname)); + } } + + override = true; + } + // Else use Known-list dll. + else if (known) + { + Q_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "%s/dlls/%s", gamedll->gamedir, knownfn); } else { - // Neither known-list found a gamedll. + // Neither override nor known-list found a gamedll. return false; } - Q_snprintf(gamedll->pathname, sizeof gamedll->pathname, "%s/dlls/%s", gamedll->gamedir, knownfn); - // get filename from pathname char *cp = Q_strrchr(gamedll->pathname, '/'); if (cp) @@ -135,11 +151,33 @@ bool setup_gamedll(gamedll_t *gamedll) gamedll->file = cp; - Q_strncpy(gamedll->real_pathname, gamedll->pathname, sizeof gamedll->real_pathname - 1); - gamedll->real_pathname[sizeof gamedll->real_pathname - 1] = '\0'; + // If found, store also the supposed "real" dll path based on the + // gamedir, in case it differs from the "override" dll path. + if (known && override) + { + Q_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname), "%s/dlls/%s", gamedll->gamedir, knownfn); + } + else + { + Q_strncpy(gamedll->real_pathname, gamedll->pathname, sizeof gamedll->real_pathname - 1); + gamedll->real_pathname[sizeof gamedll->real_pathname - 1] = '\0'; + } - gamedll->desc = known->desc; - META_LOG("Recognized game '%s'; using dllfile '%s'", gamedll->name, gamedll->file); + if (override) + { + // generate a desc + Q_snprintf(gamedll->desc, sizeof(gamedll->desc), "%s (override)", gamedll->file); + + // log result + META_LOG("Overriding game '%s' with dllfile '%s'", gamedll->name, gamedll->file); + } + else if (known) + { + Q_strncpy(gamedll->desc, known->desc, sizeof gamedll->desc - 1); + gamedll->desc[sizeof gamedll->desc - 1] = '\0'; + + META_LOG("Recognized game '%s'; using dllfile '%s'", gamedll->name, gamedll->file); + } return true; } diff --git a/metamod/src/game_support.h b/metamod/src/game_support.h index f9204c6..366abfb 100644 --- a/metamod/src/game_support.h +++ b/metamod/src/game_support.h @@ -8,7 +8,6 @@ struct game_modinfo_t const char *name; // name (the game dir) const char *linux_so; // filename of linux shared lib const char *win_dll; // filename of win32 dll - const char *osx_dylib; // filename os osx dylib const char *desc; // our long-name description }; diff --git a/metamod/src/metamod.cpp b/metamod/src/metamod.cpp index 3f0d96a..f541ea7 100644 --- a/metamod/src/metamod.cpp +++ b/metamod/src/metamod.cpp @@ -6,9 +6,9 @@ MConfig g_static_config; MConfig *g_config = &g_static_config; option_t g_global_options[] = { - { "debuglevel", CF_INT, &g_config->m_debuglevel, "0" }, - { "plugins_file", CF_PATH, &g_config->m_plugins_file, PLUGINS_INI }, - { "exec_cfg", CF_STR, &g_config->m_exec_cfg, EXEC_CFG }, + { "debuglevel", CF_INT, &g_config->m_debuglevel, "0" }, + { "gamedll", CF_PATH, &g_config->m_gamedll, NULL }, + { "exec_cfg", CF_STR, &g_config->m_exec_cfg, NULL }, // list terminator { NULL, CF_NONE, NULL, NULL } @@ -35,10 +35,16 @@ int g_requestid_counter = 0; // Do startup operations... void metamod_startup() { - const char *mmfile = nullptr; - const char *cfile = nullptr; const char *cp; + char configFile[MAX_PATH]; + char pluginFile[MAX_PATH]; + char execFile[MAX_PATH]; + + Q_snprintf(configFile, sizeof configFile, "%s/%s", g_config->directory(), CONFIG_INI); + Q_snprintf(pluginFile, sizeof pluginFile, "%s/%s", g_config->directory(), PLUGINS_INI); + Q_snprintf(execFile, sizeof execFile, "%s/%s", g_config->directory(), EXEC_CFG); + META_CONS(" "); META_CONS(" Metamod-r version %s Copyright (c) 2016-2017 ReHlds Team (rebuild of original Metamod by Will Day)", APP_VERSION_STRD); META_CONS(" Metamod-r comes with ABSOLUTELY NO WARRANTY; for details type `meta gpl'."); @@ -65,25 +71,29 @@ void metamod_startup() // Set a slight debug level for developer mode, if debug level not // already set. - if ((int) CVAR_GET_FLOAT("developer") != 0 && g_meta_debug.value == 0) + if ((int)CVAR_GET_FLOAT("developer") != 0 && g_meta_debug.value == 0) CVAR_SET_FLOAT("meta_debug", 3.0); // Init default values g_config->init(g_global_options); // Find config file - cfile = CONFIG_INI; if ((cp = LOCALINFO("mm_configfile")) && *cp != '\0') { META_LOG("Configfile specified via localinfo: %s", cp); + if (valid_gamedir_file(cp)) - cfile = cp; + { + Q_strncpy(configFile, cp, sizeof configFile - 1); + configFile[sizeof configFile - 1] = '\0'; + } else - META_ERROR("Empty/missing config.ini file: %s; falling back to %s", cp, cfile); + META_ERROR("Empty/missing config.ini file: %s; falling back to %s", cp, configFile); } + // Load config file - if (valid_gamedir_file(cfile)) - g_config->load(cfile); + if (valid_gamedir_file(configFile)) + g_config->load(configFile); else META_DEBUG(2, "No config.ini file found: %s", CONFIG_INI); @@ -93,16 +103,19 @@ void metamod_startup() META_LOG("Debuglevel specified via localinfo: %s", cp); g_config->set("debuglevel", cp); } + if ((cp = LOCALINFO("mm_gamedll")) && *cp != '\0') { META_LOG("Gamedll specified via localinfo: %s", cp); g_config->set("gamedll", cp); } + if ((cp = LOCALINFO("mm_pluginsfile")) && *cp != '\0') { META_LOG("Pluginsfile specified via localinfo: %s", cp); g_config->set("plugins_file", cp); } + if ((cp = LOCALINFO("mm_execcfg")) && *cp != '\0') { META_LOG("Execcfg specified via localinfo: %s", cp); @@ -158,16 +171,8 @@ void metamod_startup() // In fact, we need gamedir even earlier, so moved up above. // Fall back to old plugins filename, if configured one isn't found. - mmfile = PLUGINS_INI; - if (!valid_gamedir_file(PLUGINS_INI) && valid_gamedir_file(OLD_PLUGINS_INI)) - mmfile = OLD_PLUGINS_INI; - if (valid_gamedir_file(g_config->m_plugins_file)) - mmfile = g_config->m_plugins_file; - else - META_ERROR("g_plugins file is empty/missing: %s; falling back to %s", g_config->m_plugins_file, mmfile); - - g_plugins = new MPluginList(mmfile); + g_plugins = new MPluginList(pluginFile); if (!meta_load_gamedll()) { @@ -189,23 +194,21 @@ void metamod_startup() // Only attempt load if the file appears to exist and be non-empty, to // avoid confusing users with "couldn't exec exec.cfg" console // messages. - if (valid_gamedir_file(g_config->m_exec_cfg)) - mmfile = g_config->m_exec_cfg; - - else if (valid_gamedir_file(OLD_EXEC_CFG)) - mmfile = OLD_EXEC_CFG; - else - mmfile = NULL; - - if (mmfile) + if (g_config->m_exec_cfg) { - if (mmfile[0] == '/') - META_ERROR("Cannot exec absolute pathnames: %s", mmfile); + Q_strncpy(execFile, g_config->m_exec_cfg, sizeof execFile - 1); + execFile[sizeof execFile - 1] = '\0'; + } + + if (valid_gamedir_file(execFile)) + { + if (execFile[0] == '/') + META_ERROR("Cannot exec absolute pathnames: %s", execFile); else { char cmd[NAME_MAX]; - META_LOG("Exec'ing metamod exec.cfg: %s...", mmfile); - Q_snprintf(cmd, sizeof cmd, "exec %s\n", mmfile); + META_LOG("Exec'ing metamod exec.cfg: %s...", execFile); + Q_snprintf(cmd, sizeof cmd, "exec %s\n", execFile); SERVER_COMMAND(cmd); } } diff --git a/metamod/src/metamod.h b/metamod/src/metamod.h index f8b1fc9..21f8f3f 100644 --- a/metamod/src/metamod.h +++ b/metamod/src/metamod.h @@ -9,19 +9,9 @@ #include "meta_eiface.h" // HL_enginefuncs_t, meta_enginefuncs_t #include "engine_t.h" // engine_t, Engine -// file that lists plugins to load at startup -#define PLUGINS_INI "addons/metamod/plugins.ini" -#define OLD_PLUGINS_INI "metamod.ini" - -// file that contains commands to metamod plugins at startup -#define EXEC_CFG "addons/metamod/exec.cfg" -#define OLD_EXEC_CFG "metaexec.cfg" - -// previously, file that contained path for an override-gamedll -#define OLD_GAMEDLL_TXT "metagame.ini" - -// generic config file -#define CONFIG_INI "addons/metamod/config.ini" +#define PLUGINS_INI "plugins.ini" // file that lists plugins to load at startup +#define EXEC_CFG "exec.cfg" // file that contains commands to metamod plugins at startup +#define CONFIG_INI "config.ini" // generic config file // cvar to contain version extern cvar_t g_meta_version; @@ -30,7 +20,7 @@ extern cvar_t g_meta_version; struct gamedll_t { char name[NAME_MAX]; // ie "cstrike" (from gamedir) - const char *desc; // ie "Counter-Strike" + char desc[NAME_MAX]; // ie "Counter-Strike" char gamedir[PATH_MAX]; // ie "/home/willday/half-life/cstrike" char pathname[PATH_MAX]; // ie "/home/willday/half-life/cstrike/dlls/cs_i386.so" char const *file; // ie "cs_i386.so" diff --git a/metamod/src/mplugin.cpp b/metamod/src/mplugin.cpp index c509e6f..dcd9a64 100644 --- a/metamod/src/mplugin.cpp +++ b/metamod/src/mplugin.cpp @@ -311,7 +311,7 @@ bool MPlugin::resolve(void) // GAMEDIR/dlls/filename char *MPlugin::resolve_dirs(char *path) const { - static char buf[PATH_MAX ]; + static char buf[PATH_MAX]; Q_snprintf(buf, sizeof buf, "%s/%s", g_GameDLL.gamedir, path); diff --git a/metamod/src/support_meta.cpp b/metamod/src/support_meta.cpp index 44f92fd..88741e7 100644 --- a/metamod/src/support_meta.cpp +++ b/metamod/src/support_meta.cpp @@ -67,7 +67,7 @@ int valid_gamedir_file(const char* path) // able to store a string of PATH_MAX length. char* full_gamedir_path(const char* path, char* fullpath) { - char buf[PATH_MAX ]; + char buf[PATH_MAX]; // Build pathname from filename, plus gamedir if relative path. if (is_absolute_path(path))