Implement Valve game directory detection check to prevent incorrect use of mod dlls
This commit is contained in:
parent
00fb5c4708
commit
ab5735c1cf
5 changed files with 106 additions and 11 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,5 +1,15 @@
|
|||
# Half-Life Updated changelog
|
||||
|
||||
## Changes in V1.0.0 Release Candidate 004
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Disabled GCC optimization that prevents mod dlls from unloading after engine calls dlclose
|
||||
|
||||
### Features
|
||||
|
||||
* Mods made with this SDK will now shut down if they detect they are being run from a Valve game directory (e.g. by placing the dlls in `Half-Life/valve/cl_dlls` and `Half-Life/valve/dlls`). This is not supported and puts users at risk of being VAC banned. Run mods from their intended location only
|
||||
|
||||
## Changes in V1.0.0 Release Candidate 003
|
||||
|
||||
### Bug fixes
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
// this implementation handles the linking of the engine to the DLL
|
||||
//
|
||||
|
||||
#include <SDL2/SDL_messagebox.h>
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "netadr.h"
|
||||
|
@ -108,6 +110,28 @@ void DLLEXPORT HUD_PlayerMove(struct playermove_s* ppmove, int server)
|
|||
PM_Move(ppmove, server);
|
||||
}
|
||||
|
||||
static bool CL_InitClient()
|
||||
{
|
||||
EV_HookEvents();
|
||||
CL_LoadParticleMan();
|
||||
|
||||
if (!FileSystem_LoadFileSystem())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (UTIL_IsValveGameDirectory())
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error",
|
||||
"This mod has detected that it is being run from a Valve game directory which is not supported\n"
|
||||
"Run this mod from its intended location\n\nThe game will now shut down", nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get tracker interface, if any
|
||||
return true;
|
||||
}
|
||||
|
||||
int DLLEXPORT Initialize(cl_enginefunc_t* pEnginefuncs, int iVersion)
|
||||
{
|
||||
gEngfuncs = *pEnginefuncs;
|
||||
|
@ -119,15 +143,15 @@ int DLLEXPORT Initialize(cl_enginefunc_t* pEnginefuncs, int iVersion)
|
|||
|
||||
memcpy(&gEngfuncs, pEnginefuncs, sizeof(cl_enginefunc_t));
|
||||
|
||||
EV_HookEvents();
|
||||
CL_LoadParticleMan();
|
||||
const bool result = CL_InitClient();
|
||||
|
||||
if (!FileSystem_LoadFileSystem())
|
||||
if (!result)
|
||||
{
|
||||
gEngfuncs.Con_DPrintf("Error initializing client\n");
|
||||
gEngfuncs.pfnClientCmd("quit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get tracker interface, if any
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -454,6 +454,23 @@ cvar_t sk_player_leg3 = {"sk_player_leg3", "1"};
|
|||
|
||||
// END Cvars for Skill Level settings
|
||||
|
||||
static bool SV_InitServer()
|
||||
{
|
||||
if (!FileSystem_LoadFileSystem())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (UTIL_IsValveGameDirectory())
|
||||
{
|
||||
g_engfuncs.pfnServerPrint("This mod has detected that it is being run from a Valve game directory which is not supported\n"
|
||||
"Run this mod from its intended location\n\nThe game will now shut down\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Register your console variables here
|
||||
// This gets called one time when the game is initialied
|
||||
void GameDLLInit()
|
||||
|
@ -465,8 +482,9 @@ void GameDLLInit()
|
|||
g_footsteps = CVAR_GET_POINTER("mp_footsteps");
|
||||
g_psv_cheats = CVAR_GET_POINTER("sv_cheats");
|
||||
|
||||
if (!FileSystem_LoadFileSystem())
|
||||
if (!SV_InitServer())
|
||||
{
|
||||
g_engfuncs.pfnServerPrint("Error initializing server\n");
|
||||
//Shut the game down as soon as possible.
|
||||
SERVER_COMMAND("quit\n");
|
||||
return;
|
||||
|
|
|
@ -53,6 +53,7 @@ static CSysModule* g_pFileSystemModule = nullptr;
|
|||
// The engine's filesystem doesn't provide functions to do this so we have to work around it.
|
||||
static std::string g_GameDirectory;
|
||||
static std::string g_ModDirectory;
|
||||
static std::string g_ModDirectoryName;
|
||||
|
||||
static bool FileSystem_InitializeGameDirectory()
|
||||
{
|
||||
|
@ -97,18 +98,17 @@ static bool FileSystem_InitializeGameDirectory()
|
|||
|
||||
gameDirectory.shrink_to_fit();
|
||||
|
||||
std::string modDirectory;
|
||||
modDirectory.resize(BufferSize);
|
||||
g_ModDirectoryName.resize(BufferSize);
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
modDirectory = gEngfuncs.pfnGetGameDirectory();
|
||||
g_ModDirectoryName = gEngfuncs.pfnGetGameDirectory();
|
||||
#else
|
||||
g_engfuncs.pfnGetGameDir(modDirectory.data());
|
||||
modDirectory.resize(std::strlen(modDirectory.c_str()));
|
||||
g_engfuncs.pfnGetGameDir(g_ModDirectoryName.data());
|
||||
g_ModDirectoryName.resize(std::strlen(g_ModDirectoryName.c_str()));
|
||||
#endif
|
||||
|
||||
g_GameDirectory = std::move(gameDirectory);
|
||||
g_ModDirectory = g_GameDirectory + DefaultPathSeparatorChar + modDirectory;
|
||||
g_ModDirectory = g_GameDirectory + DefaultPathSeparatorChar + g_ModDirectoryName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -181,6 +181,11 @@ void FileSystem_FreeFileSystem()
|
|||
}
|
||||
}
|
||||
|
||||
const std::string& FileSystem_GetModDirectoryName()
|
||||
{
|
||||
return g_ModDirectoryName;
|
||||
}
|
||||
|
||||
void FileSystem_FixSlashes(std::string& fileName)
|
||||
{
|
||||
std::replace(fileName.begin(), fileName.end(), AlternatePathSeparatorChar, DefaultPathSeparatorChar);
|
||||
|
@ -310,3 +315,30 @@ bool FileSystem_WriteTextToFile(const char* fileName, const char* text, const ch
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr const char* ValveGameDirectoryPrefixes[] =
|
||||
{
|
||||
"valve",
|
||||
"gearbox",
|
||||
"bshift",
|
||||
"ricochet",
|
||||
"dmc",
|
||||
"cstrike",
|
||||
"czero", // Also covers Deleted Scenes (czeror)
|
||||
"dod",
|
||||
"tfc"};
|
||||
|
||||
bool UTIL_IsValveGameDirectory()
|
||||
{
|
||||
const std::string& modDirectoryName = FileSystem_GetModDirectoryName();
|
||||
|
||||
for (const auto prefix : ValveGameDirectoryPrefixes)
|
||||
{
|
||||
if (strnicmp(modDirectoryName.c_str(), prefix, strlen(prefix)) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,11 @@ inline IFileSystem* g_pFileSystem = nullptr;
|
|||
bool FileSystem_LoadFileSystem();
|
||||
void FileSystem_FreeFileSystem();
|
||||
|
||||
/**
|
||||
* @brief Returns the mod directory name. Only valid to call after calling FileSystem_LoadFileSystem.
|
||||
*/
|
||||
const std::string& FileSystem_GetModDirectoryName();
|
||||
|
||||
/**
|
||||
* @brief Replaces occurrences of ::AlternatePathSeparatorChar with ::DefaultPathSeparatorChar.
|
||||
*/
|
||||
|
@ -102,6 +107,12 @@ std::vector<std::byte> FileSystem_LoadFileIntoBuffer(const char* fileName, FileC
|
|||
*/
|
||||
bool FileSystem_WriteTextToFile(const char* fileName, const char* text, const char* pathID = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Returns @c true if the current game directory is that of a Valve game.
|
||||
* Any directory whose name starts with that of a Valve game's directory name is considered to be one, matching Steam's behavior.
|
||||
*/
|
||||
bool UTIL_IsValveGameDirectory();
|
||||
|
||||
/**
|
||||
* @brief Helper class to automatically close the file handle associated with a file.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue