experimental commit of a new feature

--HG--
branch : sourcemm-1.4.3
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/sourcemm-1.4.3%40586
This commit is contained in:
David Anderson 2007-11-29 00:13:08 +00:00
parent 09b4abab9c
commit 41d6c2c37e
5 changed files with 133 additions and 31 deletions

View File

@ -487,7 +487,7 @@ void CSmmAPI::LoadAsVSP()
void CSmmAPI::EnableVSPListener() void CSmmAPI::EnableVSPListener()
{ {
/* If GameInit already passed and we're not already enabled or loaded, go ahead and LoadAsVSP load */ /* If GameInit already passed and we're not already enabled or loaded, go ahead and LoadAsVSP load */
if (bGameInit && !m_VSP && !g_VspListener.IsLoaded()) if (bGameInit && !m_VSP && !g_VspListener.IsLoaded() && !g_VspListener.IsRootLoadMethod())
{ {
LoadAsVSP(); LoadAsVSP();
} }

View File

@ -19,6 +19,7 @@
#include "CPlugin.h" #include "CPlugin.h"
#include "util.h" #include "util.h"
#include "vsp_listener.h" #include "vsp_listener.h"
#include "iplayerinfo.h"
#include <filesystem.h> #include <filesystem.h>
using namespace SourceMM; using namespace SourceMM;
@ -63,7 +64,7 @@ int g_GameDllVersion = 0;
const char VSPIFACE_001[] = "ISERVERPLUGINCALLBACKS001"; const char VSPIFACE_001[] = "ISERVERPLUGINCALLBACKS001";
const char VSPIFACE_002[] = "ISERVERPLUGINCALLBACKS002"; const char VSPIFACE_002[] = "ISERVERPLUGINCALLBACKS002";
const char GAMEINFO_PATH[] = "|gameinfo_path|"; const char GAMEINFO_PATH[] = "|gameinfo_path|";
IBaseFileSystem *baseFs = NULL; IFileSystem *baseFs = NULL;
void ClearGamedllList(); void ClearGamedllList();
@ -125,14 +126,10 @@ void InitMainStates()
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, GameInit, g_GameDll.pGameDLL, GameInit_handler, false); SH_ADD_HOOK_STATICFUNC(IServerGameDLL, GameInit, g_GameDll.pGameDLL, GameInit_handler, false);
} }
bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals) bool StartupMetamod(CreateInterfaceFn engineFactory)
{ {
g_Engine.engineFactory = engineFactory;
g_Engine.fileSystemFactory = filesystemFactory;
g_Engine.physicsFactory = physicsFactory;
g_Engine.pGlobals = pGlobals;
g_Engine.engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL)); g_Engine.engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL));
if (!g_Engine.engine) if (!g_Engine.engine)
{ {
Error("Could not find IVEngineServer! Metamod cannot load."); Error("Could not find IVEngineServer! Metamod cannot load.");
@ -147,7 +144,6 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
g_Engine.loaded = true; g_Engine.loaded = true;
/* Initialize our console hooks */
ConCommandBaseMgr::OneTimeInit(static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor)); ConCommandBaseMgr::OneTimeInit(static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor));
g_GameDllPatch = SH_GET_CALLCLASS(g_GameDll.pGameDLL); g_GameDllPatch = SH_GET_CALLCLASS(g_GameDll.pGameDLL);
@ -155,7 +151,9 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
if (g_GameDll.pGameClients) if (g_GameDll.pGameClients)
{ {
SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false); SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false);
} else { }
else
{
/* If IServerGameClients isn't found, this really isn't a fatal error so... */ /* If IServerGameClients isn't found, this really isn't a fatal error so... */
LogMessage("[META] Warning: Could not find IServerGameClients!"); LogMessage("[META] Warning: Could not find IServerGameClients!");
LogMessage("[META] Warning: The 'meta' command will not be available to clients."); LogMessage("[META] Warning: The 'meta' command will not be available to clients.");
@ -170,13 +168,13 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
if (!g_SmmAPI.CacheUserMessages()) if (!g_SmmAPI.CacheUserMessages())
{ {
/* Don't know of a mod that has stripped out user messages completely, /* Don't know of a mod that has stripped out user messages completely,
* but perhaps should do something different here? * but perhaps should do something different here?
*/ */
LogMessage("[META] Warning: Failed to get list of user messages."); LogMessage("[META] Warning: Failed to get list of user messages.");
LogMessage("[META] Warning: The 'meta game' command will not display user messages."); LogMessage("[META] Warning: The 'meta game' command will not display user messages.");
} }
baseFs = (IBaseFileSystem *)((filesystemFactory)(BASEFILESYSTEM_INTERFACE_VERSION, NULL)); baseFs = (IFileSystem *)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL));
if (baseFs == NULL) if (baseFs == NULL)
{ {
LogMessage("[META] Failed to find filesystem interface, .vdf files will not be parsed."); LogMessage("[META] Failed to find filesystem interface, .vdf files will not be parsed.");
@ -202,9 +200,90 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
bInFirstLevel = true; bInFirstLevel = true;
return true;
}
bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals)
{
g_Engine.engineFactory = engineFactory;
g_Engine.fileSystemFactory = filesystemFactory;
g_Engine.physicsFactory = physicsFactory;
g_Engine.pGlobals = pGlobals;
StartupMetamod(engineFactory);
RETURN_META_VALUE(MRES_IGNORED, true); RETURN_META_VALUE(MRES_IGNORED, true);
} }
bool AlternatelyLoadMetamod(CreateInterfaceFn ifaceFactory, CreateInterfaceFn serverFactory)
{
g_Engine.engineFactory = ifaceFactory;
g_Engine.fileSystemFactory = ifaceFactory;
g_Engine.physicsFactory = ifaceFactory;
IPlayerInfoManager *playerInfoManager = (IPlayerInfoManager *)serverFactory("PlayerInfoManager002", NULL);
if (playerInfoManager == NULL)
{
Error("Metamod:Source requires gameinfo.txt modification to load on this game.");
return false;
}
g_Engine.pGlobals = playerInfoManager->GetGlobalVars();
/* Now find the server */
g_GameDll.factory = serverFactory;
g_GameDll.lib = NULL;
char gamedll_iface[] = "ServerGameDLL000";
for (unsigned int i = 3; i <= 50; i++)
{
gamedll_iface[15] = '0' + i;
g_GameDll.pGameDLL = (IServerGameDLL *)serverFactory(gamedll_iface, NULL);
if (g_GameDll.pGameDLL != NULL)
{
g_GameDllVersion = i;
break;
}
}
if (g_GameDll.pGameDLL == NULL)
{
Error("Metamod:Source requires gameinfo.txt modification to load on this game.");
return false;
}
char gameclients_iface[] = "ServerGameClients000";
for (unsigned int i = 3; i <= 4; i++)
{
gameclients_iface[19] = '0' + i;
g_GameDll.pGameClients = (IServerGameClients *)serverFactory(gameclients_iface, NULL);
if (g_GameDll.pGameClients != NULL)
{
break;
}
}
char smm_path[PATH_SIZE];
const char *game_dir;
GetFileOfAddress((void *)AlternatelyLoadMetamod, smm_path, sizeof(smm_path));
g_SmmPath.assign(smm_path);
game_dir = CommandLine()->ParmValue("-game", "hl2");
abspath(smm_path, game_dir);
g_ModPath.assign(smm_path);
InitMainStates();
if (!StartupMetamod(ifaceFactory))
{
return false;
}
g_PluginMngr.SetAllLoaded();
return true;
}
bool GameInit_handler() bool GameInit_handler()
{ {
if (bGameInit) if (bGameInit)
@ -212,7 +291,7 @@ bool GameInit_handler()
return true; return true;
} }
if (g_SmmAPI.VSPEnabled()) if (g_SmmAPI.VSPEnabled() && !g_VspListener.IsRootLoadMethod())
{ {
g_SmmAPI.LoadAsVSP(); g_SmmAPI.LoadAsVSP();
} }
@ -234,7 +313,7 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
/* Prevent loading of self as a SourceMM plugin or Valve server plugin :x */ /* Prevent loading of self as a SourceMM plugin or Valve server plugin :x */
if (strcmp(iface, PLAPI_NAME) == 0) if (strcmp(iface, PLAPI_NAME) == 0)
{ {
Warning("Do not try loading Metamod:Source as a SourceMM or Valve server plugin.\n"); Warning("Do not try loading Metamod:Source as a Metamod:Source plugin");
if (ret) if (ret)
{ {
@ -257,6 +336,12 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
return &g_VspListener; return &g_VspListener;
} }
/* If we're a VSP, bypass this by default */
if (g_VspListener.IsRootLoadMethod())
{
IFACE_MACRO(g_GameDll.factory, GameDLL);
}
if (!gParsedGameInfo) if (!gParsedGameInfo)
{ {
gParsedGameInfo = true; gParsedGameInfo = true;
@ -490,7 +575,7 @@ void ClearGamedllList()
gamedll_list.clear(); gamedll_list.clear();
} }
void DLLShutdown_handler() void UnloadMetamod()
{ {
/* Unload plugins */ /* Unload plugins */
g_PluginMngr.UnloadAll(); g_PluginMngr.UnloadAll();
@ -507,9 +592,15 @@ void DLLShutdown_handler()
g_SourceHook.CompleteShutdown(); g_SourceHook.CompleteShutdown();
if (g_GameDll.lib && g_GameDll.loaded) if (g_GameDll.lib && g_GameDll.loaded)
{
dlclose(g_GameDll.lib); dlclose(g_GameDll.lib);
}
memset(&g_GameDll, 0, sizeof(GameDllInfo)); memset(&g_GameDll, 0, sizeof(GameDllInfo));
}
void DLLShutdown_handler()
{
UnloadMetamod();
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
@ -586,7 +677,7 @@ void LookForVDFs(const char *dir)
if ((hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE) if ((hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE)
{ {
DWORD dw = GetLastError(); DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, NULL,
dw, dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

View File

@ -87,6 +87,8 @@ struct EngineInfo
IVEngineServer *engine; IVEngineServer *engine;
}; };
bool AlternatelyLoadMetamod(CreateInterfaceFn ifaceFactory, CreateInterfaceFn serverFactory);
/** @brief Global variable for GameDLL info */ /** @brief Global variable for GameDLL info */
extern GameDllInfo g_GameDll; extern GameDllInfo g_GameDll;
@ -116,6 +118,8 @@ extern int g_GameDllVersion;
extern bool bGameInit; extern bool bGameInit;
void UnloadMetamod();
/** @brief Global CallClass for IServerGameDLL */ /** @brief Global CallClass for IServerGameDLL */
extern SourceHook::CallClass<IServerGameDLL> *g_GameDllPatch; extern SourceHook::CallClass<IServerGameDLL> *g_GameDllPatch;

View File

@ -19,6 +19,7 @@ VSPListener::VSPListener()
{ {
m_Loaded = false; m_Loaded = false;
m_Loadable = false; m_Loadable = false;
m_bIsRootLoadMethod = false;
} }
void VSPListener::ClientActive(edict_t *pEntity) void VSPListener::ClientActive(edict_t *pEntity)
@ -92,6 +93,7 @@ void VSPListener::ServerActivate(edict_t *pEdictList, int edictCount, int client
void VSPListener::Unload() void VSPListener::Unload()
{ {
UnloadMetamod();
} }
void VSPListener::SetLoadable(bool set) void VSPListener::SetLoadable(bool set)
@ -99,27 +101,30 @@ void VSPListener::SetLoadable(bool set)
m_Loadable = set; m_Loadable = set;
} }
bool VSPListener::IsRootLoadMethod()
{
return m_bIsRootLoadMethod;
}
bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory) bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory)
{ {
if (!g_GameDll.loaded)
{
Error("Metamod:Source is not a Valve Server Plugin\n");
return false;
}
if (!m_Loadable)
{
Warning("Do not manually load Metamod:Source as a Valve Server Plugin\n");
return false;
}
if (m_Loaded) if (m_Loaded)
{ {
return false; return false;
} }
if (!m_Loadable && !g_GameDll.loaded)
{
/* New loading mechanism, do a bunch o' stuff! */
m_bIsRootLoadMethod = true;
m_Loaded = true;
SetLoadable(false);
if (!AlternatelyLoadMetamod(interfaceFactory, gameServerFactory))
{
return false;
}
}
m_Loaded = true; m_Loaded = true;
SetLoadable(false); SetLoadable(false);

View File

@ -39,9 +39,11 @@ public:
public: public:
bool IsLoaded(); bool IsLoaded();
void SetLoadable(bool loadable); void SetLoadable(bool loadable);
bool IsRootLoadMethod();
private: private:
bool m_Loaded; bool m_Loaded;
bool m_Loadable; bool m_Loadable;
bool m_bIsRootLoadMethod;
}; };
extern VSPListener g_VspListener; extern VSPListener g_VspListener;