1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-12-01 13:24:25 +01:00

mirrored VDF/VSP fixes from the 1.4.3 branch

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40605
This commit is contained in:
David Anderson 2007-12-24 17:00:22 +00:00
parent 50ac19a53b
commit d58e12d25c
9 changed files with 246 additions and 5 deletions

View File

@ -385,6 +385,11 @@ namespace SourceMM
* loading plugin should use ISmmAPI::GetVSPInfo() before relying on
* this callback.
*
* This callback is never called if Metamod:Source is in VSP mode.
* If in VSP mode, a VSP instance is automatically and always available
* via ISmmAPI::GetVSPInfo(), which should be called anyway (to handle
* late loading cases).
*
* @param iface Interface pointer. If NULL, then the VSP
* listening construct failed to initialize and
* is not available.

View File

@ -8,6 +8,9 @@
instance pointer rather than a callclass pointer.
- Metamod:Source has now received a large internal rewrite to improve coding
standards and to separate internal logic from engine specifics.
- Added ability to load from a VDF file instead of gameinfo.txt.
- Added ability to load MM:S plugins from VDF files.
- Added mm_basedir cvar to specify Metamod's base folder.
- Added API for getting highest supported IServerPluginCallbacks interface
version.
- Added API for detecting the engine version.

View File

@ -43,6 +43,7 @@
#include "console.h"
#include "metamod_console.h"
#include "vsp_listener.h"
#include <filesystem.h>
#if defined DEBUG2
#undef DEBUG2
#define _DEBUG
@ -74,6 +75,7 @@ VSPListener g_VspListener;
BaseProvider g_Ep1Provider;
IMetamodSourceProvider *provider = &g_Ep1Provider;
List<ConCommandBase *> conbases_unreg;
IFileSystem *baseFs = NULL;
ConCommand meta_local_cmd("meta", LocalCommand_Meta, "Metamod:Source control options");
SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &);
@ -106,6 +108,13 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
gameclients = (IServerGameClients *)(serverFactory("ServerGameClients004", NULL));
}
baseFs = (IFileSystem *)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL));
if (baseFs == NULL)
{
::LogMessage("Unable to find \"%s\": .vdf files will not be parsed", FILESYSTEM_INTERFACE_VERSION);
return;
}
RegisterConCommandBase(&meta_local_cmd);
conbases_unreg.push_back(&meta_local_cmd);
@ -154,6 +163,11 @@ const char *BaseProvider::GetConVarString(ConVar *convar)
return convar->GetString();
}
void BaseProvider::SetConVarString(ConVar *convar, const char *str)
{
convar->SetValue(str);
}
bool BaseProvider::IsConCommandBaseACommand(ConCommandBase *pCommand)
{
return pCommand->IsCommand();
@ -367,6 +381,68 @@ bool BaseProvider::IsAlternatelyLoaded()
return g_VspListener.IsRootLoadMethod();
}
bool BaseProvider::ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len)
{
if (baseFs == NULL)
{
return false;
}
KeyValues *pValues;
const char *plugin_file, *p_alias;
pValues = new KeyValues("Metamod Plugin");
if (!pValues->LoadFromFile(baseFs, file))
{
pValues->deleteThis();
return false;
}
if ((plugin_file = pValues->GetString("file", NULL)) == NULL)
{
pValues->deleteThis();
return false;
}
if ((p_alias = pValues->GetString("alias", NULL)) != NULL)
{
UTIL_Format(alias, alias_len, "%s", p_alias);
}
else
{
UTIL_Format(alias, alias_len, "");
}
/* Attempt to find a file extension */
if (UTIL_GetExtension(plugin_file) == NULL)
{
g_pMetamod->PathFormat(path,
path_len,
"%s/%s%s",
g_pMetamod->GetBaseDir(),
plugin_file,
#if defined WIN32 || defined _WIN32
".dll"
#else
"_i486.so"
#endif
);
}
else
{
g_pMetamod->PathFormat(path,
path_len,
"%s/%s",
g_pMetamod->GetBaseDir(),
plugin_file);
}
pValues->deleteThis();
return true;
}
class GlobCommand : public IMetamodSourceCommandInfo
{
public:

View File

@ -68,6 +68,7 @@ public:
const char *help,
int flags);
virtual const char *GetConVarString(ConVar *convar);
virtual void SetConVarString(ConVar *convar, const char *str);
virtual const char *GetGameDescription();
virtual IConCommandBaseAccessor *GetConCommandBaseAccessor();
virtual bool RegisterConCommandBase(ConCommandBase *pCommand);
@ -78,6 +79,7 @@ public:
virtual const char *GetUserMessage(int index, int *size=NULL);
virtual int DetermineSourceEngine(const char *game);
virtual bool IsAlternatelyLoaded();
virtual bool ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len);
};
extern IVEngineServer *engine;

