1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-11-29 11:24:19 +01:00

added the loading changes from the 1.4.3 branch. they're a bit different here but the theory is the same

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40595
This commit is contained in:
David Anderson 2007-12-14 04:32:47 +00:00
parent 59bd50c69d
commit a9c61692e8
13 changed files with 295 additions and 64 deletions

View File

@ -14,6 +14,8 @@
- Added API for getting the VSP-simulation interface upon late loading.
- Added OnUnlinkConCommandBase to IMetamodListner to notify when Metamod:Source
is about to remove a concommand or convar.
- Added the ability for Metamod:Source to load as a VSP instead of through
gameinfo.txt.
- The output of the "meta list" command has been reformatted in order to allow
more space for plugins' name, version, and author fields.

View File

@ -63,7 +63,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(HL2SDKOB)\lib\public\tier0.lib $(HL2SDKOB)\lib\public\tier1.lib $(HL2SDKOB)\lib\public\tier2.lib $(HL2SDKOB)\lib\public\vstdlib.lib"
AdditionalDependencies="&quot;$(HL2SDKOB)\lib\public\tier0.lib&quot; &quot;$(HL2SDKOB)\lib\public\tier1.lib&quot; &quot;$(HL2SDKOB)\lib\public\tier2.lib&quot; &quot;$(HL2SDKOB)\lib\public\vstdlib.lib&quot;"
OutputFile="$(OutDir)/server.dll"
LinkIncremental="2"
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmt.lib"
@ -150,7 +150,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(HL2SDKOB)\lib\public\tier0.lib $(HL2SDKOB)\lib\public\tier1.lib $(HL2SDKOB)\lib\public\tier2.lib $(HL2SDKOB)\lib\public\vstdlib.lib"
AdditionalDependencies="&quot;$(HL2SDKOB)\lib\public\tier0.lib&quot; &quot;$(HL2SDKOB)\lib\public\tier1.lib&quot; &quot;$(HL2SDKOB)\lib\public\tier2.lib&quot; &quot;$(HL2SDKOB)\lib\public\vstdlib.lib&quot;"
OutputFile="$(OutDir)/server.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmtd.lib"

View File

@ -30,6 +30,7 @@
#define DEBUG2
#undef _DEBUG
#endif
#include "../metamod_oslink.h"
#include <sourcehook.h>
#include <convar.h>
#include <eiface.h>
@ -82,11 +83,9 @@ void BaseProvider::ConsolePrint(const char *str)
ConMsg("%s", str);
}
void BaseProvider::Notify_DLLInit_Pre(void *gamedll,
CreateInterfaceFn engineFactory,
void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
CreateInterfaceFn serverFactory)
{
server = (IServerGameDLL *)gamedll;
engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL));
if (!engine)
{
@ -363,6 +362,11 @@ IServerPluginCallbacks *BaseProvider::GetVSPCallbacks(const char *iface)
return &g_VspListener;
}
bool BaseProvider::IsAlternatelyLoaded()
{
return g_VspListener.IsRootLoadMethod();
}
class GlobCommand : public IMetamodSourceCommandInfo
{
public:

View File

@ -60,9 +60,7 @@ public:
virtual void DisplayError(const char *fmt, ...);
virtual void DisplayWarning(const char *fmt, ...);
virtual int TryServerGameDLL(const char *iface);
virtual void Notify_DLLInit_Pre(void *gamedll,
CreateInterfaceFn engineFactory,
CreateInterfaceFn serverFactory);
virtual void Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, CreateInterfaceFn serverFactory);
void Notify_DLLShutdown_Pre();
virtual void ServerCommand(const char *cmd);
virtual ConVar *CreateConVar(const char *name,
@ -79,6 +77,7 @@ public:
virtual int FindUserMessage(const char *name, int *size=NULL);
virtual const char *GetUserMessage(int index, int *size=NULL);
virtual int DetermineSourceEngine(const char *game);
virtual bool IsAlternatelyLoaded();
};
extern IVEngineServer *engine;

View File

