From 30268f7b8f4f76401169a60b1732197d43e9201a Mon Sep 17 00:00:00 2001 From: STAM Date: Tue, 23 Jan 2018 15:20:36 +0300 Subject: [PATCH] updated original sources from commit e32e4f6 * updated original sources from commit https://github.com/theAsmodai/metamod-r/commit/e32e4f6d6ec660bed47a452e09706fe7dd786eca * added list of games --- metamod/src/game_support.cpp | 193 ++++++++++++++++++++++++++++++++++- 1 file changed, 188 insertions(+), 5 deletions(-) diff --git a/metamod/src/game_support.cpp b/metamod/src/game_support.cpp index 8d3a6d6..680ad04 100644 --- a/metamod/src/game_support.cpp +++ b/metamod/src/game_support.cpp @@ -1,3 +1,5 @@ +#include "precompiled.h" + // Adapted from adminmod h_export.cpp: //! this structure contains a list of supported mods and their dlls names //! To add support for another mod add an entry here, and add all the @@ -8,9 +10,6 @@ const game_modinfo_t g_known_games[] = { // Previously enumerated in this sourcefile, the list is now kept in a // separate file, generated based on game information stored in a // convenient db. - // - // List contains only steam\steampipe versions of mods. Any won-versions of mods is not included! - // { "action", "ahl_i386.so", "ahl.dll", "Action Half-Life" }, // + director's cut [2016], updated linux binary name { "ag", "ag.so", "ag.dll", "Adrenaline Gamer" }, // .so file by OpenAG fork { "asheep", nullptr, "hl.dll", "Azure Sheep" }, // have no linux binary found! @@ -88,7 +87,7 @@ const game_modinfo_t g_known_games[] = { { "timeless", "pt.so", "timeless.dll", "Project Timeless" }, { "tod", "hl.so", "hl.dll", "Tour of Duty" }, { "trainhunters", "th.so", "th.dll", "Train Hunters" }, - { "ts", "ts_i686.so", "mp.dll", "The Specialists" }, + { "ts", "ts_i686.so", "mp.dll", "The Specialists" }, { "ts", "ts_i386.so", "mp.dll", "The Specialists" }, { "tt", "tt.so", "tt.dll", "The Trenches" }, { "underworld", "uw.so", "uw.dll", "Underworld Bloodline" }, @@ -101,8 +100,192 @@ const game_modinfo_t g_known_games[] = { { "wormshl", "wormshl_i586.so", "wormshl.dll", "WormsHL (Old)" }, { "wormshl", "wormshl_i686.so", "wormshl.dll", "WormsHL (Steam)" }, { "zp", "hl_i386.so", "mp.dll", "Zombie Panic" }, - // End of list terminator: { nullptr, nullptr, nullptr, nullptr } }; +// Find a modinfo corresponding to the given game name. +static const game_modinfo_t *lookup_game(const char *name) +{ + for (auto& known : g_known_games) { + if (known.name && !Q_stricmp(known.name, name)) + return &known; + } + + // no match found + return nullptr; +} + +bool lookup_game_postfixes(gamedll_t *gamedll) +{ + char pathname[MAX_PATH]; + static char postfix_path[MAX_PATH] = ""; + + Q_strlcpy(pathname, gamedll->pathname); + + // find extensions and skip + char *pos = Q_strrchr(pathname, '.'); + if (pos) { + *pos = '\0'; + } + + for (size_t i = 0; i < arraysize(g_platform_postfixes); i++) + { + postfix_path[0] = '\0'; + Q_strlcat(postfix_path, pathname); + Q_strlcat(postfix_path, g_platform_postfixes[i]); + + if (is_file_exists_in_gamedir(postfix_path)) { + Q_strlcpy(gamedll->pathname, postfix_path); + Q_strlcpy(gamedll->real_pathname, postfix_path); + gamedll->file = postfix_path; + + return true; + } + } + + return false; +} + +// Installs gamedll from Steam cache +bool install_gamedll(char *from, const char *to) +{ + if (!from) + return false; + + if (!to) + to = from; + + int length_in; + byte *cachefile = LOAD_FILE_FOR_ME(from, &length_in); + + // If the file seems to exist in the cache. + if (cachefile) { + int fd = open(to, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd < 0) { + META_DEBUG(3, "Installing gamedll from cache: Failed to create file %s: %s", to, strerror(errno)); + FREE_FILE(cachefile); + return false; + } + + int length_out = write(fd, cachefile, length_in); + FREE_FILE(cachefile); + close(fd); + + // Writing the file was not successfull + if (length_out != length_in) { + META_DEBUG(3, "Installing gamedll from chache: Failed to write all %d bytes to file, only %d written: %s", length_in, length_out, strerror(errno)); + + // Let's not leave a mess but clean up nicely. + if (length_out >= 0) + _unlink(to); + + return false; + } + + META_LOG("Installed gamedll %s from cache.", to); + } + else { + META_DEBUG(3, "Failed to install gamedll from cache: file %s not found in cache.", from); + return false; + } + + return true; +} + +// Set all the fields in the gamedll struct, - based either on an entry in +// known_games matching the current gamedir, or on one specified manually +// by the server admin. +// +// meta_errno values: +// - ME_NOTFOUND couldn't recognize game +bool setup_gamedll(gamedll_t *gamedll) +{ + bool override = false; + const game_modinfo_t *known; + const char *knownfn = nullptr; + + // First, look for a known game, based on gamedir. + if ((known = lookup_game(gamedll->name))) { +#ifdef _WIN32 + knownfn = known->win_dll; +#else + knownfn = known->linux_so; +#endif + } + + // Neither override nor known-list found a gamedll. + if (!known && !g_config->m_gamedll) + return false; + + // Use override-dll if specified. + if (g_config->m_gamedll) { + Q_strlcpy(gamedll->pathname, g_config->m_gamedll); + + // If the path is relative, the gamedll file will be missing and + // it might be found in the cache file. + if (!is_abs_path(gamedll->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_strlcpy(gamedll->pathname, szInstallPath); + } + } + + 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 override nor known-list found a gamedll. + return false; + } + + // get filename from pathname + char *cp = Q_strrchr(gamedll->pathname, '/'); + if (cp) + cp++; + else + cp = gamedll->pathname; + + gamedll->file = cp; + + // 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_strlcpy(gamedll->real_pathname, gamedll->pathname); + } + + 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_strlcpy(gamedll->desc, known->desc); + +#if !defined(_WIN32) + if (!is_file_exists_in_gamedir(gamedll->pathname)) + { + // trying lookup gamedll with postfixes ie _i386.so + if (lookup_game_postfixes(gamedll)) { + META_DEBUG(3, "dll: Trying lookup to gamedll with postfixes was a success. Game '%s'", gamedll->pathname); + } + } +#endif + + META_LOG("Recognized game '%s'; using dllfile '%s'", gamedll->name, gamedll->file); + } + + return true; +}