View File

@ -218,6 +218,7 @@ bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gam
InitializeForLoad();
InitializeGlobals(interfaceFactory, interfaceFactory, interfaceFactory, pGlobals);
StartupMetamod(true);
const ConCommandBase *pBase = icvar->GetCommands();
while (pBase != NULL)
@ -240,7 +241,10 @@ bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gam
m_bLoaded = true;
SetLoadable(false);
g_Metamod.NotifyVSPListening(this);
if (!m_bIsRootLoadMethod)
{
g_Metamod.NotifyVSPListening(this);
}
return true;
}

View File

@ -64,6 +64,7 @@ void Handler_LevelShutdown();
bool Handler_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
bool Handler_GameInit();
void InitializeVSP();
void LookForVDFs(const char *dir);
struct game_dll_t
{
@ -88,6 +89,7 @@ bool vsp_loaded = false;
game_dll_t gamedll_info;
ConVar *metamod_version = NULL;
ConVar *mm_pluginsfile = NULL;
ConVar *mm_basedir = NULL;
IServerGameDLL *server = NULL;
CreateInterfaceFn engine_factory = NULL;
CreateInterfaceFn physics_factory = NULL;
@ -102,6 +104,7 @@ IServerPluginCallbacks *vsp_callbacks = NULL;
bool were_plugins_loaded = false;
MetamodSource g_Metamod;
SourceMM::ISmmAPI *g_pMetamod = &g_Metamod;
void ClearGamedllList();
@ -699,6 +702,7 @@ void LogMessage(const char *msg, ...)
void DoInitialPluginLoads()
{
const char *pluginFile = provider->GetCommandLineValue("mm_pluginsfile", NULL);
const char *mmBaseDir = provider->GetCommandLineValue("mm_basedir", NULL);
if (!pluginFile)
{
pluginFile = provider->GetConVarString(mm_pluginsfile);
@ -707,20 +711,41 @@ void DoInitialPluginLoads()
pluginFile = "addons/metamod/metaplugins.ini";
}
}
if (!mmBaseDir)
{
mmBaseDir = provider->GetConVarString(mm_basedir);
if (mmBaseDir == NULL)
{
mmBaseDir = "addons/metamod";
}
}
char full_path[260];
g_Metamod.PathFormat(full_path, sizeof(full_path), "%s/%s", mod_path.c_str(), pluginFile);
g_Metamod.PathFormat(full_path, sizeof(full_path), "%s/%s", mod_path.c_str(), pluginFile);
LoadPluginsFromFile(full_path);
g_Metamod.PathFormat(full_path, sizeof(full_path), "%s/%s", mod_path.c_str(), mmBaseDir);
LookForVDFs(full_path);
}
void StartupMetamod(bool bWaitForGameInit)
void StartupMetamod(bool is_vsp_load)
{
char buffer[255];
UTIL_Format(buffer,
sizeof(buffer),
"%s%s",
SOURCEMM_VERSION,
is_vsp_load ? "V" : "");
metamod_version = provider->CreateConVar("metamod_version",
SOURCEMM_VERSION,
"Metamod:Source Version",
ConVarFlag_Notify|ConVarFlag_Replicated|ConVarFlag_SpOnly);
provider->SetConVarString(metamod_version, buffer);
mm_pluginsfile = provider->CreateConVar("mm_pluginsfile",
#if defined WIN32 || defined _WIN32
"addons\\metamod\\metaplugins.ini",
@ -730,7 +755,16 @@ void StartupMetamod(bool bWaitForGameInit)
"Metamod:Source Plugins File",
ConVarFlag_SpOnly);
if (!bWaitForGameInit)
mm_basedir = provider->CreateConVar("mm_basedir",
#if defined __linux__
"addons/metamod",
#else
"addons\\metamod",
#endif
"Metamod:Source Base Folder",
ConVarFlag_SpOnly);
if (!is_vsp_load)
{
DoInitialPluginLoads();
in_first_level = true;
@ -827,13 +861,20 @@ void Handler_LevelShutdown(void)
if (!in_first_level)
{
char full_path[255];
g_Metamod.PathFormat(full_path,
sizeof(full_path),
"%s/%s",
mod_path.c_str(),
provider->GetConVarString(mm_pluginsfile));
LoadPluginsFromFile(full_path);
g_Metamod.PathFormat(full_path,
sizeof(full_path),
"%s/%s",
mod_path.c_str(),
provider->GetConVarString(mm_basedir));
LookForVDFs(full_path);
}
else
{
@ -1347,3 +1388,95 @@ bool MetamodSource::IsAlternateLoadComplete()
{
return were_plugins_loaded;
}
void ProcessVDF(const char *path)
{
PluginId id;
bool already;
char alias[24], file[255], error[255];
if (!provider->ProcessVDF(path, file, sizeof(file), alias, sizeof(alias)))
{
return;
}
if (alias[0] != '\0')
{
g_PluginMngr.SetAlias(alias, file);
}
id = g_PluginMngr.Load(file, Pl_File, already, error, sizeof(error));
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
{
LogMessage("[META] Failed to load plugin %s: %s", file, error);
}
}
void LookForVDFs(const char *dir)
{
char path[MAX_PATH];
#if defined _MSC_VER
HANDLE hFind;
WIN32_FIND_DATA fd;
char error[255];
g_Metamod.PathFormat(path, sizeof(path), "%s\\*.*", dir);
if ((hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE)
{
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
error,
sizeof(error),
NULL);
LogMessage("[META] Could not open folder \"%s\" (%s)", dir, error);
return;
}
do
{
if (strcmp(fd.cFileName, ".") == 0
|| strcmp(fd.cFileName, "..") == 0)
{
continue;
}
if (strstr(fd.cFileName, ".vdf") == NULL)
{
continue;
}
g_Metamod.PathFormat(path, sizeof(path), "%s\\%s", dir, fd.cFileName);
ProcessVDF(path);
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
#else
DIR *pDir;
struct dirent *pEnt;
if ((pDir = opendir(dir)) == NULL)
{
LogMessage("[META] Could not open folder \"%s\" (%s)", dir, strerror(errno));
return;
}
while ((pEnt = readdir(pDir)) != NULL)
{
if (strcmp(pEnt->d_name, ".") == 0
|| strcmp(pEnt->d_name, "..") == 0)
{
continue;
}
if (strstr(pEnt->d_name, ".vdf") == NULL)
{
continue;
}
g_SmmAPI.PathFormat(path, sizeof(path), "%s/%s", dir, pEnt->d_name);
ProcessVDF(path);
}
closedir(pDir);
#endif
}

View File

@ -110,6 +110,7 @@ void InitializeGlobals(CreateInterfaceFn engineFactory,
CreateInterfaceFn physicsFactory,
CreateInterfaceFn filesystemFactory,
CGlobalVars *pGlobals);
void StartupMetamod(bool is_vsp_load);
void UnloadMetamod();
extern MetamodSource g_Metamod;

View File

@ -219,6 +219,14 @@ namespace SourceMM
*/
virtual const char *GetConVarString(ConVar *convar) =0;
/**
* @brief Sets a ConVar string.
*
* @param convar ConVar pointer.
* @param str String pointer.
*/
virtual void SetConVarString(ConVar *convar, const char *str) =0;
/**
* @brief Retrieves the game description.
*
@ -297,12 +305,19 @@ namespace SourceMM
* @return True if loaded, false otherwise.
*/
virtual bool IsAlternatelyLoaded() =0;
/**
* @brief Processes a VDF plugin file.
*
*/
virtual bool ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len) =0;
};
};
extern PluginId g_PLID;
extern SourceHook::ISourceHook *g_SHPtr;
extern SourceMM::IMetamodSourceProvider *provider;
extern SourceMM::ISmmAPI *g_pMetamod;
#endif //_INCLUDE_METAMOD_SOURCE_SUPPORT_H_

View File

@ -95,4 +95,6 @@ bool UTIL_Relatize(char buffer[],
const char *relTo,
const char *relFrom);
void LogMessage(const char *msg, ...);
#endif //_INCLUDE_UTIL_H