@ -25,16 +25,46 @@
* Version: $Id$
*/
#if defined _DEBUG
#define DEBUG2
#undef _DEBUG
#endif
#include "../metamod_oslink.h"
#include <sourcehook.h>
#include <convar.h>
#include <eiface.h>
#include "iplayerinfo.h"
#if defined DEBUG2
#undef DEBUG2
#define _DEBUG
#endif
#include "vsp_listener.h"
#include "svn_version.h"
#include "metamod.h"
#include "provider_ep2.h"
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
using namespace SourceMM;
ConCommand *g_plugin_unload = NULL;
bool g_bIsTryingToUnload;
void InterceptPluginUnloads(const CCommand &args)
{
g_bIsTryingToUnload = true;
}
void InterceptPluginUnloads_Post(const CCommand &args)
{
g_bIsTryingToUnload = false;
}
VSPListener::VSPListener()
{
m_bLoaded = false;
m_bLoadable = false;
m_bIsRootLoadMethod = false;
}
void VSPListener::ClientActive(edict_t *pEntity)
@ -108,6 +138,24 @@ void VSPListener::ServerActivate(edict_t *pEdictList, int edictCount, int client
void VSPListener::Unload()
{
if (g_bIsTryingToUnload)
{
Error("Metamod:Source cannot be unloaded from VSP mode. Use \"meta unload\" to unload specific plugins.\n");
return;
}
if (IsRootLoadMethod())
{
if (g_plugin_unload != NULL)
{
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false);
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true);
g_plugin_unload = NULL;
}
UnloadMetamod();
}
m_bLoaded = false;
m_bLoadable = true;
m_bIsRootLoadMethod = false;
}
void VSPListener::SetLoadable(bool set)
@ -117,15 +165,76 @@ void VSPListener::SetLoadable(bool set)
bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory)
{
if (!m_bLoadable)
if (!g_Metamod.IsLoadedAsGameDLL())
{
provider->DisplayWarning("Do not manually load Metamod:Source as a Valve Server Plugin\n");
return false;
}
CGlobalVars *pGlobals;
IPlayerInfoManager *playerInfoManager;
if (m_bLoaded)
{
return false;
playerInfoManager = (IPlayerInfoManager *)gameServerFactory("PlayerInfoManager002", NULL);
if (playerInfoManager == NULL)
{
Msg("Metamod:Source requires gameinfo.txt modification to load on this game.\n");
return false;
}
pGlobals = playerInfoManager->GetGlobalVars();
char gamedll_iface[] = "ServerGameDLL000";
for (unsigned int i = 5; i <= 50; i++)
{
gamedll_iface[15] = '0' + i;
if ((server = (IServerGameDLL *)gameServerFactory(gamedll_iface, NULL)) != NULL)
{
g_Metamod.SetGameDLLInfo(gameServerFactory, i);
break;
}
}
if (server == NULL)
{
Msg("Metamod:Source could not load (GameDLL version not compatible).\n");
return false;
}
char gameclients_iface[] = "ServerGameClients000";
for (unsigned int i = 3; i <= 4; i++)
{
gameclients_iface[19] = '0' + i;
if ((gameclients = (IServerGameClients *)gameServerFactory(gameclients_iface, NULL)) == NULL)
{
break;
}
}
if (!DetectGameInformation())
{
Msg("Metamod:Source failed to detect game paths; cannot load.\n");
return false;
}
m_bIsRootLoadMethod = true;
m_bLoaded = true;
SetLoadable(false);
InitializeForLoad();
InitializeGlobals(interfaceFactory, interfaceFactory, interfaceFactory, pGlobals);
const ConCommandBase *pBase = icvar->GetCommands();
while (pBase != NULL)
{
if (pBase->IsCommand() && strcmp(pBase->GetName(), "plugin_unload") == 0)
{
g_plugin_unload = (ConCommand *)pBase;
break;
}
pBase = pBase->GetNext();
}
if (g_plugin_unload != NULL)
{
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false);
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true);
}
}
m_bLoaded = true;
@ -139,3 +248,8 @@ bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gam
void VSPListener::OnQueryCvarValueFinished(QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue )
{
}
bool VSPListener::IsRootLoadMethod()
{
return m_bIsRootLoadMethod;
}

View File

