1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2025-02-26 19:54:14 +01:00

Merged in changes from trunk to 1.4.1 branch

--HG--
branch : 1.4.1
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/1.4.1%40399
This commit is contained in:
Scott Ehlert 2007-05-16 04:31:54 +00:00
parent 35864f547b
commit ec3ebd7712
6 changed files with 263 additions and 23 deletions

Binary file not shown.

View File

@ -153,6 +153,30 @@ public:
return npos;
}
int find_last_of(const char c, int index = npos) const
{
int len = static_cast<int>(size());
if (len < 1)
return npos;
if (index >= len || index < npos)
return npos;
int i;
if (index == npos)
i = len - 1;
else
i = index;
for (; i>=0; i--)
{
if (v[i] == c)
{
return i;
}
}
return npos;
}
bool is_space(int c) const
{
if (c == '\f' || c == '\n' ||

View File

@ -454,9 +454,33 @@ void CSmmAPI::ClientConPrintf(edict_t *client, const char *fmt, ...)
void CSmmAPI::LoadAsVSP()
{
char command[350];
size_t len;
char engine_file[PATH_SIZE];
char rel_path[PATH_SIZE * 2];
GetFileOfAddress(g_Engine.engine, engine_file, sizeof(engine_file));
/* Chop off the "engine" file part */
len = strlen(engine_file);
for (size_t i = len - 1; i >= 0 && i < len; i--)
{
if (engine_file[i] == '/'
|| engine_file[i] == '\\')
{
engine_file[i] = '\0';
break;
}
}
const char *usepath = g_SmmPath.c_str();
if (UTIL_Relatize(rel_path, sizeof(rel_path), engine_file, g_SmmPath.c_str()))
{
usepath = rel_path;
}
char command[PATH_SIZE * 2];
g_VspListener.SetLoadable(true);
UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", g_SmmPath.c_str());
UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", usepath);
g_Engine.engine->ServerCommand(command);
}
@ -492,6 +516,11 @@ int CSmmAPI::GetGameDLLVersion()
#define MSGCLASS2_SIGLEN 16
#define MSGCLASS2_SIG "\x56\x8B\x74\x24\x2A\x85\xF6\x7C\x2A\x3B\x35\x2A\x2A\x2A\x2A\x7D"
#define MSGCLASS2_OFFS 11
/* Windows frame pointer sig */
#define MSGCLASS3_SIGLEN 18
#define MSGCLASS3_SIG "\x55\x8B\xEC\x51\x89\x2A\x2A\x8B\x2A\x2A\x50\x8B\x0D\x2A\x2A\x2A\x2A\xE8"
#define MSGCLASS3_OFFS 13
#elif defined OS_LINUX
/* No frame pointer sig */
#define MSGCLASS_SIGLEN 14
@ -562,6 +591,14 @@ bool CSmmAPI::CacheUserMessages()
/* Get address of CUserMessages::m_UserMessages */
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
#endif
#ifdef OS_WIN32
} else if (vcmp(vfunc, MSGCLASS3_SIG, MSGCLASS3_SIGLEN)) {
/* Get address of CUserMessages instance */
char **userMsgClass = *reinterpret_cast<char ***>(vfunc + MSGCLASS3_OFFS);
/* Get address of CUserMessages::m_UserMessages */
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
#endif
}
if (dict)

View File

@ -119,15 +119,6 @@ void InitMainStates()
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelShutdown, g_GameDll.pGameDLL, LevelShutdown_handler, true);
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelInit, g_GameDll.pGameDLL, LevelInit_handler, true);
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, GameInit, g_GameDll.pGameDLL, GameInit_handler, false);
if (g_GameDll.pGameClients)
{
SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false);
} else {
/* If IServerGameClients isn't found, this really isn't a fatal error so... */
LogMessage("[META] Warning: Could not find IServerGameClients!");
LogMessage("[META] Warning: The 'meta' command will not be available to clients.");
}
}
bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals)
@ -157,6 +148,15 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
g_GameDllPatch = SH_GET_CALLCLASS(g_GameDll.pGameDLL);
if (g_GameDll.pGameClients)
{
SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false);
} else {
/* If IServerGameClients isn't found, this really isn't a fatal error so... */
LogMessage("[META] Warning: Could not find IServerGameClients!");
LogMessage("[META] Warning: The 'meta' command will not be available to clients.");
}
if (!g_SmmAPI.CacheCmds())
{
LogMessage("[META] Warning: Failed to initialize Con_Printf. Defaulting to Msg().");
@ -373,7 +373,6 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
pInfo->lib = gamedll;
pInfo->loaded = true;
pInfo->pGameDLL = NULL;
pInfo->pGameClients = (IServerGameClients *)((fn)(INTERFACEVERSION_SERVERGAMECLIENTS, NULL));
gamedll_list.push_back(pInfo);
break;
}
@ -446,6 +445,15 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
}
}
/* We use this interface for responding to the meta client command */
if (strncmp(iface, "ServerGameClients", 17) == 0)
{
void *ptr = (g_GameDll.factory)(iface, ret);
g_GameDll.pGameClients = static_cast<IServerGameClients *>(ptr);
return ptr;
}
/* If we got here, there's definitely a GameDLL */
IFACE_MACRO(g_GameDll.factory, GameDLL);
}