@ -63,10 +63,12 @@ public:
virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue );
public:
bool IsLoaded();
bool IsRootLoadMethod();
void SetLoadable(bool loadable);
private:
bool m_bLoaded;
bool m_bLoadable;
bool m_bIsRootLoadMethod;
};
#endif //_INCLUDE_METAMOD_SOURCE_VSP_LISTENER_H_

View File

@ -25,6 +25,7 @@
* Version: $Id$
*/
#include "metamod_oslink.h"
#if defined _DEBUG
#define DEBUG2
#undef _DEBUG
@ -36,7 +37,6 @@
#include "metamod_plugins.h"
#include "metamod_util.h"
#include "metamod_console.h"
#include "metamod_oslink.h"
#if defined DEBUG2
#undef DEBUG2
#define _DEBUG
@ -99,6 +99,7 @@ ISourceHook *g_SHPtr = &g_SourceHook;
PluginId g_PLID = Pl_Console;
META_RES last_meta_res;
IServerPluginCallbacks *vsp_callbacks = NULL;
bool were_plugins_loaded = false;
MetamodSource g_Metamod;
@ -137,7 +138,7 @@ void ClearGamedllList();
}
/* Initialize everything here */
void InitMainStates()
void InitializeForLoad()
{
char full_path[PATH_SIZE] = {0};
GetFileOfAddress((void *)gamedll_info.factory, full_path, sizeof(full_path));
@ -188,6 +189,31 @@ void InitMainStates()
SH_ADD_MANUALHOOK_STATICFUNC(SGD_DLLShutdown, server, Handler_DLLShutdown, false);
}
bool DetectGameInformation()
{
char mm_path[PATH_SIZE];
char game_path[PATH_SIZE];
/* Get path to SourceMM DLL */
if (!GetFileOfAddress((void *)InitializeForLoad, mm_path, sizeof(mm_path)))
{
return false;
}
metamod_path.assign(mm_path);
/* Get value of -game from command line, defaulting to hl2 as engine seems to do */
const char *game_dir = provider->GetCommandLineValue("-game", "hl2");
/* Get absolute path */
abspath(game_path, game_dir);
mod_path.assign(game_path);
engine_build = provider->DetermineSourceEngine(game_dir);;
return true;
}
/* This is where the magic happens */
SMM_API void *CreateInterface(const char *iface, int *ret)
{
@ -221,31 +247,22 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
return vsp_callbacks;
}
if (provider->IsAlternatelyLoaded())
{
IFACE_MACRO(gamedll_info.factory, GameDLL);
}
if (!parsed_game_info)
{
parsed_game_info = true;
const char *game_dir = NULL;
char game_path[PATH_SIZE];
char mm_path[PATH_SIZE];
/* Get path to SourceMM DLL */
if (!GetFileOfAddress((void *)CreateInterface, mm_path, sizeof(mm_path)))
if (!DetectGameInformation())
{
provider->DisplayError("GetFileOfAddress() failed! Metamod cannot load.\n");
return NULL;
}
metamod_path.assign(mm_path);
/* Get value of -game from command line, defaulting to hl2 as engine seems to do */
game_dir = provider->GetCommandLineValue("-game", "hl2");
engine_build = provider->DetermineSourceEngine(game_dir);;
/* Get absolute path */
abspath(game_path, game_dir);
mod_path.assign(game_path);
char temp_path[PATH_SIZE];
/* Path to gameinfo.txt */
@ -331,7 +348,7 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
}
/* If not path to SourceMM... */
if (!UTIL_PathCmp(mm_path, temp_path))
if (!UTIL_PathCmp(metamod_path.c_str(), temp_path))
{
FILE *temp_fp = fopen(temp_path, "rb");
if (!temp_fp)
@ -413,7 +430,7 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
if (is_gamedll_loaded)
{
ClearGamedllList();
InitMainStates();
InitializeForLoad();
}
else
{
@ -603,6 +620,11 @@ int LoadPluginsFromFile(const char *_file)
void InitializeVSP()
{
if (provider->IsAlternatelyLoaded())
{
return;
}
size_t len;
char engine_file[PATH_SIZE];
char engine_path[PATH_SIZE];
@ -675,29 +697,8 @@ void LogMessage(const char *msg, ...)
}
}
bool Handler_DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals)
void DoInitialPluginLoads()
{
engine_factory = engineFactory;
filesystem_factory = filesystemFactory;
physics_factory = physicsFactory;
gpGlobals = pGlobals;
provider->Notify_DLLInit_Pre(server, engineFactory, gamedll_info.factory);
metamod_version = provider->CreateConVar("metamod_version",
SOURCEMM_VERSION,
"Metamod:Source Version",
ConVarFlag_Notify|ConVarFlag_Replicated|ConVarFlag_SpOnly);
mm_pluginsfile = provider->CreateConVar("mm_pluginsfile",
#if defined WIN32 || defined _WIN32
"addons\\metamod\\metaplugins.ini",
#else
"addons/metamod/metaplugins.ini",
#endif
"Metamod:Source Plugins File",
ConVarFlag_SpOnly);
const char *pluginFile = provider->GetCommandLineValue("mm_pluginsfile", NULL);
if (!pluginFile)
{
@ -712,8 +713,47 @@ bool Handler_DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsF
g_Metamod.PathFormat(full_path, sizeof(full_path), "%s/%s", mod_path.c_str(), pluginFile);
LoadPluginsFromFile(full_path);
}
in_first_level = true;
void StartupMetamod(bool bWaitForGameInit)
{
metamod_version = provider->CreateConVar("metamod_version",
SOURCEMM_VERSION,
"Metamod:Source Version",
ConVarFlag_Notify|ConVarFlag_Replicated|ConVarFlag_SpOnly);
mm_pluginsfile = provider->CreateConVar("mm_pluginsfile",
#if defined WIN32 || defined _WIN32
"addons\\metamod\\metaplugins.ini",
#else
"addons/metamod/metaplugins.ini",
#endif
"Metamod:Source Plugins File",
ConVarFlag_SpOnly);
if (!bWaitForGameInit)
{
DoInitialPluginLoads();
in_first_level = true;
}
}
void InitializeGlobals(CreateInterfaceFn engineFactory,
CreateInterfaceFn physicsFactory,
CreateInterfaceFn filesystemFactory,
CGlobalVars *pGlobals)
{
engine_factory = engineFactory;
physics_factory = physicsFactory;
filesystem_factory = filesystemFactory;
gpGlobals = pGlobals;
provider->Notify_DLLInit_Pre(engineFactory, gamedll_info.factory);
}
bool Handler_DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals)
{
InitializeGlobals(engineFactory, physicsFactory, filesystemFactory, pGlobals);
StartupMetamod(false);
RETURN_META_VALUE(MRES_IGNORED, true);
}
@ -730,6 +770,13 @@ bool Handler_GameInit()
InitializeVSP();
}
if (provider->IsAlternatelyLoaded() && !were_plugins_loaded)
{
DoInitialPluginLoads();
g_PluginMngr.SetAllLoaded();
were_plugins_loaded = true;
}
is_game_init = true;
RETURN_META_VALUE(MRES_IGNORED, true);
@ -741,14 +788,17 @@ bool Handler_DLLInit_Post(CreateInterfaceFn engineFactory, CreateInterfaceFn phy
RETURN_META_VALUE(MRES_IGNORED, true);
}
void Handler_DLLShutdown()
void UnloadMetamod()
{
/* Unload plugins */
g_PluginMngr.UnloadAll();
provider->Notify_DLLShutdown_Pre();
SH_CALL(server, &IServerGameDLL::DLLShutdown)();
if (is_gamedll_loaded)
{
SH_CALL(server, &IServerGameDLL::DLLShutdown)();
}
g_SourceHook.CompleteShutdown();
@ -757,12 +807,24 @@ void Handler_DLLShutdown()
dlclose(gamedll_info.lib);
is_gamedll_loaded = false;
}
}
void Handler_DLLShutdown()
{
UnloadMetamod();
RETURN_META(MRES_SUPERCEDE);
}
void Handler_LevelShutdown(void)
{
if (provider->IsAlternatelyLoaded() && !were_plugins_loaded)
{
g_PluginMngr.SetAllLoaded();
DoInitialPluginLoads();
were_plugins_loaded = true;
in_first_level = true;
}
if (!in_first_level)
{
char full_path[255];
@ -1270,3 +1332,19 @@ size_t MetamodSource::FormatArgs(char *buffer, size_t maxlength, const char *for
{
return UTIL_FormatArgs(buffer, maxlength, format, ap);
}
bool MetamodSource::IsLoadedAsGameDLL()
{
return is_gamedll_loaded;
}
void MetamodSource::SetGameDLLInfo(CreateInterfaceFn serverFactory, int version)
{
gamedll_info.factory = serverFactory;
gamedll_version = version;
}
bool MetamodSource::IsAlternateLoadComplete()
{
return were_plugins_loaded;
}

View File

@ -93,14 +93,24 @@ public:
size_t Format(char *buffer, size_t maxlength, const char *format, ...);
size_t FormatArgs(char *buffer, size_t maxlength, const char *format, va_list ap);
public:
bool IsLoadedAsGameDLL();
const char *GetGameBinaryPath();
const char *GetPluginsFile();
void UnregisterConCommandBase(PluginId id, ConCommandBase *pCommand);
void NotifyVSPListening(IServerPluginCallbacks *callbacks);
void SetGameDLLInfo(CreateInterfaceFn serverFactory, int version);
bool IsAlternateLoadComplete();
};
bool DetectGameInformation();
void LogMessage(const char *msg, ...);
int LoadPluginsFromFile(const char *_file);
void InitializeForLoad();
void InitializeGlobals(CreateInterfaceFn engineFactory,
CreateInterfaceFn physicsFactory,
CreateInterfaceFn filesystemFactory,
CGlobalVars *pGlobals);
void UnloadMetamod();
extern MetamodSource g_Metamod;
extern SourceHook::Impl::CSourceHookImpl g_SourceHook;

View File

@ -25,6 +25,7 @@
* Version: $Id$
*/
#include "metamod_oslink.h"
#if defined _DEBUG
#define DEBUG2
#undef _DEBUG
@ -54,6 +55,12 @@ bool Command_Meta(IMetamodSourceCommandInfo *info)
{
unsigned int args = info->GetArgCount();
if (provider->IsAlternatelyLoaded() && !g_Metamod.IsAlternateLoadComplete())
{
CONMSG("You must change the map to activate Metamod:Source.\n");
return true;
}
if (args >= 1)
{
const char *command = info->GetArg(1);

View File

@ -76,7 +76,7 @@
#endif
#if defined __linux__
extern int errno;
#include <errno.h>
int GetLastError();
#endif

View File

@ -25,6 +25,7 @@
* Version: $Id$
*/
#include "metamod_oslink.h"
#if defined _DEBUG
#define DEBUG2
#undef _DEBUG
@ -210,6 +211,11 @@ CPluginManager::CPlugin *CPluginManager::FindById(PluginId id)
void CPluginManager::SetAllLoaded()
{
if (m_AllLoaded)
{
return;
}
m_AllLoaded = true;
PluginIter i;

View File

@ -186,9 +186,7 @@ namespace SourceMM
/**
* @brief Notifies the provider that the DLLInit pre-hook is almost done.
*/
virtual void Notify_DLLInit_Pre(void *gamedll,
CreateInterfaceFn engineFactory,
CreateInterfaceFn serverFactory) =0;
virtual void Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, CreateInterfaceFn serverFactory) =0;
virtual void Notify_DLLShutdown_Pre() =0;
@ -291,6 +289,14 @@ namespace SourceMM
* @return SOURCE_ENGINE constant.
*/
virtual int DetermineSourceEngine(const char *game) =0;
/**
* @brief Returns if the provider has loaded itself through an
* alternate means (that is, not through gameinfo.txt.
*
* @return True if loaded, false otherwise.
*/
virtual bool IsAlternatelyLoaded() =0;
};
};

View File

@ -221,7 +221,10 @@ bool UTIL_PathCmp(const char *path1, const char *path2)
}
/* If we're at a different non-alphanumeric, the next character MUST match */
if (!isalpha(path1[pos1]) && (path1[pos1] != path2[pos2]))
if ((((unsigned)path1[pos1] & 0x80) && path1[pos1] != path2[pos2])
||
!isalpha(path1[pos1]) && (path1[pos1] != path2[pos2])
)
{
return false;
}