View File

@ -239,3 +239,170 @@ size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
return len;
}
inline bool pathchar_isalpha(char a)
{
return (((a & 1<<7) == 0) && isalpha(a));
}
inline bool pathchar_sep(char a)
{
#if defined WIN32
return (a == '/' || a == '\\');
#elif defined __linux__
return (a == '/');
#endif
}
inline bool pathstr_isabsolute(const char *str)
{
#if defined WIN32
return (pathchar_isalpha(str[0])
&& str[1] == ':'
&& pathchar_sep(str[2]));
#elif defined __linux__
return (str[0] == '/');
#endif
}
inline bool pathchar_cmp(char a, char b)
{
#if defined WIN32
if (pathchar_isalpha(a) && pathchar_isalpha(b))
{
return (tolower(a) == tolower(b));
}
/* Either path separator is acceptable */
if (pathchar_sep(a))
{
return pathchar_sep(b);
}
#endif
return (a == b);
}
/**
* @brief Forms a relative path given two absolute paths.
*
* @param buffer Buffer to store relative path in.
* @param maxlength Maximum length of the output buffer.
* @param relTo Destination folder to use as a working directory.
* Final folder name should not be pathchar-terminated.
* @param relFrom Source file or folder to use as a target.
* @return True on success, false on failure.
*/
bool UTIL_Relatize(char buffer[],
size_t maxlength,
const char *relTo,
const char *relFrom)
{
/* We don't allow relative paths in here, force
* the user to resolve these himself!
*/
if (!pathstr_isabsolute(relTo)
|| !pathstr_isabsolute(relFrom))
{
return false;
}
#if defined WIN32
/* Relative paths across drives are not possible */
if (!pathchar_cmp(relTo[0], relFrom[0]))
{
return false;
}
/* Get rid of the drive and semicolon part */
relTo = &relTo[2];
relFrom = &relFrom[2];
#endif
/* Eliminate the common root between the paths */
const char *rootTo = NULL;
const char *rootFrom = NULL;
while (*relTo != '\0' && *relFrom != '\0')
{
/* If we get to a new path sequence, start over */
if (pathchar_sep(*relTo)
&& pathchar_sep(*relFrom))
{
rootTo = relTo;
rootFrom = relFrom;
/* If the paths don't compare, stop looking for a common root */
} else if (!pathchar_cmp(*relTo, *relFrom)) {
break;
}
relTo++;
relFrom++;
}
/* NULLs shouldn't happen! */
if (rootTo == NULL
|| rootFrom == NULL)
{
return false;
}
size_t numLevels = 0;
/* The root case is special!
* Don't count anything from it.
*/
if (*(rootTo + 1) != '\0')
{
/* Search for how many levels we need to go up.
* Since the root pointer points to a '/', we increment
* the initial pointer by one.
*/
while (*rootTo != '\0')
{
if (pathchar_sep(*rootTo))
{
/* Check for an improper trailing slash,
* just to be nice even though the user
* should NOT have done this!
*/
if (*(rootTo + 1) == '\0')
{
break;
}
numLevels++;
}
rootTo++;
}
}
/* Now build the new relative path. */
size_t len, total = 0;
while (numLevels--)
{
len = _snprintf(&buffer[total], maxlength - total, ".." PATH_SEP_STR);
if (len >= maxlength - total)
{
/* Not enough space in the buffer */
return false;
}
total += len;
}
/* Add the absolute path. */
len = _snprintf(&buffer[total], maxlength - total, "%s", &rootFrom[1]);
if (len >= maxlength - total)
{
return false;
}
return true;
}
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params)
{
size_t len = vsnprintf(buffer, maxlength, fmt, params);
if (len >= maxlength)
{
len = maxlength - 1;
buffer[len] = '\0';
}
return len;
}

View File

@ -56,17 +56,21 @@ size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
/**
* @brief Same as vsnprintf except that it ensures the string buffer is null terminated.
*/
inline size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params)
{
size_t len = vsnprintf(buffer, maxlength, fmt, params);
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params);
if (len >= maxlength)
{
len = maxlength - 1;
buffer[len] = '\0';
}
return len;
}
/**
* @brief Forms a relative path given two absolute paths.
*
* @param buffer Buffer to store relative path in.
* @param maxlength Maximum length of the output buffer.
* @param relTo Destination folder to use as a working directory.
* Final folder name should not be pathchar-terminated.
* @param relFrom Source file or folder to use as a target.
* @return True on success, false on failure.
*/
bool UTIL_Relatize(char buffer[],
size_t maxlength,
const char *relTo,
const char *relFrom);
#endif //_INCLUDE_UTIL_H