2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-01-14 07:38:16 +03:00

Fix compilation

This commit is contained in:
s1lentq 2016-07-26 09:08:43 +07:00
parent d0c18ee2d7
commit 1294178a8d
38 changed files with 1687 additions and 2045 deletions

View File

@ -4,6 +4,7 @@ import org.apache.velocity.Template
import org.apache.velocity.VelocityContext
import org.apache.velocity.app.Velocity
import org.joda.time.format.DateTimeFormat
import versioning.MetamodVersionInfo
class VelocityUtils {
@ -19,15 +20,28 @@ class VelocityUtils {
Velocity.init(p);
}
static String renderTemplate(File tplFile, Map<String, ? extends Object> ctx) {
static String renderTemplate(File tplFile, MetamodVersionInfo ctx) {
Template tpl = Velocity.getTemplate(tplFile.absolutePath)
if (!tpl) {
throw new RuntimeException("Failed to load velocity template ${tplFile.absolutePath}: not found")
}
def templateCtx = [
verInfo: ctx
]
def velocityContext = new VelocityContext(ctx)
def velocityContext = new VelocityContext(templateCtx)
if (ctx.specialVersion.length() > 0) {
velocityContext.put("appFlags", 0x0L)
velocityContext.put("formatSpecialVersion", "-" + ctx.specialVersion)
} else {
velocityContext.put("appFlags", "VS_FF_SPECIALBUILD")
velocityContext.put("formatSpecialVersion", "")
}
velocityContext.put("current_version", ctx.asVersion())
velocityContext.put("_DateTimeFormat", DateTimeFormat)
def sw = new StringWriter()

View File

@ -1,3 +1,3 @@
majorVersion=0
minorVersion=1
majorVersion=1
minorVersion=3
specialVersion=

View File

@ -45,21 +45,22 @@ void setupToolchain(NativeBinarySpec b)
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'precompiled.h',
pchSourceSet: 'metamod_pch'
pchSourceSet: 'rmod_pch'
)
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF', '/GR-', '/GS-'
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
} else if (cfg instanceof GccToolchainConfig) {
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'metamod_pch'
pchSourceSet: 'rmod_pch'
)
cfg.compilerOptions.languageStandard = 'c++0x'
cfg.defines([
'_stricmp': 'strcasecmp',
'_strnicmp': 'strncasecmp',
'_strdup': 'strdup',
'_unlink': 'unlink',
'_vsnprintf': 'vsnprintf',
'_snprintf': 'snprintf'
'_vsnwprintf' : 'vswprintf',
])
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-msse2', '-fomit-frame-pointer', '-inline-forceinline', '-fvisibility=default', '-fvisibility-inlines-hidden', '-fno-rtti', '-g0', '-s'
@ -97,7 +98,7 @@ model {
baseName GradleCppUtils.windows ? 'metamod_mm' : 'metamod_mm_i386'
sources {
metamod_pch(CppSourceSet) {
rmod_pch(CppSourceSet) {
source {
srcDirs "src"
include "precompiled.cpp"
@ -107,11 +108,18 @@ model {
srcDirs "include"
}
}
metamod_src(CppSourceSet) {
rmod_src(CppSourceSet) {
source {
srcDir "src"
srcDir "version"
include "**/*.cpp"
if (GradleCppUtils.windows) {
exclude "osdep_linkent_linux.cpp"
} else {
exclude "osdep_linkent_win32.cpp"
}
exclude "precompiled.cpp"
}
@ -121,7 +129,7 @@ model {
}
rc {
source {
srcDir "msvc"
srcDirs "msvc"
include "metamod.rc"
}
exportedHeaders {
@ -170,11 +178,7 @@ task generateAppVersion {
inputs.property('lastCommitDate', verInfo.lastCommitDate.toString())
doLast {
def templateCtx = [
verInfo: verInfo
]
def content = VelocityUtils.renderTemplate(tplFile, templateCtx)
def content = VelocityUtils.renderTemplate(tplFile, verInfo)
renderedFile.delete()
renderedFile.write(content, 'utf-8')

View File

@ -60,9 +60,10 @@
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<ModuleDefinitionFile>metamod.def</ModuleDefinitionFile>
@ -95,11 +96,13 @@
<AdditionalIncludeDirectories>$(ProjectDir)\..\;$(ProjectDir)\..\src;$(ProjectDir)\..\version;$(ProjectDir)\..\include;$(ProjectDir)\..\include\common;$(ProjectDir)\..\include\dlls;$(ProjectDir)\..\include\engine;$(ProjectDir)\..\include\game_shared;$(ProjectDir)\..\include\pm_shared;$(ProjectDir)\..\include\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;METAMOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;__METAMOD_BUILD__;__BUILD_FAST_METAMOD__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader />
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<Optimization>Full</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -108,6 +111,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>metamod.def</ModuleDefinitionFile>
</Link>
<CustomBuildStep>
<Command>echo Empty Action</Command>
@ -212,6 +216,7 @@
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\reg_support.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>

View File

@ -1,108 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
#include "..\version\appversion.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
#ifdef _WIN32
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1251)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
VS_VERSION_INFO VERSIONINFO
FILEVERSION APP_VERSION_C
PRODUCTVERSION APP_VERSION_C
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS (APP_VERSION_FLAGS | VS_FF_DEBUG)
#else
FILEFLAGS (APP_VERSION_FLAGS)
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "041904b0"
BEGIN
VALUE "CompanyName", ""
VALUE "FileDescription", "AMX Mod X module, using API regamedll & rehlds"
VALUE "FileVersion", APP_VERSION_STRD_RC
VALUE "InternalName", "Reapi"
VALUE "LegalCopyright", ""
VALUE "OriginalFilename", "reapi_amxx.dll"
VALUE "ProductName", "Reapi"
VALUE "ProductVersion", APP_VERSION_STRD_RC
#if APP_VERSION_FLAGS != 0x0L
VALUE "SpecialBuild", APP_VERSION_SPECIALBUILD
#endif
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x419, 1200
END
END
#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -1,13 +1,13 @@
#include "precompiled.h"
// getting pointer with table index is faster than with if-else
static const void ** api_tables[3] = {
const void **api_tables[3] = {
(const void **)&Engine.funcs,
(const void **)&GameDLL.funcs.dllapi_table,
(const void **)&GameDLL.funcs.newapi_table
};
static const void ** api_info_tables[3] = {
const void **api_info_tables[3] = {
(const void **)&engine_info,
(const void **)&dllapi_info,
(const void **)&newapi_info
@ -19,7 +19,7 @@ static const void ** api_info_tables[3] = {
// metamod assumed that PublicMetaGlobals is free to be used.
// With call_count we can fix this by backuping up PublicMetaGlobals if
// it's already being used.
static unsigned int call_count = 0;
unsigned int call_count = 0;
// get function pointer from api table by function pointer offset
inline void *get_api_function(const void * api_table, unsigned int func_offset)
@ -44,6 +44,7 @@ void main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsig
int loglevel;
const void *api_table;
meta_globals_t backup_meta_globals[1];
// passing offset from api wrapper function makes code faster/smaller
api_info = get_api_info(api, api_info_offset);
@ -53,6 +54,7 @@ void main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsig
// Backup PublicMetaGlobals.
backup_meta_globals[0] = PublicMetaGlobals;
}
// Setup
loglevel=api_info->loglevel;
mres = MRES_UNSET;
@ -73,30 +75,39 @@ void main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsig
// plugin doesn't provide this api table
continue;
}
pfn_routine = get_api_function(api_table, func_offset);
if (!pfn_routine)
{
// plugin doesn't provide this function
continue;
}
// initialize PublicMetaGlobals
PublicMetaGlobals.mres = MRES_UNSET;
PublicMetaGlobals.prev_mres = prev_mres;
PublicMetaGlobals.status = status;
// call plugin
META_DEBUG(loglevel, ("Calling %s:%s()", iplug->file, api_info->name));
api_info->api_caller(pfn_routine, packed_args);
API_UNPAUSE_TSC_TRACKING();
// plugin's result code
mres = PublicMetaGlobals.mres;
if (mres > status)
status = mres;
// save this for successive plugins to see
prev_mres = mres;
if (mres == MRES_UNSET)
{
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
}
}
call_count--;
// Api call
if (status != MRES_SUPERCEDE)
{
@ -106,43 +117,56 @@ void main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsig
if (api_table)
{
pfn_routine = get_api_function(api_table, func_offset);
if (pfn_routine) {
if (pfn_routine)
{
META_DEBUG(loglevel, ("Calling %s:%s()", (api == e_api_engine) ? "engine" : GameDLL.file, api_info->name));
api_info->api_caller(pfn_routine, packed_args);
API_UNPAUSE_TSC_TRACKING();
} else {
}
else
{
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
if (api != e_api_newapi)
{
META_WARNING("Couldn't find api call: %s:%s", (api==e_api_engine) ? "engine" : GameDLL.file, api_info->name);
}
status = MRES_UNSET;
}
} else {
}
else
{
// don't complain for NULL NEW_DLL_FUNCTIONS-table
if (api != e_api_newapi)
{
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api == e_api_engine) ? "engine" : GameDLL.file, api_info->name));
}
status = MRES_UNSET;
}
} else
}
else
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api == e_api_engine) ? "engine" : GameDLL.file, api_info->name));
call_count++;
// Post plugin functions
prev_mres = MRES_UNSET;
for (i=0; i < Plugins->endlist; i++) {
for (i = 0; i < Plugins->endlist; i++)
{
iplug=&Plugins->plist[i];
if (iplug->status != PL_RUNNING)
continue;
api_table = iplug->get_api_post_table(api);
if (!api_table) {
if (!api_table)
{
// plugin doesn't provide this api table
continue;
}
pfn_routine = get_api_function(api_table, func_offset);
if (!pfn_routine) {
if (!pfn_routine)
{
// plugin doesn't provide this function
continue;
}
@ -171,14 +195,16 @@ void main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsig
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
}
if (--call_count>0) {
if (--call_count>0)
{
// Restore backup
PublicMetaGlobals = backup_meta_globals[0];
}
}
// full return typed version of main hook function
void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args) {
void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void *packed_args)
{
const api_info_t *api_info;
int i;
META_RES mres, status, prev_mres;
@ -192,7 +218,8 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
api_info = get_api_info(api, api_info_offset);
// Fix bug with metamod-bot-plugins.
if (call_count++>0) {
if (call_count++ > 0)
{
// Backup PublicMetaGlobals.
backup_meta_globals[0] = PublicMetaGlobals;
}
@ -209,24 +236,27 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
mres = MRES_UNSET;
status = MRES_UNSET;
prev_mres = MRES_UNSET;
pfn_routine=NULL;
pfn_routine = nullptr;
//Pre plugin functions
prev_mres = MRES_UNSET;
for (i=0; i < Plugins->endlist; i++) {
for (i = 0; i < Plugins->endlist; i++)
{
iplug = &Plugins->plist[i];
if (iplug->status != PL_RUNNING)
continue;
api_table = iplug->get_api_table(api);
if (!api_table) {
if (!api_table)
{
// plugin doesn't provide this api table
continue;
}
pfn_routine = get_api_function(api_table, func_offset);
if (!pfn_routine) {
if (!pfn_routine)
{
// plugin doesn't provide this function
continue;
}
@ -237,7 +267,8 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
PublicMetaGlobals.status = status;
pub_orig_ret = orig_ret;
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
if (status==MRES_SUPERCEDE) {
if (status == MRES_SUPERCEDE)
{
pub_override_ret = override_ret;
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
}
@ -255,11 +286,13 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
// save this for successive plugins to see
prev_mres = mres;
if (mres==MRES_SUPERCEDE) {
if (mres == MRES_SUPERCEDE)
{
pub_override_ret = dllret;
override_ret = dllret;
}
else if (mres==MRES_UNSET) {
else if (mres == MRES_UNSET)
{
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
}
}
@ -267,30 +300,41 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
call_count--;
// Api call
if (status != MRES_SUPERCEDE) {
if (status != MRES_SUPERCEDE)
{
// get api table
api_table = *api_tables[api];
if (api_table) {
if (api_table)
{
pfn_routine = get_api_function(api_table, func_offset);
if (pfn_routine) {
if (pfn_routine)
{
META_DEBUG(loglevel, ("Calling %s:%s()", (api == e_api_engine) ? "engine" : GameDLL.file, api_info->name));
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
API_UNPAUSE_TSC_TRACKING();
orig_ret = dllret;
} else {
}
else
{
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
if (api != e_api_newapi)
{
META_WARNING("Couldn't find api call: %s:%s", (api == e_api_engine) ? "engine" : GameDLL.file, api_info->name);
}
status = MRES_UNSET;
}
} else {
// don't complain for NULL NEW_DLL_FUNCTIONS-table
if (api != e_api_newapi)
{
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api==e_api_engine) ? "engine" : GameDLL.file, api_info->name));
}
status = MRES_UNSET;
}
} else {
}
else
{
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api == e_api_engine) ? "engine" : GameDLL.file, api_info->name));
orig_ret = override_ret;
pub_orig_ret = override_ret;
@ -301,20 +345,23 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
// Pre plugin functions
prev_mres = MRES_UNSET;
for (i=0; i < Plugins->endlist; i++) {
for (i = 0; i < Plugins->endlist; i++)
{
iplug = &Plugins->plist[i];
if (iplug->status != PL_RUNNING)
continue;
api_table = iplug->get_api_post_table(api);
if (!api_table) {
if (!api_table)
{
//plugin doesn't provide this api table
continue;
}
pfn_routine = get_api_function(api_table, func_offset);
if (!pfn_routine) {
if (!pfn_routine)
{
// plugin doesn't provide this function
continue;
}
@ -324,8 +371,10 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
PublicMetaGlobals.prev_mres = prev_mres;
PublicMetaGlobals.status = status;
pub_orig_ret = orig_ret;
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
if (status==MRES_OVERRIDE) {
if (status == MRES_OVERRIDE)
{
pub_override_ret = override_ret;
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
}
@ -343,27 +392,34 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
// save this for successive plugins to see
prev_mres = mres;
if (mres==MRES_OVERRIDE) {
if (mres == MRES_OVERRIDE)
{
pub_override_ret = dllret;
override_ret = dllret;
}
else if (mres==MRES_UNSET) {
else if (mres == MRES_UNSET)
{
META_WARNING("Plugin didn't set meta_result: %s:%s_Post()", iplug->file, api_info->name);
}
else if (mres==MRES_SUPERCEDE) {
else if (mres == MRES_SUPERCEDE)
{
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
}
}
if (--call_count>0) {
if (--call_count > 0)
{
// Restore backup
PublicMetaGlobals = backup_meta_globals[0];
}
// return value is passed through ret_init!
if (status != MRES_OVERRIDE) {
if (status != MRES_OVERRIDE)
{
return *(void**)orig_ret.getptr();
} else {
}
else
{
META_DEBUG(loglevel, ("Returning (override) %s()", api_info->name));
return *(void**)override_ret.getptr();
}
@ -372,7 +428,7 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
// Macros for creating api caller functions
#define BEGIN_API_CALLER_FUNC(ret_type, args_type_code) \
void *_COMBINE4(api_caller_, ret_type, _args_, args_type_code)(const void * func, const void * packed_args) { \
_COMBINE2(pack_args_type_, args_type_code) * p ATTRIBUTE(unused)= (_COMBINE2(pack_args_type_, args_type_code) *)packed_args;
_COMBINE2(pack_args_type_, args_type_code) *p UNUSED = (_COMBINE2(pack_args_type_, args_type_code) *)packed_args;
#define END_API_CALLER_FUNC(ret_t, args_t, args) \
API_PAUSE_TSC_TRACKING(); \
return *(void **)class_ret_t((*((ret_t (*) args_t)func)) args).getptr(); \
@ -384,15 +440,12 @@ void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offse
// API function callers.
//-
BEGIN_API_CALLER_FUNC(void, ipV)
END_API_CALLER_FUNC_void((int, const void *, ...), (p->i1, p->p1, p->str))
//-
BEGIN_API_CALLER_FUNC(void, 2pV)
END_API_CALLER_FUNC_void((const void *, const void *, ...), (p->p1, p->p2, p->str))
//-
BEGIN_API_CALLER_FUNC(void, void)
END_API_CALLER_FUNC_void((), ())
@ -405,26 +458,21 @@ END_API_CALLER_FUNC(int, (), ())
BEGIN_API_CALLER_FUNC(float, void)
END_API_CALLER_FUNC(float, (), ())
//-
BEGIN_API_CALLER_FUNC(float, 2f)
END_API_CALLER_FUNC(float, (float, float), (p->f1, p->f2))
//-
BEGIN_API_CALLER_FUNC(void, 2i)
END_API_CALLER_FUNC_void((int, int), (p->i1, p->i2));
BEGIN_API_CALLER_FUNC(int, 2i)
END_API_CALLER_FUNC(int, (int, int), (p->i1, p->i2));
//-
BEGIN_API_CALLER_FUNC(void, 2i2p)
END_API_CALLER_FUNC_void((int, int, const void *, const void *), (p->i1, p->i2, p->p1, p->p2));
//-
BEGIN_API_CALLER_FUNC(void, 2i2pi2p)
END_API_CALLER_FUNC_void((int, int, const void *, const void *, int, const void *, const void *), (p->i1, p->i2, p->p1, p->p2, p->i3, p->p3, p->p4));
//-
BEGIN_API_CALLER_FUNC(void, 2p)
END_API_CALLER_FUNC_void((const void *, const void *), (p->p1, p->p2));
@ -434,50 +482,39 @@ END_API_CALLER_FUNC(void*, (const void*, const void*), (p->p1, p->p2));
BEGIN_API_CALLER_FUNC(int, 2p)
END_API_CALLER_FUNC(int, (const void *, const void *), (p->p1, p->p2));
//-
BEGIN_API_CALLER_FUNC(void, 2p2f)
END_API_CALLER_FUNC_void((const void *, const void *, float, float), (p->p1, p->p2, p->f1, p->f2));
//-
BEGIN_API_CALLER_FUNC(void, 2p2i2p)
END_API_CALLER_FUNC_void((const void *, const void *, int, int, const void *, const void *), (p->p1, p->p2, p->i1, p->i2, p->p3, p->p4));
//-
BEGIN_API_CALLER_FUNC(void, 2p3fus2uc)
END_API_CALLER_FUNC_void((const void *, const void *, float, float, float, unsigned short, unsigned char, unsigned char), (p->p1, p->p2, p->f1, p->f2, p->f3, p->us1, p->uc1, p->uc2));
//-
BEGIN_API_CALLER_FUNC(ptr, 2pf)
END_API_CALLER_FUNC(void*, (const void *, const void *, float), (p->p1, p->p2, p->f1));
//-
BEGIN_API_CALLER_FUNC(void, 2pfi)
END_API_CALLER_FUNC_void((const void *, const void *, float, int), (p->p1, p->p2, p->f1, p->i1));
//-
BEGIN_API_CALLER_FUNC(void, 2pi)
END_API_CALLER_FUNC_void((const void *, const void *, int), (p->p1, p->p2, p->i1));
BEGIN_API_CALLER_FUNC(int, 2pi)
END_API_CALLER_FUNC(int, (const void *, const void *, int), (p->p1, p->p2, p->i1));
//-
BEGIN_API_CALLER_FUNC(void, 2pui)
END_API_CALLER_FUNC_void((const void *, const void *, unsigned int), (p->p1, p->p2, p->ui1));
//-
BEGIN_API_CALLER_FUNC(void, 2pi2p)
END_API_CALLER_FUNC_void((const void *, const void *, int, const void *, const void *), (p->p1, p->p2, p->i1, p->p3, p->p4));
//-
BEGIN_API_CALLER_FUNC(void, 2pif2p)
END_API_CALLER_FUNC_void((const void *, const void *, int, float, const void *, const void *), (p->p1, p->p2, p->i1, p->f1, p->p3, p->p4));
//-
BEGIN_API_CALLER_FUNC(int, 3i)
END_API_CALLER_FUNC(int, (int, int, int), (p->i1, p->i2, p->i3));
//-
BEGIN_API_CALLER_FUNC(void, 3p)
END_API_CALLER_FUNC_void((const void *, const void *, const void *), (p->p1, p->p2, p->p3));
@ -487,33 +524,27 @@ END_API_CALLER_FUNC(void*, (const void*, const void*, const void*), (p->p1, p->p
BEGIN_API_CALLER_FUNC(int, 3p)
END_API_CALLER_FUNC(int, (const void *, const void *, const void *), (p->p1, p->p2, p->p3));
//-
BEGIN_API_CALLER_FUNC(void, 3p2f2i)
END_API_CALLER_FUNC_void((const void *, const void *, const void *, float, float, int, int), (p->p1, p->p2, p->p3, p->f1, p->f2, p->i1, p->i2));
//-
BEGIN_API_CALLER_FUNC(int, 3pi2p)
END_API_CALLER_FUNC(int, (const void *, const void *, const void *, int, const void *, const void *), (p->p1, p->p2, p->p3, p->i1, p->p4, p->p5));
//-
BEGIN_API_CALLER_FUNC(void, 4p)
END_API_CALLER_FUNC_void((const void *, const void *, const void *, const void *), (p->p1, p->p2, p->p3, p->p4));
BEGIN_API_CALLER_FUNC(int, 4p)
END_API_CALLER_FUNC(int, (const void *, const void *, const void *, const void *), (p->p1, p->p2, p->p3, p->p4));
//-
BEGIN_API_CALLER_FUNC(void, 4pi)
END_API_CALLER_FUNC_void((const void *, const void *, const void *, const void *, int), (p->p1, p->p2, p->p3, p->p4, p->i1));
BEGIN_API_CALLER_FUNC(int, 4pi)
END_API_CALLER_FUNC(int, (const void *, const void *, const void *, const void *, int), (p->p1, p->p2, p->p3, p->p4, p->i1));
//-
BEGIN_API_CALLER_FUNC(void, f)
END_API_CALLER_FUNC_void((float), (p->f1));
//-
BEGIN_API_CALLER_FUNC(void, i)
END_API_CALLER_FUNC_void((int), (p->i1));
@ -529,22 +560,18 @@ END_API_CALLER_FUNC(unsigned int, (unsigned int), (p->ui1));
BEGIN_API_CALLER_FUNC(ptr, ui)
END_API_CALLER_FUNC(void*, (unsigned int), (p->ui1));
//-
BEGIN_API_CALLER_FUNC(ulong, ul)
END_API_CALLER_FUNC(unsigned long, (unsigned long), (p->ul1));
//-
BEGIN_API_CALLER_FUNC(void, i2p)
END_API_CALLER_FUNC_void((int, const void *, const void *), (p->i1, p->p1, p->p2));
BEGIN_API_CALLER_FUNC(int, i2p)
END_API_CALLER_FUNC(int, (int, const void *, const void *), (p->i1, p->p1, p->p2));
//-
BEGIN_API_CALLER_FUNC(void, i3p)
END_API_CALLER_FUNC_void((int, const void *, const void *, const void *), (p->i1, p->p1, p->p2, p->p3));
//-
BEGIN_API_CALLER_FUNC(void, ip)
END_API_CALLER_FUNC_void((int, const void *), (p->i1, p->p1));
@ -554,11 +581,9 @@ END_API_CALLER_FUNC(unsigned short, (int, const void*), (p->i1, p->p1));
BEGIN_API_CALLER_FUNC(int, ip)
END_API_CALLER_FUNC(int, (int, const void *), (p->i1, p->p1));
//-
BEGIN_API_CALLER_FUNC(void, ipusf2p2f4i)
END_API_CALLER_FUNC_void((int, const void *, unsigned short, float, const void *, const void *, float, float, int, int, int, int), (p->i1, p->p1, p->us1, p->f1, p->p2, p->p3, p->f2, p->f3, p->i2, p->i3, p->i4, p->i5));
//-
BEGIN_API_CALLER_FUNC(void, p)
END_API_CALLER_FUNC_void((const void *), (p->p1));
@ -577,39 +602,30 @@ END_API_CALLER_FUNC(unsigned int, (const void*), (p->p1));
BEGIN_API_CALLER_FUNC(float, p)
END_API_CALLER_FUNC(float, (const void *), (p->p1));
//-
BEGIN_API_CALLER_FUNC(void, p2f)
END_API_CALLER_FUNC_void((const void *, float, float), (p->p1, p->f1, p->f2));
//-
BEGIN_API_CALLER_FUNC(int, p2fi)
END_API_CALLER_FUNC(int, (const void *, float, float, int), (p->p1, p->f1, p->f2, p->i1));
//-
BEGIN_API_CALLER_FUNC(void, p2i)
END_API_CALLER_FUNC_void((const void *, int, int), (p->p1, p->i1, p->i2));
//-
BEGIN_API_CALLER_FUNC(void, p3i)
END_API_CALLER_FUNC_void((const void *, int, int, int), (p->p1, p->i1, p->i2, p->i3));
//-
BEGIN_API_CALLER_FUNC(void, p4i)
END_API_CALLER_FUNC_void((const void *, int, int, int, int), (p->p1, p->i1, p->i2, p->i3, p->i4));
//-
BEGIN_API_CALLER_FUNC(void, puc)
END_API_CALLER_FUNC_void((const void *, unsigned char), (p->p1, p->uc1));
//-
BEGIN_API_CALLER_FUNC(void, pf)
END_API_CALLER_FUNC_void((const void *, float), (p->p1, p->f1));
//-
BEGIN_API_CALLER_FUNC(void, pfp)
END_API_CALLER_FUNC_void((const void *, float, const void *), (p->p1, p->f1, p->p2));
//-
BEGIN_API_CALLER_FUNC(void, pi)
END_API_CALLER_FUNC_void((const void *, int), (p->p1, p->i1));
@ -619,25 +635,20 @@ END_API_CALLER_FUNC(void*, (const void*, int), (p->p1, p->i1));
BEGIN_API_CALLER_FUNC(int, pi)
END_API_CALLER_FUNC(int, (const void *, int), (p->p1, p->i1));
//-
BEGIN_API_CALLER_FUNC(void, pi2p)
END_API_CALLER_FUNC_void((const void *, int, const void *, const void *), (p->p1, p->i1, p->p2, p->p3));
//-
BEGIN_API_CALLER_FUNC(int, pi2p2ip)
END_API_CALLER_FUNC(int, (const void *, int, const void *, const void *, int, int, const void *), (p->p1, p->i1, p->p2, p->p3, p->i2, p->i3, p->p4));
//-
BEGIN_API_CALLER_FUNC(void, pip)
END_API_CALLER_FUNC_void((const void *, int, const void *), (p->p1, p->i1, p->p2));
BEGIN_API_CALLER_FUNC(ptr, pip)
END_API_CALLER_FUNC(void*, (const void *, int, const void *), (p->p1, p->i1, p->p2));
//-
BEGIN_API_CALLER_FUNC(void, pip2f2i)
END_API_CALLER_FUNC_void((const void *, int, const void *, float, float, int, int), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3));
//-
BEGIN_API_CALLER_FUNC(void, pip2f4i2p)
END_API_CALLER_FUNC_void((const void *, int, const void *, float, float, int, int, int, int, const void *, const void *), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3, p->i4, p->i5, p->p3, p->p4));

View File

@ -1,10 +1,7 @@
#ifndef API_HOOK_H
#define API_HOOK_H
#pragma once
#include "ret_type.h"
#include "api_info.h"
#include "meta_api.h"
#include "osdep.h" //OPEN_ARGS
// Compine 4 parts for single name
#define _COMBINE4(w,x,y,z) w##x##y##z
@ -16,9 +13,7 @@ void main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsig
// full return typed version of main hook function
void *main_hook_function(const class_ret_t ret_init, unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void *packed_args);
//
// API function args structures/classes
//
#define API_PACK_ARGS(type, args)\
_COMBINE2(pack_args_type_, type) packed_args args;
@ -363,5 +358,3 @@ EXTERN_API_CALLER_FUNCTION(void, pip);
EXTERN_API_CALLER_FUNCTION(ptr, pip);
EXTERN_API_CALLER_FUNCTION(void, pip2f2i);
EXTERN_API_CALLER_FUNCTION(void, pip2f4i2p);
#endif /*API_HOOK_H*/

View File

@ -52,18 +52,18 @@ const dllapi_info_t dllapi_info = {
{ mFALSE, 9, api_caller_void_args_void, "CreateInstancedBaselines" }, // pfnCreateInstancedBaselines
{ mFALSE, 3, api_caller_int_args_3p, "InconsistentFile" }, // pfnInconsistentFile
{ mFALSE, 20, api_caller_int_args_void, "AllowLagCompensation" }, // pfnAllowLagCompensation
{ mFALSE, 0, NULL, NULL },
{ mFALSE, 0, nullptr, nullptr },
};
const newapi_info_t newapi_info = {
{ mFALSE, 16, api_caller_void_args_p, "OnFreeEntPrivateData" }, // pfnOnFreeEntPrivateData
{ mFALSE, 3, api_caller_void_args_void, "GameShutdown" }, // pfnGameShutdown
{ mFALSE, 14, api_caller_int_args_2p, "ShouldCollide" }, // pfnShouldCollide
// Added 2005/08/11 (no SDK update):
{ mFALSE, 3, api_caller_void_args_2p, "CvarValue" }, // pfnCvarValue
// Added 2005/11/21 (no SDK update):
{ mFALSE, 3, api_caller_void_args_pi2p, "CvarValue2" }, // pfnCvarValue2
{ mFALSE, 0, NULL, NULL },
{ mFALSE, 0, nullptr, nullptr },
};
const engine_info_t engine_info = {
@ -208,12 +208,11 @@ const engine_info_t engine_info = {
{ mFALSE, 9, api_caller_void_args_i3p, "ForceUnmodified" }, // pfnForceUnmodified
{ mFALSE, 9, api_caller_void_args_3p, "GetPlayerStats" }, // pfnGetPlayerStats
{ mFALSE, 3, api_caller_void_args_2p, "AddServerCommand" }, // pfnAddServerCommand
// Added in SDK 2.2:
{ mFALSE, 9, api_caller_int_args_2i, "Voice_GetClientListening" }, // Voice_GetClientListening
{ mFALSE, 9, api_caller_int_args_3i, "Voice_SetClientListening" }, // Voice_SetClientListening
// Added for HL 1109 (no SDK update):
{ mFALSE, 9, api_caller_ptr_args_p, "GetPlayerAuthId" }, // pfnGetPlayerAuthId
// Added 2003/11/10 (no SDK update):
{ mFALSE, 30, api_caller_ptr_args_2p, "SequenceGet" }, // pfnSequenceGet
{ mFALSE, 30, api_caller_ptr_args_pip, "SequencePickSentence" }, // pfnSequencePickSentence
{ mFALSE, 30, api_caller_int_args_p, "GetFileSize" }, // pfnGetFileSize
@ -225,12 +224,11 @@ const engine_info_t engine_info = {
{ mFALSE, 30, api_caller_void_args_pi, "ProcessTutorMessageDecayBuffer" }, // pfnProcessTutorMessageDecayBuffer
{ mFALSE, 30, api_caller_void_args_pi, "ConstructTutorMessageDecayBuffer" }, // pfnConstructTutorMessageDecayBuffer
{ mFALSE, 9, api_caller_void_args_void, "ResetTutorMessageDecayData" }, // pfnResetTutorMessageDecayData
// Added 2005/08/11 (no SDK update):
{ mFALSE, 3, api_caller_void_args_2p, "QueryClientCvarValue" }, // pfnQueryClientCvarValue
// Added 2005/11/21 (no SDK update):
{ mFALSE, 3, api_caller_void_args_2pi, "QueryClientCvarValue2" }, // pfnQueryClientCvarValue2
// Added 2009-06-17 (no SDK update):
{ mFALSE, 8, api_caller_int_args_2p, "CheckParm" }, // pfnEngCheckParm
// end
{ mFALSE, 0, NULL, NULL },
{ mFALSE, 0, nullptr, nullptr },
};

View File

@ -1,6 +1,5 @@
#pragma once
#include "comp_dep.h"
#include "types_meta.h" // mBOOL
#include "ret_type.h"
@ -16,7 +15,7 @@ enum enum_api_t
};
// API caller function prototype
typedef void *(DLLINTERNAL_NOVIS *api_caller_func_t)(const void *func, const void *packed_args);
typedef void *(*api_caller_func_t)(const void *func, const void *packed_args);
struct api_info_t
{

View File

@ -366,8 +366,7 @@ void cmd_doplug(PLUG_CMD pcmd)
{
if (findp && findp->status >= PL_RUNNING)
{
META_DEBUG(3, ("Required plugin '%s' found loaded and running.",
arg));
META_DEBUG(3, ("Required plugin '%s' found loaded and running.", arg));
return;
}
// Output to both places, because we don't want the admin
@ -387,6 +386,7 @@ void cmd_doplug(PLUG_CMD pcmd)
META_ERROR("Required plugin '%s' did not load successfully! (status=%s) Exiting.", arg, findp->str_status(ST_SIMPLE));
META_CONS("\nERROR: Required plugin '%s' did not load successfully! (status=%s) Exiting.\n", arg, findp->str_status(ST_SIMPLE));
}
// Allow chance to read the message, before any window closes.
do_exit(1);
}
@ -400,21 +400,21 @@ void cmd_doplug(PLUG_CMD pcmd)
return;
}
if (pcmd == PC_PAUSE)
switch (pcmd)
{
case PC_PAUSE:
if (findp->pause())
META_CONS("Paused plugin '%s'", findp->desc);
else
META_CONS("Pause failed for plugin '%s'", findp->desc);
}
else if (pcmd == PC_UNPAUSE)
{
break;
case PC_UNPAUSE:
if (findp->unpause())
META_CONS("Unpaused plugin '%s'", findp->desc);
else
META_CONS("Unpause failed for plugin '%s'", findp->desc);
}
else if (pcmd == PC_UNLOAD)
break;
case PC_UNLOAD:
{
findp->action = PA_UNLOAD;
if (findp->unload(PT_ANYTIME, PNL_COMMAND, PNL_COMMAND))
@ -426,8 +426,9 @@ void cmd_doplug(PLUG_CMD pcmd)
META_CONS("Unload delayed for plugin '%s'", findp->desc);
else
META_CONS("Unload failed for plugin '%s'", findp->desc);
break;
}
else if (pcmd == PC_FORCE_UNLOAD)
case PC_FORCE_UNLOAD:
{
findp->action = PA_UNLOAD;
if (findp->unload(PT_ANYTIME, PNL_CMD_FORCED, PNL_CMD_FORCED))
@ -437,8 +438,9 @@ void cmd_doplug(PLUG_CMD pcmd)
}
else
META_CONS("Forced unload failed for plugin '%s'", findp->desc);
break;
}
else if (pcmd == PC_RELOAD)
case PC_RELOAD:
{
findp->action = PA_RELOAD;
if (findp->reload(PT_ANYTIME, PNL_COMMAND))
@ -449,30 +451,31 @@ void cmd_doplug(PLUG_CMD pcmd)
META_CONS("Reload not allowed for plugin '%s' now, only allowed %s", findp->desc, findp->str_loadable(SL_ALLOWED));
else
META_CONS("Reload failed for plugin '%s'", findp->desc);
break;
}
else if (pcmd == PC_RETRY)
{
case PC_RETRY:
if (findp->retry(PT_ANYTIME, PNL_COMMAND))
META_CONS("Retry succeeded for plugin '%s'", findp->desc);
else
META_CONS("Retry failed for plugin '%s'", findp->desc);
break;
case PC_CLEAR:
if (!findp->clear())
{
META_CONS("Clear failed for plugin '%s'", findp->desc);
return;
}
else if (pcmd == PC_CLEAR)
{
if (findp->clear())
{
META_CONS("Cleared failed plugin '%s' from list", findp->desc);
Plugins->show();
}
else
META_CONS("Clear failed for plugin '%s'", findp->desc);
}
else if (pcmd == PC_INFO)
break;
case PC_INFO:
findp->show();
else
{
break;
default:
META_WARNING("Unexpected plug_cmd: %d", pcmd);
META_CONS("Command failed; see log");
break;
}
}
}

View File

@ -1,11 +1,11 @@
#pragma once
#include "types_meta.h" // mBOOL
#include "comp_dep.h"
#include "types_meta.h"
// Flags to use for meta_cmd_doplug(), to operate on existing plugins; note
// "load" operates on a non-existing plugin thus isn't included here.
typedef enum {
enum PLUG_CMD
{
PC_NULL = 0,
PC_PAUSE, // pause the plugin
PC_UNPAUSE, // unpause the plugin
@ -16,7 +16,7 @@ typedef enum {
PC_CLEAR, // remove a failed plugin from the list
PC_FORCE_UNLOAD, // forcibly unload the plugin
PC_REQUIRE, // require that this plugin is loaded/running
} PLUG_CMD;
};
void meta_register_cmdcvar();

View File

@ -1,65 +0,0 @@
#ifndef COMP_DEP_H
#define COMP_DEP_H
#define DECLSPEC(kw)
#if defined (_WIN32) && defined (_MSC_VER)
#define ATTRIBUTE(kw)
#else
#define ATTRIBUTE(kw) __attribute__((kw))
#endif
#define MM_CDECL
// We use these macros to hide our internal globals from being exported
// on ELF .so
#if defined(__GNUC__) && !defined(_WIN32) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 3
// Hidden internal function.
#if defined(__x86_64__) || defined(__amd64__)
#define DLLINTERNAL __attribute__((visibility("internal")))
#define DLLINTERNAL_NOVIS
#else
#ifdef __INTERNALS_USE_REGPARAMS__
#define DLLINTERNAL __attribute__((visibility("internal"), regparm(3)))
#define DLLINTERNAL_NOVIS __attribute__((regparm(3)))
#else
#define DLLINTERNAL __attribute__((visibility("internal")))
#define DLLINTERNAL_NOVIS
#endif
#endif
#else
#if defined (_WIN32) && defined (_MSC_VER)
#define DLLINTERNAL_NOVIS
#define DLLINTERNAL
#else
#ifdef __INTERNALS_USE_REGPARAMS__
#define DLLINTERNAL_NOVIS __attribute__((regparm(3)))
#define DLLINTERNAL DLLINTERNAL_NOVIS
#else
#define DLLINTERNAL_NOVIS
#define DLLINTERNAL
#endif
#endif //defined WIN32
#endif
/*
#if defined (_WIN32) && defined (_MSC_VER)
// On x86 va_list is just a pointer.
#define va_copy(dst,src) ((dst)=(src))
#else
// Some systems that do not supply va_copy have __va_copy instead, since
// that was the name used in the draft proposal.
#if !defined(__GNUC__) || __GNUC__ < 3
#define va_copy __va_copy
#endif
#endif
*/
// Manual branch optimization for GCC 3.0.0 and newer
#if !defined(__GNUC__) || __GNUC__ < 3
#define likely(x) (x)
#define unlikely(x) (x)
#else
#define likely(x) __builtin_expect((long int)(x), true)
#define unlikely(x) __builtin_expect((long int)(x), false)
#endif
#endif /*COMP_DEP_H*/

View File

@ -1,8 +1,7 @@
#pragma once
#include "types_meta.h" // mBOOL
#include "types_meta.h"
#include "new_baseclass.h"
#include "comp_dep.h"
// Max length of line in config file.
#define MAX_CONF_LEN 1024

View File

@ -29,109 +29,148 @@
API_END_TSC_TRACKING()
// From SDK dlls/game.cpp:
static void mm_GameDLLInit() {
void mm_GameDLLInit()
{
META_DLLAPI_HANDLE_void(FN_GAMEINIT, pfnGameInit, void, (VOID_ARG));
RETURN_API_void();
}
// From SDK dlls/cbase.cpp:
static int mm_DispatchSpawn(edict_t *pent) {
int mm_DispatchSpawn(edict_t *pent)
{
// 0==Success, -1==Failure ?
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHSPAWN, pfnSpawn, p, (pent));
RETURN_API(int);
}
static void mm_DispatchThink(edict_t *pent) {
void mm_DispatchThink(edict_t *pent)
{
META_DLLAPI_HANDLE_void(FN_DISPATCHTHINK, pfnThink, p, (pent));
RETURN_API_void();
}
static void mm_DispatchUse(edict_t *pentUsed, edict_t *pentOther) {
void mm_DispatchUse(edict_t *pentUsed, edict_t *pentOther)
{
META_DLLAPI_HANDLE_void(FN_DISPATCHUSE, pfnUse, 2p, (pentUsed, pentOther));
RETURN_API_void();
}
static void mm_DispatchTouch(edict_t *pentTouched, edict_t *pentOther) {
void mm_DispatchTouch(edict_t *pentTouched, edict_t *pentOther)
{
META_DLLAPI_HANDLE_void(FN_DISPATCHTOUCH, pfnTouch, 2p, (pentTouched, pentOther));
RETURN_API_void();
}
static void mm_DispatchBlocked(edict_t *pentBlocked, edict_t *pentOther) {
void mm_DispatchBlocked(edict_t *pentBlocked, edict_t *pentOther)
{
META_DLLAPI_HANDLE_void(FN_DISPATCHBLOCKED, pfnBlocked, 2p, (pentBlocked, pentOther));
RETURN_API_void();
}
static void mm_DispatchKeyValue(edict_t *pentKeyvalue, KeyValueData *pkvd) {
void mm_DispatchKeyValue(edict_t *pentKeyvalue, KeyValueData *pkvd)
{
META_DLLAPI_HANDLE_void(FN_DISPATCHKEYVALUE, pfnKeyValue, 2p, (pentKeyvalue, pkvd));
RETURN_API_void();
}
static void mm_DispatchSave(edict_t *pent, SAVERESTOREDATA *pSaveData) {
void mm_DispatchSave(edict_t *pent, SAVERESTOREDATA *pSaveData)
{
META_DLLAPI_HANDLE_void(FN_DISPATCHSAVE, pfnSave, 2p, (pent, pSaveData));
RETURN_API_void();
}
static int mm_DispatchRestore(edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity) {
int mm_DispatchRestore(edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity)
{
// 0==Success, -1==Failure ?
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHRESTORE, pfnRestore, 2pi, (pent, pSaveData, globalEntity));
RETURN_API(int);
}
static void mm_DispatchObjectCollsionBox(edict_t *pent) {
void mm_DispatchObjectCollsionBox(edict_t *pent)
{
META_DLLAPI_HANDLE_void(FN_DISPATCHOBJECTCOLLISIONBOX, pfnSetAbsBox, p, (pent));
RETURN_API_void();
}
static void mm_SaveWriteFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
void mm_SaveWriteFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount)
{
META_DLLAPI_HANDLE_void(FN_SAVEWRITEFIELDS, pfnSaveWriteFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
RETURN_API_void();
}
static void mm_SaveReadFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
void mm_SaveReadFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount)
{
META_DLLAPI_HANDLE_void(FN_SAVEREADFIELDS, pfnSaveReadFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
RETURN_API_void();
}
// From SDK dlls/world.cpp:
static void mm_SaveGlobalState(SAVERESTOREDATA *pSaveData) {
void mm_SaveGlobalState(SAVERESTOREDATA *pSaveData)
{
META_DLLAPI_HANDLE_void(FN_SAVEGLOBALSTATE, pfnSaveGlobalState, p, (pSaveData));
RETURN_API_void();
}
static void mm_RestoreGlobalState(SAVERESTOREDATA *pSaveData) {
void mm_RestoreGlobalState(SAVERESTOREDATA *pSaveData)
{
META_DLLAPI_HANDLE_void(FN_RESTOREGLOBALSTATE, pfnRestoreGlobalState, p, (pSaveData));
RETURN_API_void();
}
static void mm_ResetGlobalState() {
void mm_ResetGlobalState()
{
META_DLLAPI_HANDLE_void(FN_RESETGLOBALSTATE, pfnResetGlobalState, void, (VOID_ARG));
RETURN_API_void();
}
// From SDK dlls/client.cpp:
static qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) {
qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128])
{
g_Players.clear_player_cvar_query(pEntity);
META_DLLAPI_HANDLE(qboolean, TRUE, FN_CLIENTCONNECT, pfnClientConnect, 4p, (pEntity, pszName, pszAddress, szRejectReason));
RETURN_API(qboolean);
}
static void mm_ClientDisconnect(edict_t *pEntity) {
void mm_ClientDisconnect(edict_t *pEntity)
{
g_Players.clear_player_cvar_query(pEntity);
META_DLLAPI_HANDLE_void(FN_CLIENTDISCONNECT, pfnClientDisconnect, p, (pEntity));
RETURN_API_void();
}
static void mm_ClientKill(edict_t *pEntity) {
void mm_ClientKill(edict_t *pEntity)
{
META_DLLAPI_HANDLE_void(FN_CLIENTKILL, pfnClientKill, p, (pEntity));
RETURN_API_void();
}
static void mm_ClientPutInServer(edict_t *pEntity) {
void mm_ClientPutInServer(edict_t *pEntity)
{
META_DLLAPI_HANDLE_void(FN_CLIENTPUTINSERVER, pfnClientPutInServer, p, (pEntity));
RETURN_API_void();
}
static void mm_ClientCommand(edict_t *pEntity) {
if (Config->clientmeta && !Q_strcmp(CMD_ARGV(0), "meta")) {
void mm_ClientCommand(edict_t *pEntity)
{
if (Config->clientmeta && !Q_strcmp(CMD_ARGV(0), "meta"))
{
client_meta(pEntity);
}
META_DLLAPI_HANDLE_void(FN_CLIENTCOMMAND, pfnClientCommand, p, (pEntity));
RETURN_API_void();
}
static void mm_ClientUserInfoChanged(edict_t *pEntity, char *infobuffer) {
void mm_ClientUserInfoChanged(edict_t *pEntity, char *infobuffer)
{
META_DLLAPI_HANDLE_void(FN_CLIENTUSERINFOCHANGED, pfnClientUserInfoChanged, 2p, (pEntity, infobuffer));
RETURN_API_void();
}
static void mm_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) {
void mm_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
{
META_DLLAPI_HANDLE_void(FN_SERVERACTIVATE, pfnServerActivate, p2i, (pEdictList, edictCount, clientMax));
RETURN_API_void();
}
static void mm_ServerDeactivate() {
void mm_ServerDeactivate()
{
META_DLLAPI_HANDLE_void(FN_SERVERDEACTIVATE, pfnServerDeactivate, void, (VOID_ARG));
// Update loaded plugins. Look for new plugins in inifile, as well as
// any plugins waiting for a changelevel to load.
@ -153,204 +192,256 @@ static void mm_ServerDeactivate() {
requestid_counter = 0;
RETURN_API_void();
}
static void mm_PlayerPreThink(edict_t *pEntity) {
void mm_PlayerPreThink(edict_t *pEntity)
{
META_DLLAPI_HANDLE_void(FN_PLAYERPRETHINK, pfnPlayerPreThink, p, (pEntity));
RETURN_API_void();
}
static void mm_PlayerPostThink(edict_t *pEntity) {
void mm_PlayerPostThink(edict_t *pEntity)
{
META_DLLAPI_HANDLE_void(FN_PLAYERPOSTTHINK, pfnPlayerPostThink, p, (pEntity));
RETURN_API_void();
}
static void mm_StartFrame() {
void mm_StartFrame()
{
meta_debug_value = (int)meta_debug.value;
META_DLLAPI_HANDLE_void(FN_STARTFRAME, pfnStartFrame, void, (VOID_ARG));
RETURN_API_void();
}
static void mm_ParmsNewLevel() {
void mm_ParmsNewLevel()
{
META_DLLAPI_HANDLE_void(FN_PARMSNEWLEVEL, pfnParmsNewLevel, void, (VOID_ARG));
RETURN_API_void();
}
static void mm_ParmsChangeLevel() {
void mm_ParmsChangeLevel()
{
META_DLLAPI_HANDLE_void(FN_PARMSCHANGELEVEL, pfnParmsChangeLevel, void, (VOID_ARG));
RETURN_API_void();
}
static const char *mm_GetGameDescription() {
const char *mm_GetGameDescription()
{
META_DLLAPI_HANDLE(const char *, NULL, FN_GETGAMEDESCRIPTION, pfnGetGameDescription, void, (VOID_ARG));
RETURN_API(const char *);
}
static void mm_PlayerCustomization(edict_t *pEntity, customization_t *pCust) {
void mm_PlayerCustomization(edict_t *pEntity, customization_t *pCust)
{
META_DLLAPI_HANDLE_void(FN_PLAYERCUSTOMIZATION, pfnPlayerCustomization, 2p, (pEntity, pCust));
RETURN_API_void();
}
static void mm_SpectatorConnect(edict_t *pEntity) {
void mm_SpectatorConnect(edict_t *pEntity)
{
META_DLLAPI_HANDLE_void(FN_SPECTATORCONNECT, pfnSpectatorConnect, p, (pEntity));
RETURN_API_void();
}
static void mm_SpectatorDisconnect(edict_t *pEntity) {
void mm_SpectatorDisconnect(edict_t *pEntity)
{
META_DLLAPI_HANDLE_void(FN_SPECTATORDISCONNECT, pfnSpectatorDisconnect, p, (pEntity));
RETURN_API_void();
}
static void mm_SpectatorThink(edict_t *pEntity) {
void mm_SpectatorThink(edict_t *pEntity)
{
META_DLLAPI_HANDLE_void(FN_SPECTATORTHINK, pfnSpectatorThink, p, (pEntity));
RETURN_API_void();
}
static void mm_Sys_Error(const char *error_string) {
void mm_Sys_Error(const char *error_string)
{
META_DLLAPI_HANDLE_void(FN_SYS_ERROR, pfnSys_Error, p, (error_string));
RETURN_API_void();
}
// From SDK pm_shared/pm_shared.c:
static void mm_PM_Move(struct playermove_s *ppmove, int server) {
void mm_PM_Move(struct playermove_s *ppmove, int server)
{
META_DLLAPI_HANDLE_void(FN_PM_MOVE, pfnPM_Move, pi, (ppmove, server));
RETURN_API_void();
}
static void mm_PM_Init(struct playermove_s *ppmove) {
void mm_PM_Init(struct playermove_s *ppmove)
{
META_DLLAPI_HANDLE_void(FN_PM_INIT, pfnPM_Init, p, (ppmove));
RETURN_API_void();
}
static char mm_PM_FindTextureType(char *name) {
char mm_PM_FindTextureType(char *name)
{
META_DLLAPI_HANDLE(const char, '\0', FN_PM_FINDTEXTURETYPE, pfnPM_FindTextureType, p, (name));
RETURN_API(const char);
}
// From SDK dlls/client.cpp:
static void mm_SetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas) {
void mm_SetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas)
{
META_DLLAPI_HANDLE_void(FN_SETUPVISIBILITY, pfnSetupVisibility, 4p, (pViewEntity, pClient, pvs, pas));
RETURN_API_void();
}
static void mm_UpdateClientData(const struct edict_s *ent, int sendweapons, struct clientdata_s *cd) {
void mm_UpdateClientData(const struct edict_s *ent, int sendweapons, struct clientdata_s *cd)
{
META_DLLAPI_HANDLE_void(FN_UPDATECLIENTDATA, pfnUpdateClientData, pip, (ent, sendweapons, cd));
RETURN_API_void();
}
static int mm_AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet) {
int mm_AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet)
{
META_DLLAPI_HANDLE(int, 0, FN_ADDTOFULLPACK, pfnAddToFullPack, pi2p2ip, (state, e, ent, host, hostflags, player, pSet));
RETURN_API(int);
}
static void mm_CreateBaseline(int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs) {
void mm_CreateBaseline(int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs)
{
META_DLLAPI_HANDLE_void(FN_CREATEBASELINE, pfnCreateBaseline, 2i2pi2p, (player, eindex, baseline, entity, playermodelindex, (float*)player_mins, (float*)player_maxs));
RETURN_API_void();
}
static void mm_RegisterEncoders() {
void mm_RegisterEncoders()
{
META_DLLAPI_HANDLE_void(FN_REGISTERENCODERS, pfnRegisterEncoders, void, (VOID_ARG));
RETURN_API_void();
}
static int mm_GetWeaponData(struct edict_s *player, struct weapon_data_s *info) {
int mm_GetWeaponData(struct edict_s *player, struct weapon_data_s *info)
{
META_DLLAPI_HANDLE(int, 0, FN_GETWEAPONDATA, pfnGetWeaponData, 2p, (player, info));
RETURN_API(int);
}
static void mm_CmdStart(const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed) {
void mm_CmdStart(const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed)
{
META_DLLAPI_HANDLE_void(FN_CMDSTART, pfnCmdStart, 2pui, (player, cmd, random_seed));
RETURN_API_void();
}
static void mm_CmdEnd(const edict_t *player) {
void mm_CmdEnd(const edict_t *player)
{
META_DLLAPI_HANDLE_void(FN_CMDEND, pfnCmdEnd, p, (player));
RETURN_API_void();
}
static int mm_ConnectionlessPacket(const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size) {
int mm_ConnectionlessPacket(const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size)
{
META_DLLAPI_HANDLE(int, 0, FN_CONNECTIONLESSPACKET, pfnConnectionlessPacket, 4p, (net_from, args, response_buffer, response_buffer_size));
RETURN_API(int);
}
static int mm_GetHullBounds(int hullnumber, float *mins, float *maxs) {
int mm_GetHullBounds(int hullnumber, float *mins, float *maxs)
{
META_DLLAPI_HANDLE(int, 0, FN_GETHULLBOUNDS, pfnGetHullBounds, i2p, (hullnumber, mins, maxs));
RETURN_API(int);
}
static void mm_CreateInstancedBaselines() {
void mm_CreateInstancedBaselines()
{
META_DLLAPI_HANDLE_void(FN_CREATEINSTANCEDBASELINES, pfnCreateInstancedBaselines, void, (VOID_ARG));
RETURN_API_void();
}
static int mm_InconsistentFile(const edict_t *player, const char *filename, char *disconnect_message) {
int mm_InconsistentFile(const edict_t *player, const char *filename, char *disconnect_message)
{
META_DLLAPI_HANDLE(int, 0, FN_INCONSISTENTFILE, pfnInconsistentFile, 3p, (player, filename, disconnect_message));
RETURN_API(int);
}
static int mm_AllowLagCompensation() {
int mm_AllowLagCompensation()
{
META_DLLAPI_HANDLE(int, 0, FN_ALLOWLAGCOMPENSATION, pfnAllowLagCompensation, void, (VOID_ARG));
RETURN_API(int);
}
// New API functions
// From SDK ?
static void mm_OnFreeEntPrivateData(edict_t *pEnt) {
void mm_OnFreeEntPrivateData(edict_t *pEnt)
{
META_NEWAPI_HANDLE_void(FN_ONFREEENTPRIVATEDATA, pfnOnFreeEntPrivateData, p, (pEnt));
RETURN_API_void();
}
static void mm_GameShutdown() {
void mm_GameShutdown()
{
META_NEWAPI_HANDLE_void(FN_GAMESHUTDOWN, pfnGameShutdown, void, (VOID_ARG));
RETURN_API_void();
}
static int mm_ShouldCollide(edict_t *pentTouched, edict_t *pentOther) {
int mm_ShouldCollide(edict_t *pentTouched, edict_t *pentOther)
{
META_NEWAPI_HANDLE(int, 1, FN_SHOULDCOLLIDE, pfnShouldCollide, 2p, (pentTouched, pentOther));
RETURN_API(int);
}
// Added 2005/08/11 (no SDK update):
static void mm_CvarValue(const edict_t *pEnt, const char *value) {
void mm_CvarValue(const edict_t *pEnt, const char *value)
{
g_Players.clear_player_cvar_query(pEnt);
META_NEWAPI_HANDLE_void(FN_CVARVALUE, pfnCvarValue, 2p, (pEnt, value));
RETURN_API_void();
}
// Added 2005/11/21 (no SDK update):
static void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value) {
void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value)
{
META_NEWAPI_HANDLE_void(FN_CVARVALUE2, pfnCvarValue2, pi2p, (pEnt, requestID, cvarName, value));
RETURN_API_void();
}
// From SDK dlls/cbase.cpp:
// "(wd)" indicates my comments on the functions
static DLL_FUNCTIONS gFunctionTable =
DLL_FUNCTIONS gFunctionTable =
{
mm_GameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll)
mm_DispatchSpawn, //! pfnSpawn()
mm_DispatchThink, //! pfnThink()
mm_DispatchUse, //! pfnUse()
mm_DispatchTouch, //! pfnTouch()
mm_DispatchBlocked, //! pfnBlocked()
mm_DispatchKeyValue, //! pfnKeyValue()
mm_DispatchSave, //! pfnSave()
mm_DispatchRestore, //! pfnRestore()
mm_DispatchObjectCollsionBox, //! pfnSetAbsBox()
mm_SaveWriteFields, //! pfnSaveWriteFields()
mm_SaveReadFields, //! pfnSaveReadFields()
mm_SaveGlobalState, //! pfnSaveGlobalState()
mm_RestoreGlobalState, //! pfnRestoreGlobalState()
mm_ResetGlobalState, //! pfnResetGlobalState()
mm_ClientConnect, //! pfnClientConnect() (wd) Client has connected
mm_ClientDisconnect, //! pfnClientDisconnect() (wd) Player has left the game
mm_ClientKill, //! pfnClientKill() (wd) Player has typed "kill"
mm_ClientPutInServer, //! pfnClientPutInServer() (wd) Client is entering the game
mm_ClientCommand, //! pfnClientCommand() (wd) Player has sent a command (typed, or from a bind)
mm_ClientUserInfoChanged, //! pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure
mm_ServerActivate, //! pfnServerActivate() (wd) Server is starting a new map
mm_ServerDeactivate, //! pfnServerDeactivate() (wd) Server is leaving the map (shutdown, or changelevel); SDK2
mm_PlayerPreThink, //! pfnPlayerPreThink()
mm_PlayerPostThink, //! pfnPlayerPostThink()
mm_StartFrame, //! pfnStartFrame()
mm_ParmsNewLevel, //! pfnParmsNewLevel()
mm_ParmsChangeLevel, //! pfnParmsChangeLevel()
mm_GetGameDescription, //! pfnGetGameDescription() Returns string describing current .dll. E.g. "TeamFotrress 2", "Half-Life"
mm_PlayerCustomization, //! pfnPlayerCustomization() Notifies .dll of new customization for player.
mm_SpectatorConnect, //! pfnSpectatorConnect() Called when spectator joins server
mm_SpectatorDisconnect, //! pfnSpectatorDisconnect() Called when spectator leaves the server
mm_SpectatorThink, //! pfnSpectatorThink() Called when spectator sends a command packet (usercmd_t)
mm_Sys_Error, //! pfnSys_Error() Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. SDK2
mm_PM_Move, //! pfnPM_Move() (wd) SDK2
mm_PM_Init, //! pfnPM_Init() Server version of player movement initialization; (wd) SDK2
mm_PM_FindTextureType, //! pfnPM_FindTextureType() (wd) SDK2
mm_SetupVisibility, //! pfnSetupVisibility() Set up PVS and PAS for networking for this client; (wd) SDK2
mm_UpdateClientData, //! pfnUpdateClientData() Set up data sent only to specific client; (wd) SDK2
mm_AddToFullPack, //! pfnAddToFullPack() (wd) SDK2
mm_CreateBaseline, //! pfnCreateBaseline() Tweak entity baseline for network encoding, allows setup of player baselines, too.; (wd) SDK2
mm_RegisterEncoders, //! pfnRegisterEncoders() Callbacks for network encoding; (wd) SDK2
mm_GetWeaponData, //! pfnGetWeaponData() (wd) SDK2
mm_CmdStart, //! pfnCmdStart() (wd) SDK2
mm_CmdEnd, //! pfnCmdEnd() (wd) SDK2
mm_ConnectionlessPacket, //! pfnConnectionlessPacket() (wd) SDK2
mm_GetHullBounds, //! pfnGetHullBounds() (wd) SDK2
mm_CreateInstancedBaselines, //! pfnCreateInstancedBaselines() (wd) SDK2
mm_InconsistentFile, //! pfnInconsistentFile() (wd) SDK2
mm_AllowLagCompensation, //! pfnAllowLagCompensation() (wd) SDK2
mm_GameDLLInit, // pfnGameInit() Initialize the game (one-time call after loading of game .dll)
mm_DispatchSpawn, // pfnSpawn()
mm_DispatchThink, // pfnThink()
mm_DispatchUse, // pfnUse()
mm_DispatchTouch, // pfnTouch()
mm_DispatchBlocked, // pfnBlocked()
mm_DispatchKeyValue, // pfnKeyValue()
mm_DispatchSave, // pfnSave()
mm_DispatchRestore, // pfnRestore()
mm_DispatchObjectCollsionBox, // pfnSetAbsBox()
mm_SaveWriteFields, // pfnSaveWriteFields()
mm_SaveReadFields, // pfnSaveReadFields()
mm_SaveGlobalState, // pfnSaveGlobalState()
mm_RestoreGlobalState, // pfnRestoreGlobalState()
mm_ResetGlobalState, // pfnResetGlobalState()
mm_ClientConnect, // pfnClientConnect() (wd) Client has connected
mm_ClientDisconnect, // pfnClientDisconnect() (wd) Player has left the game
mm_ClientKill, // pfnClientKill() (wd) Player has typed "kill"
mm_ClientPutInServer, // pfnClientPutInServer() (wd) Client is entering the game
mm_ClientCommand, // pfnClientCommand() (wd) Player has sent a command (typed, or from a bind)
mm_ClientUserInfoChanged, // pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure
mm_ServerActivate, // pfnServerActivate() (wd) Server is starting a new map
mm_ServerDeactivate, // pfnServerDeactivate() (wd) Server is leaving the map (shutdown, or changelevel); SDK2
mm_PlayerPreThink, // pfnPlayerPreThink()
mm_PlayerPostThink, // pfnPlayerPostThink()
mm_StartFrame, // pfnStartFrame()
mm_ParmsNewLevel, // pfnParmsNewLevel()
mm_ParmsChangeLevel, // pfnParmsChangeLevel()
mm_GetGameDescription, // pfnGetGameDescription() Returns string describing current .dll. E.g. "TeamFotrress 2", "Half-Life"
mm_PlayerCustomization, // pfnPlayerCustomization() Notifies .dll of new customization for player.
mm_SpectatorConnect, // pfnSpectatorConnect() Called when spectator joins server
mm_SpectatorDisconnect, // pfnSpectatorDisconnect() Called when spectator leaves the server
mm_SpectatorThink, // pfnSpectatorThink() Called when spectator sends a command packet (usercmd_t)
mm_Sys_Error, // pfnSys_Error() Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. SDK2
mm_PM_Move, // pfnPM_Move() (wd) SDK2
mm_PM_Init, // pfnPM_Init() Server version of player movement initialization; (wd) SDK2
mm_PM_FindTextureType, // pfnPM_FindTextureType() (wd) SDK2
mm_SetupVisibility, // pfnSetupVisibility() Set up PVS and PAS for networking for this client; (wd) SDK2
mm_UpdateClientData, // pfnUpdateClientData() Set up data sent only to specific client; (wd) SDK2
mm_AddToFullPack, // pfnAddToFullPack() (wd) SDK2
mm_CreateBaseline, // pfnCreateBaseline() Tweak entity baseline for network encoding, allows setup of player baselines, too.; (wd) SDK2
mm_RegisterEncoders, // pfnRegisterEncoders() Callbacks for network encoding; (wd) SDK2
mm_GetWeaponData, // pfnGetWeaponData() (wd) SDK2
mm_CmdStart, // pfnCmdStart() (wd) SDK2
mm_CmdEnd, // pfnCmdEnd() (wd) SDK2
mm_ConnectionlessPacket, // pfnConnectionlessPacket() (wd) SDK2
mm_GetHullBounds, // pfnGetHullBounds() (wd) SDK2
mm_CreateInstancedBaselines, // pfnCreateInstancedBaselines() (wd) SDK2
mm_InconsistentFile, // pfnInconsistentFile() (wd) SDK2
mm_AllowLagCompensation, // pfnAllowLagCompensation() (wd) SDK2
};
DLL_FUNCTIONS *g_pHookedDllFunctions = &gFunctionTable;
@ -370,18 +461,20 @@ DLL_FUNCTIONS *g_pHookedDllFunctions = &gFunctionTable;
//
// It's unclear whether a DLL coded under SDK2 needs to provide the older
// GetAPI or not..
C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion)
{
META_DEBUG(3, ("called: GetEntityAPI; version=%d", interfaceVersion));
if (!pFunctionTable || metamod_not_loaded) {
if (!pFunctionTable || metamod_not_loaded)
{
META_WARNING("GetEntityAPI called with null pFunctionTable");
return FALSE;
}
else if (interfaceVersion != INTERFACE_VERSION) {
else if (interfaceVersion != INTERFACE_VERSION)
{
META_WARNING("GetEntityAPI version mismatch; requested=%d ours=%d", interfaceVersion, INTERFACE_VERSION);
return FALSE;
}
Q_memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
return TRUE;
}
@ -389,21 +482,23 @@ C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion
C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
{
META_DEBUG(3, ("called: GetEntityAPI2; version=%d", *interfaceVersion));
if (!pFunctionTable || metamod_not_loaded) {
if (!pFunctionTable || metamod_not_loaded)
{
META_WARNING("GetEntityAPI2 called with null pFunctionTable");
return FALSE;
}
else if (*interfaceVersion != INTERFACE_VERSION) {
else if (*interfaceVersion != INTERFACE_VERSION)
{
META_WARNING("GetEntityAPI2 version mismatch; requested=%d ours=%d", *interfaceVersion, INTERFACE_VERSION);
//! Tell engine what version we had, so it can figure out who is out of date.
// Tell engine what version we had, so it can figure out who is out of date.
*interfaceVersion = INTERFACE_VERSION;
return FALSE;
}
Q_memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
return TRUE;
}
// I could find _no_ documentation or examples for the intended use of
// NEW_DLL_FUNCTIONS. I wouldn't have even _known_ about the
// GetNewDLLFunctions() function except for the reference in Adminmod.. It
@ -414,15 +509,12 @@ C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersi
// appending new functions to the GetAPI table/interface.
//
// Interestingly, it appears to be called by the engine _before_ GetAPI.
static meta_new_dll_functions_t sNewFunctionTable(
&mm_OnFreeEntPrivateData, //! pfnOnFreeEntPrivateData() Called right before the object's memory is freed. Calls its destructor.
&mm_GameShutdown, //! pfnGameShutdown()
&mm_ShouldCollide, //! pfnShouldCollide()
// Added 2005/08/11 (no SDK update):
&mm_CvarValue, //! pfnCvarValue()
// Added 2005/11/21 (no SDK update):
&mm_CvarValue2 //! pfnCvarValue2()
meta_new_dll_functions_t sNewFunctionTable(
&mm_OnFreeEntPrivateData, // pfnOnFreeEntPrivateData() Called right before the object's memory is freed. Calls its destructor.
&mm_GameShutdown, // pfnGameShutdown()
&mm_ShouldCollide, // pfnShouldCollide()
&mm_CvarValue, // pfnCvarValue()
&mm_CvarValue2 // pfnCvarValue2()
);
NEW_DLL_FUNCTIONS *g_pHookedNewDllFunctions = &sNewFunctionTable;
@ -430,6 +522,7 @@ NEW_DLL_FUNCTIONS *g_pHookedNewDllFunctions = &sNewFunctionTable;
C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion)
{
META_DEBUG(6, ("called: GetNewDLLFunctions; version=%d", *interfaceVersion));
#if 0 // ~dvander - but then you can't use cvar querying on many mods...
// Don't provide these functions to engine if gamedll doesn't provide
// them. Otherwise, we're in the position of having to provide answers
@ -437,16 +530,21 @@ C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *in
if (!GameDLL.funcs.newapi_table)
return FALSE;
#endif
if (!pNewFunctionTable) {
if (!pNewFunctionTable)
{
META_ERROR("GetNewDLLFunctions called with null pNewFunctionTable");
return FALSE;
}
else if (*interfaceVersion != NEW_DLL_FUNCTIONS_VERSION) {
else if (*interfaceVersion != NEW_DLL_FUNCTIONS_VERSION)
{
META_ERROR("GetNewDLLFunctions version mismatch; requested=%d ours=%d", *interfaceVersion, NEW_DLL_FUNCTIONS_VERSION);
//! Tell engine what version we had, so it can figure out who is out of date.
// Tell engine what version we had, so it can figure out who is out of date.
*interfaceVersion = NEW_DLL_FUNCTIONS_VERSION;
return FALSE;
}
sNewFunctionTable.copy_to(pNewFunctionTable);
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
#pragma once
#include "comp_dep.h"
// Plugin's GetEngineFunctions, called by metamod.
typedef int (*GET_ENGINE_FUNCTIONS_FN)(enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion);

View File

@ -1,7 +1,6 @@
#pragma once
#include "eiface.h" // engfuncs_t, globalvars_t
#include "comp_dep.h"
// Our structure for storing engine references.
struct engine_t {
@ -19,13 +18,11 @@ inline engine_t::engine_t()
{
}
inline engine_t::engine_t(const engine_t& _rhs)
: funcs(_rhs.funcs), globals(_rhs.globals), pl_funcs(_rhs.pl_funcs)
{
}
inline engine_t& engine_t::operator=(const engine_t& _rhs)
{
funcs = _rhs.funcs;

View File

@ -1,11 +1,11 @@
#include "precompiled.h"
#ifdef _WIN32
//! Required DLL entry point
// Required DLL entry point
// The above SDK comment indicates this routine is required, but the MSDN
// documentation indicates it's actually optional. We keep it, though, for
// completeness.
// Note! 'extern "C"' needed for mingw compile.
// Note: 'extern "C"' needed for mingw compile.
extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH) {
@ -31,7 +31,7 @@ void _fini() {
}
#endif
//! Holds engine functionality callbacks
// Holds engine functionality callbacks
HL_enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals;
engine_t Engine;
@ -43,7 +43,7 @@ engine_t Engine;
// is actually all done in meta_startup().
C_DLLEXPORT void WINAPI GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, globalvars_t *pGlobals)
{
#ifdef linux
#ifndef _WIN32
metamod_handle = get_module_handle_of_memptr((void*)&g_engfuncs);
#endif
@ -53,7 +53,7 @@ C_DLLEXPORT void WINAPI GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, glob
g_engfuncs.initialise_interface(pengfuncsFromEngine);
// NOTE! Have to call logging function _after_ initialising g_engfuncs, so
// NOTE: Have to call logging function _after_ initialising g_engfuncs, so
// that g_engfuncs.pfnAlertMessage() can be resolved properly, heh. :)
META_DEV("called: GiveFnptrsToDll");
// Load plugins, load game dll.

View File

@ -41,8 +41,8 @@ void META_DEV(const char *fmt, ...)
va_list ap;
static const char *const prefixDEV = "[META] dev:";
//if (!CVAR_GET_FLOAT("developer"))
// return;
if (!CVAR_GET_FLOAT("developer"))
return;
va_start(ap, fmt);
buffered_ALERT(mlsDEV, at_logged, prefixDEV, fmt, ap);

View File

@ -1,7 +1,5 @@
#pragma once
#include "comp_dep.h"
// Debug logging.
//
// This is done as a macro, rather than a function. This way, you can add

View File

@ -1,7 +1,5 @@
#ifndef META_API_H
#define META_API_H
#pragma once
#include "comp_dep.h"
#include "dllapi.h" // GETENTITYAPI_FN, etc
#include "engine_api.h" // GET_ENGINE_FUNCTIONS_FN, etc
#include "plinfo.h" // plugin_info_t, etc
@ -31,36 +29,42 @@
// Flags returned by a plugin's api function.
// NOTE: order is crucial, as greater/less comparisons are made.
typedef enum {
enum META_RES
{
MRES_UNSET = 0,
MRES_IGNORED, // plugin didn't take any action
MRES_HANDLED, // plugin did something, but real function should still be called
MRES_OVERRIDE, // call real function, but use my return value
MRES_SUPERCEDE, // skip real function; use my return value
} META_RES;
};
// Variables provided to plugins.
typedef struct meta_globals_s {
struct meta_globals_t
{
META_RES mres; // writable; plugin's return flag
META_RES prev_mres; // readable; return flag of the previous plugin called
META_RES status; // readable; "highest" return flag so far
void *orig_ret; // readable; return value from "real" function
void *override_ret; // readable; return value from overriding/superceding plugin
} meta_globals_t;
};
extern meta_globals_t *gpMetaGlobals;
#define SET_META_RESULT(result) gpMetaGlobals->mres = result
#define RETURN_META(result) \
do { gpMetaGlobals->mres = result; return; } while (0)
#define RETURN_META_VALUE(result, value) \
do { gpMetaGlobals->mres = result; return value; } while (0)
#define META_RESULT_STATUS gpMetaGlobals->status
#define META_RESULT_PREVIOUS gpMetaGlobals->prev_mres
#define META_RESULT_ORIG_RET(type) *(type *)gpMetaGlobals->orig_ret
#define META_RESULT_OVERRIDE_RET(type) *(type *)gpMetaGlobals->override_ret
// Table of getapi functions, retrieved from each plugin.
typedef struct {
struct META_FUNCTIONS
{
GETENTITYAPI_FN pfnGetEntityAPI;
GETENTITYAPI_FN pfnGetEntityAPI_Post;
GETENTITYAPI2_FN pfnGetEntityAPI2;
@ -69,13 +73,14 @@ typedef struct {
GETNEWDLLFUNCTIONS_FN pfnGetNewDLLFunctions_Post;
GET_ENGINE_FUNCTIONS_FN pfnGetEngineFunctions;
GET_ENGINE_FUNCTIONS_FN pfnGetEngineFunctions_Post;
} META_FUNCTIONS;
};
// Pair of function tables provided by game DLL.
typedef struct {
struct gamedll_funcs_t
{
DLL_FUNCTIONS *dllapi_table;
NEW_DLL_FUNCTIONS *newapi_table;
} gamedll_funcs_t;
};
// Declared in plugin; referenced in macros.
extern gamedll_funcs_t *gpGamedllFuncs;
@ -91,41 +96,26 @@ typedef void (*META_INIT_FN)();
// Get info about plugin, compare meta_interface versions, provide meta
// utility callback functions.
C_DLLEXPORT int Meta_Query(char *interfaceVersion,
plugin_info_t **plinfo,
mutil_funcs_t *pMetaUtilFuncs);
typedef int (*META_QUERY_FN) (char *interfaceVersion,
plugin_info_t **plinfo,
mutil_funcs_t *pMetaUtilFuncs);
C_DLLEXPORT int Meta_Query(char *interfaceVersion, plugin_info_t **plinfo, mutil_funcs_t *pMetaUtilFuncs);
typedef int (*META_QUERY_FN) (char *interfaceVersion, plugin_info_t **plinfo, mutil_funcs_t *pMetaUtilFuncs);
// Attach the plugin to the API; get the table of getapi functions; give
// meta_globals and gamedll_funcs.
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now,
META_FUNCTIONS *pFunctionTable,
meta_globals_t *pMGlobals,
gamedll_funcs_t *pGamedllFuncs);
typedef int (*META_ATTACH_FN) (PLUG_LOADTIME now,
META_FUNCTIONS *pFunctionTable,
meta_globals_t *pMGlobals,
gamedll_funcs_t *pGamedllFuncs);
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs);
typedef int (*META_ATTACH_FN) (PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs);
// Detach the plugin; tell why and when.
C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
typedef int (*META_DETACH_FN) (PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
// Standard HL SDK interface function prototypes.
C_DLLEXPORT int GetEntityAPI_Post(DLL_FUNCTIONS *pFunctionTable,
int interfaceVersion );
C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable,
int *interfaceVersion );
C_DLLEXPORT int GetEntityAPI_Post(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
// Additional SDK-like interface function prototypes.
C_DLLEXPORT int GetNewDLLFunctions_Post(NEW_DLL_FUNCTIONS *pNewFunctionTable,
int *interfaceVersion );
C_DLLEXPORT int GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine,
int *interfaceVersion);
C_DLLEXPORT int GetEngineFunctions_Post(enginefuncs_t *pengfuncsFromEngine,
int *interfaceVersion);
C_DLLEXPORT int GetNewDLLFunctions_Post(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion );
C_DLLEXPORT int GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion);
C_DLLEXPORT int GetEngineFunctions_Post(enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion);
// Convenience macros for accessing GameDLL functions. Note: these talk
// _directly_ to the gamedll, and are not multiplexed through Metamod to
@ -192,5 +182,3 @@ C_DLLEXPORT int GetEngineFunctions_Post(enginefuncs_t *pengfuncsFromEngine,
#define MNEW_GameShutdown MNEW_FUNC->pfnGameShutdown
#define MNEW_ShouldCollide MNEW_FUNC->pfnShouldCollide
#define MNEW_CvarValue MNEW_FUNC->pfnCvarValue
#endif /* META_API_H */

View File

@ -6,8 +6,7 @@ meta_new_dll_functions_t::meta_new_dll_functions_t(
void (*_pfnGameShutdown) (),
int (*_pfnShouldCollide) (edict_t *, edict_t *),
void (*_pfnCvarValue) (const edict_t *, const char *),
void (*_pfnCvarValue2) (const edict_t *, int, const char *, const char *)
)
void (*_pfnCvarValue2) (const edict_t *, int, const char *, const char *))
{
pfnOnFreeEntPrivateData = _pfnOnFreeEntPrivateData;
pfnGameShutdown = _pfnGameShutdown;
@ -347,6 +346,7 @@ meta_enginefuncs_t::meta_enginefuncs_t(
void HL_enginefuncs_t::initialise_interface(enginefuncs_t *_pFuncs)
{
set_from(_pFuncs);
// Now the pfnAlertMessage is available and we trust it to be a valid
// pointer, so flush the message buffer.
flush_ALERT_buffer();

View File

@ -1,10 +1,5 @@
#pragma once
#include <extdll.h> // NEW_DLL_FUNCTIONS, enginefuncs_t
#include <string.h> // memset()
#include "comp_dep.h"
// We use our own versions of the engine/dll interface structs. We add a
// few dummy entries to the end and set them to 0. That way we are
// protected from updates to the HL SDK adding new functions which would
@ -15,7 +10,6 @@
// meta_new_dll_functions_t
struct meta_new_dll_functions_t: public NEW_DLL_FUNCTIONS {
public:
// functions:
meta_new_dll_functions_t();
meta_new_dll_functions_t(
void (*pfnOnFreeEntPrivateData) (edict_t *),
@ -282,7 +276,6 @@ inline void meta_enginefuncs_t::copy_to(enginefuncs_t *_pFuncs)
//
struct HL_enginefuncs_t: public meta_enginefuncs_t {
public:
// functions:
HL_enginefuncs_t();
// Fill this object with pointers copied from an enginefuncs_t struct
@ -292,8 +285,6 @@ public:
void initialise_interface(enginefuncs_t *pFuncs);
private:
// functions:
public:
// Moving copy_to() and set_from() to the private space.
void set_from(enginefuncs_t *pFuncs) { meta_enginefuncs_t::set_from(pFuncs); };
void copy_to(enginefuncs_t *pFuncs) { meta_enginefuncs_t::copy_to(pFuncs); };

View File

@ -1,7 +1,5 @@
#ifndef METAMOD_H
#define METAMOD_H
#pragma once
#include "comp_dep.h"
#include "meta_api.h" // META_RES, etc
#include "mlist.h" // MPluginList, etc
#include "mreg.h" // MRegCmdList, etc
@ -33,7 +31,8 @@ extern DLHANDLE metamod_handle;
extern cvar_t meta_version;
// Info about the game dll/mod.
typedef struct gamedll_s {
struct gamedll_t
{
char name[NAME_MAX]; // ie "cstrike" (from gamedir)
const char *desc; // ie "Counter-Strike"
char gamedir[PATH_MAX]; // ie "/home/willday/half-life/cstrike"
@ -42,7 +41,8 @@ typedef struct gamedll_s {
char real_pathname[PATH_MAX]; // in case pathname overridden by bot, etc
DLHANDLE handle;
gamedll_funcs_t funcs; // dllapi_table, newapi_table
} gamedll_t;
};
extern gamedll_t GameDLL;
// SDK variables for storing engine funcs and globals.
@ -145,26 +145,21 @@ mBOOL meta_load_gamedll();
// accept. Thus there are "_void" versions of the 5 macros; these are
// listed first.
// ===== macros for void-returning functions ==================================
// macros for void-returning functions
// return ()
#define RETURN_API_void() \
return;
// ===== macros for type-returning functions ==================================
// macros for type-returning functions
// return a value
#define RETURN_API(ret_t) \
{ return GET_RET_CLASS(ret_val, ret_t); }
// ===== end macros ===========================================================
#ifdef META_PERFMON
// ============================================================================
// Api-hook performance monitoring
// ============================================================================
extern long double total_tsc;
extern unsigned long long count_tsc;
extern unsigned long long active_tsc;
@ -202,19 +197,11 @@ inline unsigned long long GET_TSC() {
min_tsc = run_tsc; \
}
// ===== end ==================================================================
#else
// ===== performance monitor disabled =========================================
#define API_START_TSC_TRACKING()
#define API_PAUSE_TSC_TRACKING()
#define API_UNPAUSE_TSC_TRACKING()
#define API_END_TSC_TRACKING()
// ===== end ==================================================================
#endif /*META_PERFMON*/
#endif /* METAMOD_H */
#endif // META_PERFMON

View File

View File

@ -143,7 +143,8 @@ mBOOL MPlugin::cmd_parseline(const char *line)
// Grab description.
// Specify no delimiter chars, as we just want the rest of the line.
token=strtok_r(NULL, "", &ptr_token);
if (token) {
if (token)
{
token = token + strspn(token, " \t"); // skip whitespace
Q_strncpy(desc, token, sizeof(desc) - 1);
@ -255,7 +256,8 @@ mBOOL MPlugin::resolve()
char *found;
char *cp;
int len;
if (!check_input()) {
if (!check_input())
{
// details logged, meta_errno set in check_input()
return mFALSE;
}
@ -306,7 +308,8 @@ mBOOL MPlugin::resolve()
// GAMEDIR/dlls/filename
// meta_errno values:
// - none
char *MPlugin::resolve_dirs(const char *path) {
char *MPlugin::resolve_dirs(const char *path)
{
struct stat st;
static char buf[PATH_MAX];
char *found;
@ -336,7 +339,8 @@ char *MPlugin::resolve_dirs(const char *path) {
// dir/file
// meta_errno values:
// - none
char *MPlugin::resolve_prefix(const char *path) {
char *MPlugin::resolve_prefix(const char *path)
{
struct stat st;
char *cp, *fname;
char dname[PATH_MAX];
@ -383,14 +387,16 @@ char *MPlugin::resolve_prefix(const char *path) {
// path_i386.so, path_i486.so, etc (if linux)
// meta_errno values:
// - none
char *MPlugin::resolve_suffix(const char *path) {
char *MPlugin::resolve_suffix(const char *path)
{
struct stat st;
static char buf[PATH_MAX];
static char tmpbuf[PATH_MAX];
char *found;
// Hmm, recursion.
if (!Q_strstr(path, "_mm")) {
if (!Q_strstr(path, "_mm"))
{
safevoid_snprintf(buf, sizeof(buf), "%s_mm", path);
Q_memcpy(tmpbuf,buf,sizeof(tmpbuf));
found = resolve_suffix(tmpbuf);
@ -398,7 +404,8 @@ char *MPlugin::resolve_suffix(const char *path) {
return found;
}
if (!Q_strstr(path, "_MM")) {
if (!Q_strstr(path, "_MM"))
{
safevoid_snprintf(buf, sizeof(buf), "%s_MM", path);
Q_memcpy(tmpbuf,buf,sizeof(tmpbuf));
found = resolve_suffix(tmpbuf);
@ -408,11 +415,10 @@ char *MPlugin::resolve_suffix(const char *path) {
#ifdef _WIN32
safevoid_snprintf(buf, sizeof(buf), "%s.dll", path);
#elif defined(linux)
safevoid_snprintf(buf, sizeof(buf), "%s.so", path);
#else
#error "OS unrecognized"
#endif /* _WIN32 */
safevoid_snprintf(buf, sizeof(buf), "%s.so", path);
#endif
if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
return buf;
@ -431,16 +437,18 @@ char *MPlugin::resolve_suffix(const char *path) {
return buf;
#endif
return NULL;
return nullptr;
}
// Check if a passed string starts with a known platform postfix.
// It does not check beyond the period in order to work for both
// Linux and Win32.
mBOOL MPlugin::is_platform_postfix(const char *pf) {
mBOOL MPlugin::is_platform_postfix(const char *pf)
{
typedef struct { const char *postfix; size_t len; } postfix_t;
static const postfix_t postfixes[] = {
static const postfix_t postfixes[] =
{
{"_i386.", 6},
{"_i686.", 6},
{"_amd64.", 7},
@ -454,7 +462,8 @@ mBOOL MPlugin::is_platform_postfix(const char *pf) {
if (!pf)
return mFALSE;
for (const postfix_t * plist = postfixes; plist->postfix; plist++) {
for (const postfix_t *plist = postfixes; plist->postfix; plist++)
{
if (!Q_strncmp(pf, plist->postfix, plist->len))
return mTRUE;
}
@ -475,7 +484,8 @@ mBOOL MPlugin::is_platform_postfix(const char *pf) {
// the part up to the last dot, if one exists.
// meta_errno values:
// - none
mBOOL MPlugin::platform_match(MPlugin* other) {
mBOOL MPlugin::platform_match(MPlugin *other)
{
char *end, *other_end;
int prefixlen;
@ -522,35 +532,44 @@ mBOOL MPlugin::platform_match(MPlugin* other) {
// - errno's from query()
// - errno's from attach()
// - errno's from check_input()
mBOOL MPlugin::load(PLUG_LOADTIME now) {
if (!check_input()) {
mBOOL MPlugin::load(PLUG_LOADTIME now)
{
if (!check_input())
{
// details logged, meta_errno set in check_input()
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
}
if (status >= PL_RUNNING) {
if (status >= PL_RUNNING)
{
META_WARNING("dll: Not loading plugin '%s'; already loaded (status=%s)",
desc, str_status());
RETURN_ERRNO(mFALSE, ME_ALREADY);
}
if (action != PA_LOAD && action != PA_ATTACH && action != PA_RELOAD) {
if (action != PA_LOAD && action != PA_ATTACH && action != PA_RELOAD)
{
META_WARNING("dll: Not loading plugin '%s'; not marked for load (action=%s)", desc, str_action());
RETURN_ERRNO(mFALSE, ME_BADREQ);
}
if (status <= PL_OPENED) {
if (status <= PL_OPENED)
{
// query plugin; open file and get info about it
if (!query()) {
if (!query())
{
META_WARNING("dll: Skipping plugin '%s'; couldn't query", desc);
if (meta_errno != ME_DLOPEN) {
if (DLCLOSE(handle) != 0) {
META_WARNING("dll: Couldn't close plugin file '%s': %s",
file, DLERROR());
if (meta_errno != ME_DLOPEN)
{
if (DLCLOSE(handle) != 0)
{
META_WARNING("dll: Couldn't close plugin file '%s': %s", file, DLERROR());
}
else
handle=NULL;
handle = nullptr;
}
status = PL_BADFILE;
info=NULL; // prevent crash
info = nullptr; // prevent crash
// meta_errno should be already set in query()
return mFALSE;
}
@ -558,16 +577,18 @@ mBOOL MPlugin::load(PLUG_LOADTIME now) {
}
// are we allowed to attach this plugin at this time?
if (info->loadable < now) {
if (info->loadable > PT_STARTUP) {
if (info->loadable < now)
{
if (info->loadable > PT_STARTUP)
{
// will try to attach again at next opportunity
META_DEBUG(2, ("dll: Delaying load plugin '%s'; can't attach now: allowed=%s; now=%s",
desc, str_loadable(), str_loadtime(now, SL_SIMPLE)));
META_DEBUG(2, ("dll: Delaying load plugin '%s'; can't attach now: allowed=%s; now=%s", desc, str_loadable(), str_loadtime(now, SL_SIMPLE)));
RETURN_ERRNO(mFALSE, ME_DELAYED);
}
else {
META_DEBUG(2, ("dll: Failed load plugin '%s'; can't attach now: allowed=%s; now=%s",
desc, str_loadable(), str_loadtime(now, SL_SIMPLE)));
else
{
META_DEBUG(2, ("dll: Failed load plugin '%s'; can't attach now: allowed=%s; now=%s", desc, str_loadable(), str_loadtime(now, SL_SIMPLE)));
// don't try to attach again later
action = PA_NONE;
RETURN_ERRNO(mFALSE, ME_NOTALLOWED);
@ -575,13 +596,15 @@ mBOOL MPlugin::load(PLUG_LOADTIME now) {
}
// attach plugin; get function tables
if (attach(now) != mTRUE) {
if (attach(now) != mTRUE)
{
META_WARNING("dll: Failed to attach plugin '%s'", desc);
// Note we don't dlclose() here, since we're returning PL_FAILED,
// which implies that it's been dlopened and queried successfully.
// Doing so causes crashes, because things like "meta list" try to
// look at *info, which is in the DLL memory space and unaccessible
// (segfault) after dlclosed.
status = PL_FAILED;
// meta_errno should be already set in attach()
return mFALSE;
@ -592,19 +615,19 @@ mBOOL MPlugin::load(PLUG_LOADTIME now) {
// If not loading at server startup, then need to call plugin's
// GameInit, since we've passed that.
if (now != PT_STARTUP) {
FN_GAMEINIT pfn_gameinit=NULL;
if (now != PT_STARTUP)
{
FN_GAMEINIT pfn_gameinit = nullptr;
if (tables.dllapi && (pfn_gameinit=tables.dllapi->pfnGameInit))
pfn_gameinit();
}
// If loading during map, then I'd like to call plugin's
// ServerActivate, since we've passed that. However, I'm not sure what
// arguments to give it... So, we'll just have to say for the
// moment that plugins that are loadable during a map can't need to
// hook ServerActivate.
META_LOG("dll: Loaded plugin '%s': %s v%s %s, %s", desc, info->name,
info->version, info->date, info->author);
META_LOG("dll: Loaded plugin '%s': %s v%s %s, %s", desc, info->name, info->version, info->date, info->author);
return mTRUE;
}
@ -628,9 +651,9 @@ mBOOL MPlugin::query()
META_QUERY_FN pfn_query;
// open the plugin DLL
if (!(handle=DLOPEN(pathname))) {
META_WARNING("dll: Failed query plugin '%s'; Couldn't open file '%s': %s",
desc, pathname, DLERROR());
if (!(handle = DLOPEN(pathname)))
{
META_WARNING("dll: Failed query plugin '%s'; Couldn't open file '%s': %s", desc, pathname, DLERROR());
RETURN_ERRNO(mFALSE, ME_DLOPEN);
}
@ -645,7 +668,8 @@ mBOOL MPlugin::query()
// engine functions like AlertMessage, which have to be passed along via
// GiveFnptrsToDll.
pfn_query = (META_QUERY_FN) DLSYM(handle, "Meta_Query");
if (!pfn_query) {
if (!pfn_query)
{
META_WARNING("dll: Failed query plugin '%s'; Couldn't find Meta_Query(): %s", desc, DLERROR());
// caller will dlclose()
RETURN_ERRNO(mFALSE, ME_DLMISSING);
@ -666,41 +690,47 @@ mBOOL MPlugin::query()
// plugin can NOT use any Engine functions, as they haven't been
// provided yet (done next, in GiveFnptrsToDll).
pfn_init = (META_INIT_FN) DLSYM(handle, "Meta_Init");
if (pfn_init) {
if (pfn_init)
{
pfn_init();
META_DEBUG(6, ("dll: Plugin '%s': Called Meta_Init()", desc));
}
else {
else
{
META_DEBUG(5, ("dll: no Meta_Init present in plugin '%s'", desc));
// don't return; not an error
}
// pass on engine function table and globals to plugin
if (!(pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN) DLSYM(handle, "GiveFnptrsToDll"))) {
if (!(pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN) DLSYM(handle, "GiveFnptrsToDll")))
{
// META_WARNING("dll: Couldn't find GiveFnptrsToDll() in plugin '%s': %s", desc, DLERROR());
META_WARNING("dll: Failed query plugin '%s'; Couldn't find GiveFnptrsToDll(): %s", desc, DLERROR());
// caller will dlclose()
RETURN_ERRNO(mFALSE, ME_DLMISSING);
}
pfn_give_engfuncs(Engine.pl_funcs, Engine.globals);
META_DEBUG(6, ("dll: Plugin '%s': Called GiveFnptrsToDll()", desc));
// Call plugin's Meta_Query(), to pass our meta interface version, and get
// plugin's info structure.
meta_errno = ME_NOERROR;
info=NULL;
info = nullptr;
// Make a copy of the meta_util function table for each plugin, for the
// same reason.
Q_memcpy(&mutil_funcs, &MetaUtilFunctions, sizeof(mutil_funcs));
if (pfn_query(META_INTERFACE_VERSION, &info, &mutil_funcs) != TRUE) {
META_WARNING("dll: Failed query plugin '%s'; Meta_Query returned error",
desc);
meta_errno=ME_DLERROR;
if (pfn_query(META_INTERFACE_VERSION, &info, &mutil_funcs))
{
META_DEBUG(6, ("dll: Plugin '%s': Called Meta_Query() successfully", desc));
}
else {
META_DEBUG(6, ("dll: Plugin '%s': Called Meta_Query() successfully",
desc));
else
{
META_WARNING("dll: Failed query plugin '%s'; Meta_Query returned error", desc);
meta_errno = ME_DLERROR;
}
// Check for interface differences... Generally, a difference in major
@ -712,20 +742,24 @@ mBOOL MPlugin::query()
//
// Note, this check is done regardless of whether meta_query returns an
// error.
if (info && !FStrEq(info->ifvers, META_INTERFACE_VERSION)) {
if (info && !FStrEq(info->ifvers, META_INTERFACE_VERSION))
{
int mmajor = 0, mminor = 0, pmajor = 0, pminor = 0;
META_DEBUG(3, ("dll: Note: Plugin '%s' interface version didn't match; expected %s, found %s", desc, META_INTERFACE_VERSION, info->ifvers));
sscanf(META_INTERFACE_VERSION, "%d:%d", &mmajor, &mminor);
sscanf(info->ifvers, "%d:%d", &pmajor, &pminor);
// If plugin has later interface version, it's incompatible
// (update metamod).
if (pmajor > mmajor || (pmajor==mmajor && pminor > mminor)) {
if (pmajor > mmajor || (pmajor == mmajor && pminor > mminor))
{
META_WARNING("dll: Plugin '%s' requires a newer version of Metamod (Metamod needs at least interface %s not the current %s)", desc, info->ifvers, META_INTERFACE_VERSION);
meta_errno = ME_IFVERSION;
}
// If plugin has older major interface version, it's incompatible
// (update plugin).
else if (pmajor < mmajor) {
else if (pmajor < mmajor)
{
META_WARNING("dll: Plugin '%s' is out of date and incompatible with this version of Metamod; please find a newer version of the plugin (plugin needs at least interface %s not the current %s)", desc, META_INTERFACE_VERSION, info->ifvers);
meta_errno = ME_IFVERSION;
}
@ -734,23 +768,27 @@ mBOOL MPlugin::query()
else if (pmajor == mmajor && pminor < mminor)
META_LOG("dll: Note: plugin '%s' is using an older interface version (%s), not the latest interface version (%s); there might be an updated version of the plugin", desc, info->ifvers, META_INTERFACE_VERSION);
else
META_LOG("dll: Plugin '%s': unexpected version comparision; metavers=%s, mmajor=%d, mminor=%d; plugvers=%s, pmajor=%d, pminor=%d",
desc, META_INTERFACE_VERSION, mmajor, mminor, info->ifvers, pmajor, pminor);
META_LOG("dll: Plugin '%s': unexpected version comparision; metavers=%s, mmajor=%d, mminor=%d; plugvers=%s, pmajor=%d, pminor=%d", desc, META_INTERFACE_VERSION, mmajor, mminor, info->ifvers, pmajor, pminor);
}
if (meta_errno == ME_IFVERSION) {
if (meta_errno == ME_IFVERSION)
{
META_WARNING("dll: Rejected plugin '%s' due to interface version incompatibility (mm=%s, pl=%s)", desc, META_INTERFACE_VERSION, info->ifvers);
// meta_errno is set already above
// caller will dlclose()
return mFALSE;
}
else if (meta_errno != ME_NOERROR) {
else if (meta_errno != ME_NOERROR)
{
// some other error, already logged
return mFALSE;
}
if (!info) {
if (!info)
{
META_WARNING("dll: Failed query plugin '%s'; Empty info structure", desc);
// caller will dlclose()
RETURN_ERRNO(mFALSE, ME_NULLRESULT);
}
@ -761,24 +799,20 @@ mBOOL MPlugin::query()
desc[sizeof(desc) - 1] = '\0';
}
//
// Give plugin the p-series extension function table.
// Check for version differences!
//
if (NULL!=(pfn_give_pext_funcs=(META_GIVE_PEXT_FUNCTIONS_FN) DLSYM(handle, "Meta_PExtGiveFnptrs"))) {
if ((pfn_give_pext_funcs = (META_GIVE_PEXT_FUNCTIONS_FN)DLSYM(handle, "Meta_PExtGiveFnptrs")))
{
plugin_pext_version = (*pfn_give_pext_funcs)(META_PEXT_VERSION, (pextension_funcs_t*)(&(mutil_funcs.pfnLoadPlugin)));
// if plugin is newer, we got incompatibility problem!
if (plugin_pext_version > META_PEXT_VERSION) {
META_WARNING("dll: Plugin '%s' requires a newer version of Metamod-P (extension interface needs to be at least %d not the current %d)",
desc,
plugin_pext_version,
META_PEXT_VERSION);
if (plugin_pext_version > META_PEXT_VERSION)
{
META_WARNING("dll: Plugin '%s' requires a newer version of Metamod-P (extension interface needs to be at least %d not the current %d)", desc, plugin_pext_version, META_PEXT_VERSION);
}
}
META_DEBUG(6, ("dll: Plugin '%s': Query successful", desc));
return mTRUE;
}
@ -801,7 +835,8 @@ mBOOL MPlugin::query()
// - ME_DLMISSING couldn't find meta_attach() in plugin
// - ME_DLERROR plugin attach() returned error
// - ME_NOMEM failed malloc
mBOOL MPlugin::attach(PLUG_LOADTIME now) {
mBOOL MPlugin::attach(PLUG_LOADTIME now)
{
int ret;
int iface_vers;
@ -810,9 +845,11 @@ mBOOL MPlugin::attach(PLUG_LOADTIME now) {
// Make copy of gameDLL's function tables for each plugin, so we don't
// risk the plugins screwing with the tables everyone uses.
if (!gamedll_funcs.dllapi_table) {
if (!gamedll_funcs.dllapi_table)
{
gamedll_funcs.dllapi_table = (DLL_FUNCTIONS *) calloc(1, sizeof(DLL_FUNCTIONS));
if (!gamedll_funcs.dllapi_table) {
if (!gamedll_funcs.dllapi_table)
{
META_WARNING("dll: Failed attach plugin '%s': Failed malloc() for dllapi_table");
RETURN_ERRNO(mFALSE, ME_NOMEM);
}
@ -821,9 +858,12 @@ mBOOL MPlugin::attach(PLUG_LOADTIME now) {
else
Q_memset(gamedll_funcs.dllapi_table, 0, sizeof(DLL_FUNCTIONS));
}
if (!gamedll_funcs.newapi_table) {
if (!gamedll_funcs.newapi_table)
{
gamedll_funcs.newapi_table = (NEW_DLL_FUNCTIONS *) calloc(1, sizeof(NEW_DLL_FUNCTIONS));
if (!gamedll_funcs.newapi_table) {
if (!gamedll_funcs.newapi_table)
{
META_WARNING("dll: Failed attach plugin '%s': Failed malloc() for newapi_table");
RETURN_ERRNO(mFALSE, ME_NOMEM);
}
@ -832,7 +872,9 @@ mBOOL MPlugin::attach(PLUG_LOADTIME now) {
else
Q_memset(gamedll_funcs.newapi_table, 0, sizeof(NEW_DLL_FUNCTIONS));
}
if (!(pfn_attach = (META_ATTACH_FN) DLSYM(handle, "Meta_Attach"))) {
if (!(pfn_attach = (META_ATTACH_FN) DLSYM(handle, "Meta_Attach")))
{
META_WARNING("dll: Failed attach plugin '%s': Couldn't find Meta_Attach(): %s", desc, DLERROR());
// caller will dlclose()
RETURN_ERRNO(mFALSE, ME_DLMISSING);
@ -842,7 +884,8 @@ mBOOL MPlugin::attach(PLUG_LOADTIME now) {
// get table of function tables,
// give public meta globals
ret = pfn_attach(now, &meta_table, &PublicMetaGlobals, &gamedll_funcs);
if (ret != TRUE) {
if (ret != TRUE)
{
META_WARNING("dll: Failed attach plugin '%s': Error from Meta_Attach(): %d", desc, ret);
// caller will dlclose()
RETURN_ERRNO(mFALSE, ME_DLERROR);
@ -871,57 +914,37 @@ mBOOL MPlugin::attach(PLUG_LOADTIME now) {
META_DEBUG(5, ("dll: Plugin '%s': No %s", desc, STR_GetFuncs));\
if (struct_field)\
free(struct_field);\
struct_field=NULL; \
struct_field = nullptr;\
}
// Look for API-NEW interface in plugin. We do this before API2/API, because
// that's what the engine appears to do..
iface_vers = NEW_DLL_FUNCTIONS_VERSION;
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetNewDLLFunctions,
"GetNewDLLFunctions", tables.newapi,
NEW_DLL_FUNCTIONS_FN, NEW_DLL_FUNCTIONS, sizeof(NEW_DLL_FUNCTIONS),
&iface_vers, iface_vers, NEW_DLL_FUNCTIONS_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetNewDLLFunctions, "GetNewDLLFunctions", tables.newapi, NEW_DLL_FUNCTIONS_FN, NEW_DLL_FUNCTIONS, sizeof(NEW_DLL_FUNCTIONS), &iface_vers, iface_vers, NEW_DLL_FUNCTIONS_VERSION);
iface_vers = NEW_DLL_FUNCTIONS_VERSION;
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetNewDLLFunctions_Post,
"GetNewDLLFunctions_Post", post_tables.newapi,
NEW_DLL_FUNCTIONS_FN, NEW_DLL_FUNCTIONS, sizeof(NEW_DLL_FUNCTIONS),
&iface_vers, iface_vers, NEW_DLL_FUNCTIONS_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetNewDLLFunctions_Post, "GetNewDLLFunctions_Post", post_tables.newapi, NEW_DLL_FUNCTIONS_FN, NEW_DLL_FUNCTIONS, sizeof(NEW_DLL_FUNCTIONS), &iface_vers, iface_vers, NEW_DLL_FUNCTIONS_VERSION);
// Look for API2 interface in plugin; preferred over API-1.
iface_vers = INTERFACE_VERSION;
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI2,
"GetEntityAPI2", tables.dllapi,
APIFUNCTION2, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS),
&iface_vers, iface_vers, INTERFACE_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI2, "GetEntityAPI2", tables.dllapi, APIFUNCTION2, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS), &iface_vers, iface_vers, INTERFACE_VERSION);
iface_vers = INTERFACE_VERSION;
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI2_Post,
"GetEntityAPI2_Post", post_tables.dllapi,
APIFUNCTION2, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS),
&iface_vers, iface_vers, INTERFACE_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI2_Post, "GetEntityAPI2_Post", post_tables.dllapi, APIFUNCTION2, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS), &iface_vers, iface_vers, INTERFACE_VERSION);
// Look for old-style API in plugin, if API2 interface wasn't found.
if (!tables.dllapi && !post_tables.dllapi) {
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI,
"GetEntityAPI", tables.dllapi,
APIFUNCTION, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS),
INTERFACE_VERSION, INTERFACE_VERSION, INTERFACE_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI_Post,
"GetEntityAPI_Post", post_tables.dllapi,
APIFUNCTION, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS),
INTERFACE_VERSION, INTERFACE_VERSION, INTERFACE_VERSION);
if (!tables.dllapi && !post_tables.dllapi)
{
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI, "GetEntityAPI", tables.dllapi, APIFUNCTION, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS), INTERFACE_VERSION, INTERFACE_VERSION, INTERFACE_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEntityAPI_Post, "GetEntityAPI_Post", post_tables.dllapi, APIFUNCTION, DLL_FUNCTIONS, sizeof(DLL_FUNCTIONS), INTERFACE_VERSION, INTERFACE_VERSION, INTERFACE_VERSION);
}
// Look for Engine interface.
iface_vers = ENGINE_INTERFACE_VERSION;
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEngineFunctions,
"GetEngineFunctions", tables.engine,
GET_ENGINE_FUNCTIONS_FN, enginefuncs_t, sizeof(enginefuncs_t),
&iface_vers, iface_vers, ENGINE_INTERFACE_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEngineFunctions, "GetEngineFunctions", tables.engine, GET_ENGINE_FUNCTIONS_FN, enginefuncs_t, sizeof(enginefuncs_t), &iface_vers, iface_vers, ENGINE_INTERFACE_VERSION);
iface_vers = ENGINE_INTERFACE_VERSION;
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEngineFunctions_Post,
"GetEngineFunctions_Post", post_tables.engine,
GET_ENGINE_FUNCTIONS_FN, enginefuncs_t, sizeof(enginefuncs_t),
&iface_vers, iface_vers, ENGINE_INTERFACE_VERSION);
GET_FUNC_TABLE_FROM_PLUGIN(pfnGetEngineFunctions_Post, "GetEngineFunctions_Post", post_tables.engine, GET_ENGINE_FUNCTIONS_FN, enginefuncs_t, sizeof(enginefuncs_t), &iface_vers, iface_vers, ENGINE_INTERFACE_VERSION);
if (!tables.dllapi && !post_tables.dllapi
&& !tables.newapi && !post_tables.newapi
@ -937,26 +960,31 @@ mBOOL MPlugin::attach(PLUG_LOADTIME now) {
// Unload a plugin from plugin request
// meta_errno values:
// - errno's from unload()
mBOOL MPlugin::plugin_unload(plid_t plid, PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
mBOOL MPlugin::plugin_unload(plid_t plid, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
{
PLUG_ACTION old_action;
MPlugin *pl_unloader;
// try find unloader
if (!(pl_unloader=Plugins->find(plid))) {
if (!(pl_unloader = Plugins->find(plid)))
{
META_WARNING("dll: Not unloading plugin '%s'; plugin that requested unload is not found.", desc);
RETURN_ERRNO(mFALSE, ME_BADREQ);
}
// self check. Do not allow plugin to unload itself!
else if (pl_unloader->index == index) {
else if (pl_unloader->index == index)
{
META_WARNING("dll: Not unloading plugin '%s'; Plugin tried to unload itself.", desc);
RETURN_ERRNO(mFALSE, ME_UNLOAD_SELF);
}
// safe check. Do not allow active unloader to be unloaded!
else if (is_unloader) {
else if (is_unloader)
{
META_WARNING("dll: Not unloading plugin '%s'; Plugin is unloading plugin that tried to unload it.", desc);
RETURN_ERRNO(mFALSE, ME_UNLOAD_UNLOADER);
}
else {
else
{
unloader_index = pl_unloader->index;
}
@ -966,7 +994,8 @@ mBOOL MPlugin::plugin_unload(plid_t plid, PLUG_LOADTIME now, PL_UNLOAD_REASON re
// try unload
old_action = action;
action = PA_UNLOAD;
if (unload(now, reason, (reason==PNL_CMD_FORCED) ? PNL_PLG_FORCED : PNL_PLUGIN)) {
if (unload(now, reason, (reason == PNL_CMD_FORCED) ? PNL_PLG_FORCED : PNL_PLUGIN))
{
META_DEBUG(1,("Unloaded plugin '%s'", desc));
pl_unloader->is_unloader = mFALSE;
return mTRUE;
@ -975,7 +1004,8 @@ mBOOL MPlugin::plugin_unload(plid_t plid, PLUG_LOADTIME now, PL_UNLOAD_REASON re
pl_unloader->is_unloader = mFALSE;
// Cannot unload plugin now. Don't set delayed mode.
if (meta_errno==ME_DELAYED) {
if (meta_errno == ME_DELAYED)
{
action = old_action;
meta_errno = ME_NOTALLOWED;
META_DEBUG(2, ("dll: Failed unload plugin '%s'; can't detach now: allowed=%s; now=%s", desc, str_unloadable(), str_loadtime(PT_ANYTIME, SL_SIMPLE)));
@ -992,36 +1022,48 @@ mBOOL MPlugin::plugin_unload(plid_t plid, PLUG_LOADTIME now, PL_UNLOAD_REASON re
// - ME_DELAYED unload request is delayed (till changelevel?)
// - ME_NOTALLOWED plugin not unloadable after startup
// - errno's from check_input()
mBOOL MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, PL_UNLOAD_REASON real_reason) {
if (!check_input()) {
mBOOL MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, PL_UNLOAD_REASON real_reason)
{
if (!check_input())
{
// details logged, meta_errno set in check_input()
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
}
if (status < PL_RUNNING) {
if (reason != PNL_CMD_FORCED && reason != PNL_RELOAD) {
if (status < PL_RUNNING)
{
if (reason != PNL_CMD_FORCED && reason != PNL_RELOAD)
{
META_WARNING("dll: Not unloading plugin '%s'; already unloaded (status=%s)", desc, str_status());
RETURN_ERRNO(mFALSE, ME_ALREADY);
}
}
if (action != PA_UNLOAD && action != PA_RELOAD) {
if (action != PA_UNLOAD && action != PA_RELOAD)
{
META_WARNING("dll: Not unloading plugin '%s'; not marked for unload (action=%s)", desc, str_action());
RETURN_ERRNO(mFALSE, ME_BADREQ);
}
// Are we allowed to detach this plugin at this time?
// If forcing unload, we disregard when plugin wants to be unloaded.
if (info && info->unloadable < now) {
if (reason == PNL_CMD_FORCED) {
if (info && info->unloadable < now)
{
if (reason == PNL_CMD_FORCED)
{
META_DEBUG(2, ("dll: Forced unload plugin '%s' overriding allowed times: allowed=%s; now=%s", desc, str_unloadable(), str_loadtime(now, SL_SIMPLE)));
}
else {
if (info->unloadable > PT_STARTUP) {
else
{
if (info->unloadable > PT_STARTUP)
{
META_DEBUG(2, ("dll: Delaying unload plugin '%s'; can't detach now: allowed=%s; now=%s", desc, str_unloadable(), str_loadtime(now, SL_SIMPLE)));
// caller should give message to user
// try to unload again at next opportunity
RETURN_ERRNO(mFALSE, ME_DELAYED);
}
else {
else
{
META_DEBUG(2, ("dll: Failed unload plugin '%s'; can't detach now: allowed=%s; now=%s", desc, str_unloadable(), str_loadtime(now, SL_SIMPLE)));
// don't try to unload again later
action = PA_NONE;
@ -1036,14 +1078,18 @@ mBOOL MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, PL_UNLOAD_REAS
// indicates these two routines should match call for call.
// detach plugin
if (!detach(now, reason)) {
if (reason == PNL_RELOAD) {
if (!detach(now, reason))
{
if (reason == PNL_RELOAD)
{
META_DEBUG(2, ("dll: Reload plugin '%s' overriding failed detach", desc));
}
else if (reason == PNL_CMD_FORCED) {
else if (reason == PNL_CMD_FORCED)
{
META_DEBUG(2, ("dll: Forced unload plugin '%s' overriding failed detach", desc));
}
else {
else
{
META_WARNING("dll: Failed to detach plugin '%s'; ", desc);
// meta_errno should be already set in detach()
return mFALSE;
@ -1057,27 +1103,33 @@ mBOOL MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, PL_UNLOAD_REAS
// Unmark registered commands for this plugin (by index number).
RegCmds->disable(index);
// Unmark registered cvars for this plugin (by index number).
RegCvars->disable(index);
// Close the file. Note: after this, attempts to reference any memory
// locations in the file will produce a segfault.
if (DLCLOSE(handle) != 0) {
if (DLCLOSE(handle) != 0)
{
// If DLL cannot be closed, OS is badly broken or we are giving invalid handle.
// So we don't return here but instead remove plugin from our listings.
META_WARNING("dll: Couldn't dlclose plugin file '%s': %s", file, DLERROR());
}
handle=NULL;
if (action==PA_UNLOAD) {
handle = nullptr;
if (action == PA_UNLOAD)
{
status = PL_EMPTY;
clear();
}
else if (action==PA_RELOAD) {
else if (action == PA_RELOAD)
{
status = PL_VALID;
action = PA_LOAD;
clear();
}
META_LOG("dll: Unloaded plugin '%s' for reason '%s'", desc, str_reason(reason, real_reason));
return mTRUE;
}
@ -1087,7 +1139,8 @@ mBOOL MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, PL_UNLOAD_REAS
// -
// - ME_DLMISSING couldn't find meta_detach() in plugin
// - ME_DLERROR plugin detach() returned error
mBOOL MPlugin::detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
mBOOL MPlugin::detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
{
int ret;
META_DETACH_FN pfn_detach;
@ -1097,17 +1150,20 @@ mBOOL MPlugin::detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
if (!handle)
return mTRUE;
if (!(pfn_detach = (META_DETACH_FN) DLSYM(handle, "Meta_Detach"))) {
if (!(pfn_detach = (META_DETACH_FN) DLSYM(handle, "Meta_Detach")))
{
META_WARNING("dll: Error detach plugin '%s': Couldn't find Meta_Detach(): %s", desc, DLERROR());
// caller will dlclose()
RETURN_ERRNO(mFALSE, ME_DLMISSING);
}
ret = pfn_detach(now, reason);
if (ret != TRUE) {
if (ret != TRUE)
{
META_WARNING("dll: Failed detach plugin '%s': Error from Meta_Detach(): %d", desc, ret);
RETURN_ERRNO(mFALSE, ME_DLERROR);
}
META_DEBUG(6, ("dll: Plugin '%s': Called Meta_Detach() successfully", desc));
return mTRUE;
}
@ -1118,22 +1174,27 @@ mBOOL MPlugin::detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
// - errno's from check_input()
// - errno's from unload()
// - errno's from load()
mBOOL MPlugin::reload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
if (!check_input()) {
mBOOL MPlugin::reload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
{
if (!check_input())
{
// details logged, meta_errno set in check_input()
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
}
// Are we allowed to load this plugin at this time?
// If we cannot load the plugin after unloading it, we keep it.
if (info && info->loadable < now) {
if (info->loadable > PT_STARTUP) {
if (info && info->loadable < now)
{
if (info->loadable > PT_STARTUP)
{
META_DEBUG(2, ("dll: Delaying reload plugin '%s'; would not be able to reattach now: allowed=%s; now=%s", desc, str_loadable(), str_loadtime(now, SL_SIMPLE)));
// caller should give message to user
// try to reload again at next opportunity
RETURN_ERRNO(mFALSE, ME_DELAYED);
}
else {
else
{
META_DEBUG(2, ("dll: Failed reload plugin '%s'; would not be able to reattach now: allowed=%s; now=%s", desc, str_loadable(), str_loadtime(now, SL_SIMPLE)));
// don't try to reload again later
action = PA_NONE;
@ -1142,20 +1203,26 @@ mBOOL MPlugin::reload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
}
// this is to fix unloading
if (status < PL_RUNNING) {
if (status < PL_RUNNING)
{
META_WARNING("dll: Plugin '%s' isn't running; Forcing unload plugin for reloading", desc);
reason = PNL_RELOAD;
}
if (!unload(now, reason, reason)) {
if (!unload(now, reason, reason))
{
META_WARNING("dll: Failed to unload plugin '%s' for reloading", desc);
// meta_errno should be set already in unload()
return mFALSE;
}
if (!load(now)) {
if (!load(now))
{
META_WARNING("dll: Failed to reload plugin '%s' after unloading", desc);
// meta_errno should be set already in load()
return mFALSE;
}
return mTRUE;
}
@ -1166,17 +1233,21 @@ mBOOL MPlugin::reload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
// - ME_NOTALLOWED plugin doesn't want to be paused
mBOOL MPlugin::pause()
{
if (status == PL_PAUSED) {
if (status == PL_PAUSED)
{
META_WARNING("Not pausing plugin '%s'; already paused", desc);
RETURN_ERRNO(mFALSE, ME_ALREADY);
}
if (status != PL_RUNNING) {
if (status != PL_RUNNING)
{
META_WARNING("Cannot pause plugin '%s'; not currently running (status=%s)", desc, str_status());
RETURN_ERRNO(mFALSE, ME_BADREQ);
}
// are we allowed to pause this plugin?
if (info->unloadable < PT_ANYPAUSE) {
if (info->unloadable < PT_ANYPAUSE)
{
META_WARNING("Cannot pause plugin '%s'; not allowed by plugin (allowed=%s)", desc, str_unloadable());
action = PA_NONE;
RETURN_ERRNO(mFALSE, ME_NOTALLOWED);
@ -1192,10 +1263,12 @@ mBOOL MPlugin::pause()
// - ME_BADREQ can't unpause; not paused
mBOOL MPlugin::unpause()
{
if (status != PL_PAUSED) {
if (status != PL_PAUSED)
{
META_WARNING("Cannot unpause plugin '%s'; not currently paused (status=%s)", desc, str_status());
RETURN_ERRNO(mFALSE, ME_BADREQ);
}
status = PL_RUNNING;
META_LOG("Unpaused plugin '%s'", desc);
return mTRUE;
@ -1223,7 +1296,6 @@ mBOOL MPlugin::retry(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
}
}
//
void MPlugin::free_api_pointers()
{
if (gamedll_funcs.dllapi_table)
@ -1252,29 +1324,31 @@ void MPlugin::free_api_pointers()
// - ME_DLERROR failed to dlclose
mBOOL MPlugin::clear()
{
if (status != PL_FAILED && status != PL_BADFILE
&& status != PL_EMPTY && status != PL_OPENED) {
if (status != PL_FAILED && status != PL_BADFILE && status != PL_EMPTY && status != PL_OPENED)
{
META_WARNING("Cannot clear plugin '%s'; not marked as failed, empty, or open (status=%s)", desc, str_status());
RETURN_ERRNO(mFALSE, ME_BADREQ);
}
// If file is open, close the file. Note: after this, attempts to
// reference any memory locations in the file will produce a segfault.
if (handle && DLCLOSE(handle) != 0) {
if (handle && DLCLOSE(handle) != 0)
{
META_WARNING("dll: Couldn't close plugin file '%s': %s", file, DLERROR());
status = PL_FAILED;
RETURN_ERRNO(mFALSE, ME_DLERROR);
}
handle=NULL;
handle = nullptr;
free_api_pointers();
status = PL_EMPTY;
action = PA_NULL;
handle=NULL;
info=NULL;
handle = nullptr;
info = nullptr;
time_loaded = 0;
gamedll_funcs.dllapi_table=NULL;
gamedll_funcs.newapi_table=NULL;
gamedll_funcs.dllapi_table = nullptr;
gamedll_funcs.newapi_table = nullptr;
Q_memset(&tables, 0, sizeof(tables));
Q_memset(&post_tables, 0, sizeof(post_tables));
@ -1287,8 +1361,9 @@ mBOOL MPlugin::clear()
void MPlugin::show()
{
char *cp, *tstr;
int n, width;
width=13;
const int width = 13;
int n;
META_CONS("%*s: %s", width, "name", info ? info->name : "(nil)");
META_CONS("%*s: %s", width, "desc", desc);
META_CONS("%*s: %s", width, "status", str_status());
@ -1306,21 +1381,26 @@ void MPlugin::show()
META_CONS("%*s: %s", width, "url", info ? info->url : "(nil)");
META_CONS("%*s: %s", width, "logtag", info ? info->logtag : "(nil)");
META_CONS("%*s: %s", width, "ifvers", info ? info->ifvers : "(nil)");
// ctime() includes newline at EOL
tstr = ctime(&time_loaded);
if ((cp = Q_strchr(tstr, '\n')))
*cp = '\0';
META_CONS("%*s: %s", width, "last loaded", tstr);
// XXX show file time ?
if (tables.dllapi) {
if (tables.dllapi)
{
META_CONS("DLLAPI functions:");
SHOW_DEF_DLLAPI(tables.dllapi," ", "");
META_CONS("%d functions (dllapi)", n);
}
else
META_CONS("No DLLAPI functions.");
if (post_tables.dllapi) {
if (post_tables.dllapi)
{
META_CONS("DLLAPI-Post functions:");
SHOW_DEF_DLLAPI(post_tables.dllapi, " ", "_Post");
META_CONS("%d functions (dllapi post)", n);
@ -1328,14 +1408,17 @@ void MPlugin::show()
else
META_CONS("No DLLAPI-Post functions.");
if (tables.newapi) {
if (tables.newapi)
{
META_CONS("NEWAPI functions:");
SHOW_DEF_NEWAPI(tables.newapi, " ", "");
META_CONS("%d functions (newapi)", n);
}
else
META_CONS("No NEWAPI functions.");
if (post_tables.newapi) {
if (post_tables.newapi)
{
META_CONS("NEWAPI-Post functions:");
SHOW_DEF_NEWAPI(post_tables.newapi, " ", "_Post");
META_CONS("%d functions (newapi post)", n);
@ -1343,20 +1426,24 @@ void MPlugin::show()
else
META_CONS("No NEWAPI-Post functions.");
if (tables.engine) {
if (tables.engine)
{
META_CONS("Engine functions:");
SHOW_DEF_ENGINE(tables.engine, " ", "");
META_CONS("%d functions (engine)", n);
}
else
META_CONS("No Engine functions.");
if (post_tables.engine) {
if (post_tables.engine)
{
META_CONS("Engine-Post functions:");
SHOW_DEF_ENGINE(post_tables.engine, " ", "_Post");
META_CONS("%d functions (engine post)", n);
}
else
META_CONS("No Engine-Post functions.");
RegCmds->show(index);
RegCvars->show(index);
@ -1378,9 +1465,9 @@ mBOOL MPlugin::newer_file()
if (stat(pathname, &st) != 0)
RETURN_ERRNO(mFALSE, ME_NOFILE);
file_time = st.st_ctime > st.st_mtime ? st.st_ctime : st.st_mtime;
META_DEBUG(5, ("newer_file? file=%s; load=%d, file=%d; ctime=%d, mtime=%d",
file, time_loaded, file_time, st.st_ctime, st.st_mtime));
META_DEBUG(5, ("newer_file? file=%s; load=%d, file=%d; ctime=%d, mtime=%d", file, time_loaded, file_time, st.st_ctime, st.st_mtime));
if (file_time > time_loaded)
return mTRUE;
else
@ -1468,7 +1555,7 @@ const char *MPlugin::str_action(STR_ACTION fmt)
// - none
const char *MPlugin::str_loadtime(PLUG_LOADTIME ptime, STR_LOADTIME fmt)
{
static const char *rPrintLoadTime[][5] = {
static const char *rPrintLoadTime[][26] = {
// SL_SIMPLE // SL_SHOW // SL_ALLOWED // SL_NOW
{ "never", "Never", "never", "never" }, // PT_NEVER
{ "startup", "Start", "at server startup", "during server startup" }, // PT_STARTUP

View File

@ -1,7 +1,6 @@
#pragma once
#include "types_meta.h" // mBOOL
#include "comp_dep.h" //
#include "new_baseclass.h"
// Number of entries to add to reglists when they need to grow. Typically

View File

@ -1,7 +1,5 @@
#ifndef MUTIL_H
#define MUTIL_H
#pragma once
#include "comp_dep.h"
#include "plinfo.h" // plugin_info_t, etc
#include "sdk_util.h" // hudtextparms_t, etc
@ -9,17 +7,19 @@
#define MAX_LOGMSG_LEN 1024
// For GetGameInfo:
typedef enum {
enum ginfo_t
{
GINFO_NAME = 0,
GINFO_DESC,
GINFO_GAMEDIR,
GINFO_DLL_FULLPATH,
GINFO_DLL_FILENAME,
GINFO_REALDLL_FULLPATH,
} ginfo_t;
};
// Meta Utility Function table type.
typedef struct meta_util_funcs_s {
struct mutil_funcs_t
{
void (*pfnLogConsole) (plid_t plid, const char *fmt, ...);
void (*pfnLogMessage) (plid_t plid, const char *fmt, ...);
void (*pfnLogError) (plid_t plid, const char *fmt, ...);
@ -38,7 +38,7 @@ typedef struct meta_util_funcs_s {
const char * (*pfnIsQueryingClientCvar) (plid_t plid, const edict_t *player);
int (*pfnMakeRequestID) (plid_t plid);
void (*pfnGetHookTables) (plid_t plid, enginefuncs_t **peng, DLL_FUNCTIONS **pdll, NEW_DLL_FUNCTIONS **pnewdll);
} mutil_funcs_t;
};
extern mutil_funcs_t MetaUtilFunctions;
@ -61,5 +61,3 @@ extern mutil_funcs_t MetaUtilFunctions;
#define IS_QUERYING_CLIENT_CVAR (*gpMetaUtilFuncs->pfnIsQueryingClientCvar)
#define MAKE_REQUESTID (*gpMetaUtilFuncs->pfnMakeRequestID)
#define GET_HOOK_TABLES (*gpMetaUtilFuncs->pfnGetHookTables)
#endif /* MUTIL_H */

View File

@ -1,8 +1,5 @@
#pragma once
#include <malloc.h>
#include "comp_dep.h"
// new/delete operators with malloc/free to remove need for libstdc++
class class_metamod_new {

View File

@ -11,31 +11,37 @@ mBOOL dlclose_handle_invalid;
// Since windows doesn't provide a verison of strtok_r(), we include one
// here. This may or may not operate exactly like strtok_r(), but does
// what we need it it do.
char *my_strtok_r(char *s, const char *delim, char **ptrptr) {
char *begin=NULL;
char *end=NULL;
char *rest=NULL;
char *my_strtok_r(char *s, const char *delim, char **ptrptr)
{
char *begin = nullptr;
char *end = nullptr;
char *rest = nullptr;
if (s)
begin = s;
else
begin = *ptrptr;
if (!begin)
return NULL;
return nullptr;
end = strpbrk(begin, delim);
if (end) {
if (end)
{
*end='\0';
rest = end + 1;
*ptrptr = rest + strspn(rest, delim);
}
else
*ptrptr=NULL;
*ptrptr = nullptr;
return begin;
}
#endif /* _WIN32 */
#endif // _WIN32
#ifdef linux
char *my_strlwr(char *s) {
#ifndef _WIN32
char *my_strlwr(char *s)
{
char *c;
if (!s)
return 0;
@ -45,12 +51,12 @@ char *my_strlwr(char *s) {
}
#endif
#ifndef DO_NOT_FIX_VARARG_ENGINE_API_WARPERS
// Microsoft's msvcrt.dll:vsnprintf is buggy and so is vsnprintf on some glibc versions.
// We use wrapper function to fix bugs.
// from: http://sourceforge.net/tracker/index.php?func=detail&aid=1083721&group_id=2435&atid=102435
int safe_vsnprintf(char* s, size_t n, const char *format, va_list src_ap) {
int safe_vsnprintf(char *s, size_t n, const char *format, va_list src_ap)
{
va_list ap;
int res;
char *tmpbuf;
@ -77,7 +83,8 @@ int safe_vsnprintf(char* s, size_t n, const char *format, va_list src_ap) {
res = Q_vsnprintf(s, n, format, ap);
va_end(ap);
if (res > 0) {
if (res > 0)
{
if ((unsigned)res == n)
s[res - 1] = 0;
return res;
@ -123,10 +130,12 @@ int safe_vsnprintf(char* s, size_t n, const char *format, va_list src_ap) {
va_end(ap);
}
if (res > 0 && n > 0) {
if (res > 0 && n > 0)
{
if (n > (unsigned)res)
Q_memcpy(s, tmpbuf, (res + 1) * sizeof (char));
else {
else
{
Q_memcpy(s, tmpbuf, (n - 1) * sizeof (char));
s[n - 1] = 0;
}
@ -136,7 +145,8 @@ int safe_vsnprintf(char* s, size_t n, const char *format, va_list src_ap) {
return res;
}
int safe_snprintf(char* s, size_t n, const char* format, ...) {
int safe_snprintf(char *s, size_t n, const char *format, ...)
{
int res;
va_list ap;
va_start(ap, format);
@ -146,15 +156,19 @@ int safe_snprintf(char* s, size_t n, const char* format, ...) {
}
#endif
void safevoid_vsnprintf(char* s, size_t n, const char *format, va_list ap) {
void safevoid_vsnprintf(char *s, size_t n, const char *format, va_list ap)
{
int res;
if (!s || n <= 0)
return;
// If the format string is empty, nothing to do.
if (!format || !*format) {
if (!format || !*format)
{
s[0] = 0;
return;
}
res = Q_vsnprintf(s, n, format, ap);
// w32api returns -1 on too long write, glibc returns number of bytes it could have written if there were enough space
// w32api doesn't write null at all, some buggy glibc don't either
@ -162,7 +176,8 @@ void safevoid_vsnprintf(char* s, size_t n, const char *format, va_list ap) {
s[n - 1] = 0;
}
void safevoid_snprintf(char* s, size_t n, const char* format, ...) {
void safevoid_snprintf(char *s, size_t n, const char *format, ...)
{
va_list ap;
va_start(ap, format);
safevoid_vsnprintf(s, n, format, ap);
@ -176,23 +191,23 @@ void safevoid_snprintf(char* s, size_t n, const char* format, ...) {
// http://msdn.microsoft.com/library/en-us/debug/errors_0sdh.asp
// except without FORMAT_MESSAGE_ALLOCATE_BUFFER, since we use a local
// static buffer.
char *str_GetLastError() {
char *str_GetLastError()
{
static char buf[MAX_STRBUF_LEN];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //! Default language
(LPTSTR) &buf, MAX_STRBUF_LEN-1, NULL);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buf, MAX_STRBUF_LEN - 1, NULL);
return buf;
}
#endif /* _WIN32 */
#endif // _WIN32
// Find the filename of the DLL/shared-lib where the given memory location
// exists.
#ifdef linux
#ifndef _WIN32
// Errno values:
// - ME_NOTFOUND couldn't find a sharedlib that contains memory location
const char *DLFNAME(void *memptr) {
const char *DLFNAME(void *memptr)
{
Dl_info dli;
Q_memset(&dli, 0, sizeof(dli));
if (dladdr(memptr, &dli))
@ -200,7 +215,8 @@ const char *DLFNAME(void *memptr) {
else
RETURN_ERRNO(NULL, ME_NOTFOUND);
}
#elif defined(_WIN32)
#else
// Implementation for win32 provided by Jussi Kivilinna <kijuhe00@rhea.otol.fi>:
//
// 1. Get memory location info on memptr with VirtualQuery.
@ -222,7 +238,8 @@ const char *DLFNAME(void *memptr) {
//
// Errno values:
// - ME_NOTFOUND couldn't find a DLL that contains memory location
const char *DLFNAME(void *memptr) {
const char *DLFNAME(void *memptr)
{
MEMORY_BASIC_INFORMATION MBI;
static char fname[PATH_MAX];
@ -230,8 +247,10 @@ const char *DLFNAME(void *memptr) {
if (!VirtualQuery(memptr, &MBI, sizeof(MBI)))
RETURN_ERRNO(NULL, ME_NOTFOUND);
if (MBI.State != MEM_COMMIT)
RETURN_ERRNO(NULL, ME_NOTFOUND);
if (!MBI.AllocationBase)
RETURN_ERRNO(NULL, ME_NOTFOUND);
@ -239,14 +258,14 @@ const char *DLFNAME(void *memptr) {
// null-terminated, even if it's truncated because buffer is too small.
if (!GetModuleFileNameA((HMODULE)MBI.AllocationBase, fname, sizeof(fname) - 1))
RETURN_ERRNO(NULL, ME_NOTFOUND);
if (!fname[0])
RETURN_ERRNO(NULL, ME_NOTFOUND);
normalize_pathname(fname);
return fname;
}
#endif /* _WIN32 */
#endif // _WIN32
#ifdef _WIN32
// Normalize/standardize a pathname.
@ -257,37 +276,46 @@ const char *DLFNAME(void *memptr) {
// non-case-sensitive.
// - For linux, this requires no work, as paths uses slashes (/) natively,
// and pathnames are case-sensitive.
void normalize_pathname(char *path) {
void normalize_pathname(char *path)
{
char *cp;
META_DEBUG(8, ("normalize: %s", path));
for (cp=path; *cp; cp++) {
for (cp = path; *cp; cp++)
{
/*if (isupper(*cp))*/
*cp=tolower(*cp);
if (*cp == '\\')
*cp = '/';
}
META_DEBUG(8, ("normalized: %s", path));
}
// Buffer pointed to by resolved_name is assumed to be able to store a
// string of PATH_MAX length.
char *realpath(const char *file_name, char *resolved_name) {
char *realpath(const char *file_name, char *resolved_name)
{
int ret;
ret = GetFullPathNameA(file_name, PATH_MAX, resolved_name, NULL);
if (ret > PATH_MAX) {
if (ret > PATH_MAX)
{
errno=ENAMETOOLONG;
return nullptr;
}
else if (ret > 0) {
else if (ret > 0)
{
HANDLE handle;
WIN32_FIND_DATAA find_data;
handle = FindFirstFileA(resolved_name, &find_data);
if (INVALID_HANDLE_VALUE == handle) {
if (INVALID_HANDLE_VALUE == handle)
{
errno = ENOENT;
return nullptr;
}
FindClose(handle);
normalize_pathname(resolved_name);
return resolved_name;
@ -295,19 +323,19 @@ char *realpath(const char *file_name, char *resolved_name) {
else
return nullptr;
}
#endif /*_WIN32*/
#endif // _WIN32
// Determine whether the given memory location is valid (ie whether we
// should expect to be able to reference strings or functions at this
// location without segfaulting).
#ifdef linux
#ifndef _WIN32
// Simulate this with dladdr. I'm not convinced this will be as generally
// applicable as the native windows routine below, but it should do what
// we need it for in this particular situation.
// meta_errno values:
// - ME_NOTFOUND couldn't find a matching sharedlib for this ptr
mBOOL IS_VALID_PTR(void *memptr) {
mBOOL IS_VALID_PTR(void *memptr)
{
Dl_info dli;
Q_memset(&dli, 0, sizeof(dli));
if (dladdr(memptr, &dli))
@ -315,24 +343,26 @@ mBOOL IS_VALID_PTR(void *memptr) {
else
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
}
#elif defined(_WIN32)
#else
// Use the native windows routine IsBadCodePtr.
// meta_errno values:
// - ME_BADMEMPTR not a valid memory pointer
mBOOL IS_VALID_PTR(void *memptr) {
mBOOL IS_VALID_PTR(void *memptr)
{
if (IsBadCodePtr((FARPROC) memptr))
RETURN_ERRNO(mFALSE, ME_BADMEMPTR);
else
return mTRUE;
}
#endif /* _WIN32 */
#endif // _WIN32
// This used to be OS-dependent, as it used a SEGV signal handler under
// linux, but that was removed because (a) it masked legitimate segfaults
// in plugin commands and produced confusing output ("plugin has been
// unloaded", when really it segfaultd), and (b) wasn't necessary since
// IS_VALID_PTR() should cover the situation.
mBOOL os_safe_call(REG_CMD_FN pfn) {
mBOOL os_safe_call(REG_CMD_FN pfn)
{
// try and see if this is a valid memory location
if (!IS_VALID_PTR((void *)pfn))
// meta_errno should be already set in is_valid_ptr()

View File

@ -1,70 +1,25 @@
#pragma once
#include <string.h> // strerror()
#include <ctype.h> // isupper, tolower
#include <errno.h> // errno
// Various differences between WIN32 and Linux.
#include "comp_dep.h"
#include "types_meta.h" // mBOOL
#include "mreg.h" // REG_CMD_FN, etc
#include "log_meta.h" // LOG_ERROR, etc
// String describing platform/DLL-type, for matching lines in plugins.ini.
#ifdef _WIN32
#define UNUSED /**/
#define PLATFORM "mswin"
#define PLATFORM_SPC "win32"
#define PLATFORM_DLEXT ".dll"
#else
#define UNUSED __attribute__((unused))
#define PLATFORM "linux"
#define PLATFORM_SPC "lin32"
#define PLATFORM_DLEXT ".so"
#endif
// Macro for function-exporting from DLL..
// from SDK dlls/cbase.h:
//! C functions for external declarations that call the appropriate C++ methods
// Windows uses "__declspec(dllexport)" to mark functions in the DLL that
// should be visible/callable externally.
//
// It also apparently requires WINAPI for GiveFnptrsToDll().
//
// See doc/notes_windows_coding for more information..
// Attributes to specify an "exported" function, visible from outside the
// DLL.
#undef DLLEXPORT
#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
// WINAPI should be provided in the windows compiler headers.
// It's usually defined to something like "__stdcall".
#elif defined(linux)
#define DLLEXPORT /* */
#define WINAPI /* */
#endif /* linux */
// Simplified macro for declaring/defining exported DLL functions. They
// need to be 'extern "C"' so that the C++ compiler enforces parameter
// type-matching, rather than considering routines with mis-matched
// arguments/types to be overloaded functions...
//
// AFAIK, this is os-independent, but it's included here in osdep.h where
// DLLEXPORT is defined, for convenience.
#ifdef _WIN32
#define C_DLLEXPORT extern "C" DLLEXPORT
#elif defined(linux)
#define C_DLLEXPORT extern "C" __attribute__((visibility("default")))
#endif /* linux */
// Special version that fixes vsnprintf bugs.
#ifndef DO_NOT_FIX_VARARG_ENGINE_API_WARPERS
int safe_vsnprintf(char* s, size_t n, const char *format, va_list ap);
@ -151,13 +106,11 @@ mBOOL os_safe_call(REG_CMD_FN pfn);
#ifdef _WIN32
#define strtok_r(s, delim, ptrptr) my_strtok_r(s, delim, ptrptr)
char *my_strtok_r(char *s, const char *delim, char **ptrptr);
#endif /* _WIN32 */
#else
// Linux doesn't have an strlwr() routine, so we write our own.
#ifdef linux
#define strlwr(s) my_strlwr(s)
char *my_strlwr(char *s);
#endif /* _WIN32 */
#endif // _WIN32
// Set filename and pathname maximum lengths. Note some windows compilers
@ -175,7 +128,7 @@ mBOOL os_safe_call(REG_CMD_FN pfn);
#ifndef PATH_MAX
#define PATH_MAX _MAX_PATH
#endif
#endif /* _WIN32 */
#endif // _WIN32
// Various other windows routine differences.
#ifdef linux
@ -204,7 +157,7 @@ mBOOL os_safe_call(REG_CMD_FN pfn);
#define write _write
#define close _close
#endif /* GCC or MSVC 8.0+ */
#endif /* _WIN32 */
#endif // _WIN32
#if !defined WIN32 && !defined _MSC_VER
#include <unistd.h> // getcwd
@ -232,7 +185,7 @@ mBOOL os_safe_call(REG_CMD_FN pfn);
#ifndef S_IWGRP
#define S_IWGRP S_IWUSR
#endif
#endif /* _WIN32 */
#endif // _WIN32
// Normalize/standardize a pathname.
// - For win32, this involves:
@ -246,7 +199,7 @@ mBOOL os_safe_call(REG_CMD_FN pfn);
#define normalize_pathname(a)
#elif defined(_WIN32)
void normalize_pathname(char *path);
#endif /* _WIN32 */
#endif // _WIN32
// Indicate if pathname appears to be an absolute-path. Under linux this
// is a leading slash (/). Under win32, this can be:
@ -259,7 +212,7 @@ inline mBOOL is_absolute_path(const char *path) {
#ifdef _WIN32
if (path[1]==':') return mTRUE;
if (path[0]=='\\') return mTRUE;
#endif /* _WIN32 */
#endif // _WIN32
return mFALSE;
}
@ -267,7 +220,7 @@ inline mBOOL is_absolute_path(const char *path) {
// Buffer pointed to by resolved_name is assumed to be able to store a
// string of PATH_MAX length.
char *realpath(const char *file_name, char *resolved_name);
#endif /* _WIN32 */
#endif // _WIN32
// Generic "error string" from a recent OS call. For linux, this is based
// on errno. For win32, it's based on GetLastError.

View File

@ -1,253 +0,0 @@
#include "precompiled.h"
/*
* GLIBC 2.11+ intercept longjmp with __longjmp_chk. However we want
* binary compability with older versions of GLIBC.
*/
#ifdef __amd64__
__asm__(".symver __longjmp_chk,longjmp@GLIBC_2.2.5");
#else
__asm__(".symver __longjmp_chk,longjmp@GLIBC_2.0");
#endif /*__amd64__*/
// On linux manually search for exports from dynamic library file.
// --Jussi Kivilinna
static jmp_buf signal_jmp_buf;
// Signal handler for is_gamedll()
static void signal_handler_sigsegv(int) {
longjmp(signal_jmp_buf, 1);
}
#define invalid_elf_ptr(x) (((unsigned long)&(x)) > file_end - 1)
#define invalid_elf_offset(x) (((unsigned long)(x)) > filesize - 1)
#define elf_error_exit() \
do { \
sigaction(SIGSEGV, &oldaction, 0); \
META_DEBUG(3, ("is_gamedll(%s): Invalid ELF.", filename)); \
munmap(ehdr, filesize); \
return mFALSE; \
} while (0)
mBOOL is_gamedll(const char *filename) {
// When these are not static there are some mysterious hidden bugs that I can't find/solve.
// So this is simple workaround.
static struct sigaction action;
static struct sigaction oldaction;
static ElfW(Ehdr) * ehdr = 0;
static ElfW(Shdr) * shdr = 0;
static ElfW(Sym) * symtab = 0;
static char * strtab = 0;
static FILE * pf = 0;
static unsigned long filesize = 0;
static unsigned long strtab_size = 0;
static unsigned long nsyms = 0;
static unsigned long i = 0;
static unsigned long file_end = 0;
static char * funcname = 0;
static int has_GiveFnptrsToDll = 0;
static int has_GetEntityAPI2 = 0;
static int has_GetEntityAPI = 0;
ehdr = 0;
shdr = 0;
symtab = 0;
strtab = 0;
pf = 0;
filesize = 0;
file_end = 0;
strtab_size = 0;
nsyms = 0;
i = 0;
funcname = 0;
has_GiveFnptrsToDll = 0;
has_GetEntityAPI2 = 0;
has_GetEntityAPI = 0;
// Try open file and get filesize
if ((pf = fopen(filename, "rb"))) {
fseek(pf, 0, SEEK_END);
filesize = ftell(pf);
fseek(pf, 0, SEEK_SET);
} else {
META_DEBUG(3, ("is_gamedll(%s): Failed, cannot fopen() file.", filename));
return mFALSE;
}
// Check that filesize is atleast size of ELF header!
if (filesize < sizeof(ElfW(Ehdr)))
{
META_DEBUG(3, ("is_gamedll(%s): Failed, file is too small to be ELF32. [%i < %i]", filename, filesize, sizeof(ElfW(Ehdr))));
fclose(pf);
return mFALSE;
}
// mmap library for easy reading
ehdr = (ElfW(Ehdr) *)mmap(0, filesize, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(pf), 0);
file_end = (unsigned long)ehdr + filesize;
// not needed anymore
fclose(pf);
// check if mmap was successful
if (!ehdr || (void*)ehdr==(void*)-1) {
META_DEBUG(3, ("is_gamedll(%s): Failed, mmap() [0x%x]", filename, ehdr));
return mFALSE;
}
//In case that ELF file is incomplete (because bad upload etc), we protect memory-mapping access with signal-handler
if (!setjmp(signal_jmp_buf)) {
Q_memset(&action, 0, sizeof(struct sigaction));
Q_memset(&oldaction, 0, sizeof(struct sigaction));
// Not returning from signal, set SIGSEGV handler.
action.sa_handler = signal_handler_sigsegv;
action.sa_flags = SA_RESETHAND | SA_NODEFER;
sigemptyset(&action.sa_mask);
sigaction(SIGSEGV, &action, &oldaction);
} else {
// Reset signal handler.
sigaction(SIGSEGV, &oldaction, 0);
META_DEBUG(3, ("is_gamedll(%s): Failed, signal SIGSEGV.", filename));
munmap(ehdr, filesize);
return mFALSE;
}
if (Q_strncmp((char *)ehdr, ELFMAG, SELFMAG) != 0 || ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
// Reset signal handler.
sigaction(SIGSEGV, &oldaction, 0);
META_DEBUG(3, ("is_gamedll(%s): Failed, file isn't ELF (%02x%02x%02x%02x:%x).", filename, ((char *)ehdr)[0], ((char *)ehdr)[1], ((char *)ehdr)[2], ((char *)ehdr)[3], ehdr->e_ident[EI_VERSION]));
munmap(ehdr, filesize);
return mFALSE;
}
// check if x86-shared-library
if (ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_386)
{
// Reset signal handler.
sigaction(SIGSEGV, &oldaction, 0);
META_DEBUG(3, ("is_gamedll(%s): Failed, ELF isn't for target:i386. [%x:%x:%x]", filename, ehdr->e_ident[EI_CLASS], ehdr->e_type, ehdr->e_machine));
munmap(ehdr, filesize);
return mFALSE;
}
//Get symtab and strtab info
shdr = (ElfW(Shdr) *)((char *)ehdr + ehdr->e_shoff);
if (invalid_elf_ptr(shdr[ehdr->e_shnum]))
elf_error_exit();
for (i = 0; i < ehdr->e_shnum; i++) {
// searching for dynamic linker symbol table
if (shdr[i].sh_type == SHT_DYNSYM) {
if (invalid_elf_offset(shdr[i].sh_offset) ||
invalid_elf_ptr(shdr[shdr[i].sh_link]) ||
invalid_elf_offset(shdr[shdr[i].sh_link].sh_offset) ||
invalid_elf_ptr(strtab[strtab_size]) ||
invalid_elf_ptr(symtab[nsyms]))
elf_error_exit();
symtab = (ElfW(Sym) *)((char *)ehdr + shdr[i].sh_offset);
strtab = (char *)((char *)ehdr + shdr[shdr[i].sh_link].sh_offset);
strtab_size = shdr[shdr[i].sh_link].sh_size;
nsyms = shdr[i].sh_size / shdr[i].sh_entsize;
break;
}
}
if (!symtab) {
//Another method for finding symtab
for (i = 0; i < ehdr->e_shnum; i++) {
if (shdr[i].sh_type == SHT_SYMTAB) {
if (invalid_elf_offset(shdr[i].sh_offset) ||
invalid_elf_ptr(shdr[shdr[i].sh_link]) ||
invalid_elf_offset(shdr[shdr[i].sh_link].sh_offset) ||
invalid_elf_ptr(strtab[strtab_size]) ||
invalid_elf_ptr(symtab[nsyms]))
elf_error_exit();
symtab = (ElfW(Sym) *)((char *)ehdr + shdr[i].sh_offset);
strtab = (char *)((char *)ehdr + shdr[shdr[i].sh_link].sh_offset);
strtab_size = shdr[shdr[i].sh_link].sh_size;
nsyms = shdr[i].sh_size / shdr[i].sh_entsize;
break;
}
}
}
if (!symtab) {
// Reset signal handler.
sigaction(SIGSEGV, &oldaction, 0);
META_DEBUG(3, ("is_gamedll(%s): Failed, couldn't locate symtab.", filename));
munmap(ehdr, filesize);
return mFALSE;
}
//Search symbols for exports
for (i = 0; i < nsyms; i++)
{
// Export?
if (ELF32_ST_TYPE(symtab[i].st_info) != STT_FUNC || ELF32_ST_BIND(symtab[i].st_info) != STB_GLOBAL)
continue;
// string outside strtab?
if (symtab[i].st_name <= 0 || symtab[i].st_name >= strtab_size)
continue;
funcname = &strtab[symtab[i].st_name];
// Check
// Fast check for 'G' first
if (funcname[0] == 'G') {
// Collect export information
if (!has_GiveFnptrsToDll)
has_GiveFnptrsToDll = !Q_strcmp(funcname, "GiveFnptrsToDll");
if (!has_GetEntityAPI2)
has_GetEntityAPI2 = !Q_strcmp(funcname, "GetEntityAPI2");
if (!has_GetEntityAPI)
has_GetEntityAPI = !Q_strcmp(funcname, "GetEntityAPI");
}
// Check if metamod plugin
else if (funcname[0] == 'M')
{
if (!Q_strcmp(funcname, "Meta_Init") || !Q_strcmp(funcname, "Meta_Query") || !Q_strcmp(funcname, "Meta_Attach") || !Q_strcmp(funcname, "Meta_Detach"))
{
// Metamod plugin.. is not gamedll
META_DEBUG(5, ("is_gamedll(%s): Detected Metamod plugin, library exports [%s].", filename, funcname));
// Reset signal handler.
sigaction(SIGSEGV, &oldaction, 0);
munmap(ehdr, filesize);
return mFALSE;
}
}
}
// Check if gamedll
if (has_GiveFnptrsToDll && (has_GetEntityAPI2 || has_GetEntityAPI)) {
// This is gamedll!
META_DEBUG(5, ("is_gamedll(%s): Detected GameDLL.", filename));
// Reset signal handler.
sigaction(SIGSEGV, &oldaction, 0);
munmap(ehdr, filesize);
return mTRUE;
} else {
META_DEBUG(5, ("is_gamedll(%s): Library isn't GameDLL.", filename));
}
// Reset signal handler.
sigaction(SIGSEGV, &oldaction, 0);
munmap(ehdr, filesize);
return mFALSE;
}

View File

@ -1,193 +0,0 @@
#include "precompiled.h"
//check for invalid handle values
#define is_invalid_handle(X) ((X)==0 || (X)==INVALID_HANDLE_VALUE)
//relative virtual address to virtual address
#define rva_to_va(base, rva) ((unsigned long)base + (unsigned long)rva)
//virtual address to relative virtual address
#define va_to_rva(base, va) ((unsigned long)va - (unsigned long)base)
unsigned long va_to_mapaddr(void * mapview, IMAGE_SECTION_HEADER * sections, int num_sects, unsigned long vaddr) {
for (int i = 0; i < num_sects; i++)
if (vaddr >= sections[i].VirtualAddress && vaddr < sections[i].VirtualAddress + sections[i].SizeOfRawData)
return rva_to_va(mapview, (vaddr - sections[i].VirtualAddress + sections[i].PointerToRawData));
return 0;
}
// Checks module signatures and return ntheaders pointer for valid module
IMAGE_NT_HEADERS *get_ntheaders(void * mapview) {
union {
unsigned long mem;
IMAGE_DOS_HEADER * dos;
IMAGE_NT_HEADERS * pe;
} mem;
//Check if valid dos header
mem.mem = (unsigned long)mapview;
if (IsBadReadPtr(mem.dos, sizeof(*mem.dos)) || mem.dos->e_magic != IMAGE_DOS_SIGNATURE)
return 0;
//Get and check pe header
mem.mem = rva_to_va(mapview, mem.dos->e_lfanew);
if (IsBadReadPtr(mem.pe, sizeof(*mem.pe)) || mem.pe->Signature != IMAGE_NT_SIGNATURE)
return 0;
return mem.pe;
}
// Returns export table for valid module
IMAGE_EXPORT_DIRECTORY *get_export_table(void * mapview, IMAGE_NT_HEADERS * ntheaders, IMAGE_SECTION_HEADER * sections, int num_sects) {
union {
unsigned long mem;
void * pvoid;
IMAGE_DOS_HEADER * dos;
IMAGE_NT_HEADERS * pe;
IMAGE_EXPORT_DIRECTORY * export_dir;
} mem;
mem.pe = ntheaders;
//Check for exports
if (!mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
return 0;
mem.mem = va_to_mapaddr(mapview, sections, num_sects, mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
if (IsBadReadPtr(mem.export_dir, sizeof(*mem.export_dir)))
return 0;
return mem.export_dir;
}
mBOOL is_gamedll(const char *filename) {
HANDLE hFile;
HANDLE hMap;
void * mapview;
IMAGE_NT_HEADERS * ntheaders;
IMAGE_SECTION_HEADER * sections;
int num_sects;
IMAGE_EXPORT_DIRECTORY * exports;
int has_GiveFnptrsToDll = 0;
int has_GetEntityAPI2 = 0;
int has_GetEntityAPI = 0;
// Try open file for read
hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (is_invalid_handle(hFile)) {
META_DEBUG(3, ("is_gamedll(%s): CreateFile() failed.", filename));
return mFALSE;
}
//
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (is_invalid_handle(hMap)) {
META_DEBUG(3, ("is_gamedll(%s): CreateFileMapping() failed.", filename));
CloseHandle(hFile);
return mFALSE;
}
//
mapview = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
if (!mapview) {
META_DEBUG(3, ("is_gamedll(%s): MapViewOfFile() failed.", filename));
CloseHandle(hMap);
CloseHandle(hFile);
return mFALSE;
}
ntheaders = get_ntheaders(mapview);
if (!ntheaders) {
META_DEBUG(3, ("is_gamedll(%s): get_ntheaders() failed.", filename));
UnmapViewOfFile(mapview);
CloseHandle(hMap);
CloseHandle(hFile);
return mFALSE;
}
//Sections for va_to_mapaddr function
sections = IMAGE_FIRST_SECTION(ntheaders);
num_sects = ntheaders->FileHeader.NumberOfSections;
if (IsBadReadPtr(sections, num_sects * sizeof(IMAGE_SECTION_HEADER))) {
META_DEBUG(3, ("is_gamedll(%s): IMAGE_FIRST_SECTION() failed.", filename));
UnmapViewOfFile(mapview);
CloseHandle(hMap);
CloseHandle(hFile);
return mFALSE;
}
//
exports = get_export_table(mapview, ntheaders, sections, num_sects);
if (!exports) {
META_DEBUG(3, ("is_gamedll(%s): get_export_table() failed.", filename));
UnmapViewOfFile(mapview);
CloseHandle(hMap);
CloseHandle(hFile);
return mFALSE;
}
//
unsigned long * names = (unsigned long *)va_to_mapaddr(mapview, sections, num_sects, exports->AddressOfNames);
if (IsBadReadPtr(names, exports->NumberOfNames * sizeof(unsigned long)))
{
META_DEBUG(3, ("is_gamedll(%s): Pointer to exported function names is invalid.", filename));
UnmapViewOfFile(mapview);
CloseHandle(hMap);
CloseHandle(hFile);
return mFALSE;
}
for (unsigned int i = 0; i < exports->NumberOfNames; i++)
{
//get function name with valid address
char * funcname = (char *)va_to_mapaddr(mapview, sections, num_sects, names[i]);
if (IsBadStringPtrA(funcname, 128))
continue;
// Check
// Fast check for 'G' first
if (funcname[0] == 'G')
{
// Collect export information
if (!has_GiveFnptrsToDll)
has_GiveFnptrsToDll = !Q_strcmp(funcname, "GiveFnptrsToDll");
if (!has_GetEntityAPI2)
has_GetEntityAPI2 = !Q_strcmp(funcname, "GetEntityAPI2");
if (!has_GetEntityAPI)
has_GetEntityAPI = !Q_strcmp(funcname, "GetEntityAPI");
}
// Check if metamod plugin
else if (funcname[0] == 'M')
{
if (!Q_strcmp(funcname, "Meta_Init") || !Q_strcmp(funcname, "Meta_Query") || !Q_strcmp(funcname, "Meta_Attach") || !Q_strcmp(funcname, "Meta_Detach"))
{
// Metamod plugin.. is not gamedll
META_DEBUG(5, ("is_gamedll(%s): Detected Metamod plugin, library exports [%s].", filename, funcname));
UnmapViewOfFile(mapview);
CloseHandle(hMap);
CloseHandle(hFile);
return mFALSE;
}
}
}
UnmapViewOfFile(mapview);
CloseHandle(hMap);
CloseHandle(hFile);
// Check if gamedll
if (has_GiveFnptrsToDll && (has_GetEntityAPI2 || has_GetEntityAPI))
{
// This is gamedll!
META_DEBUG(5, ("is_gamedll(%s): Detected GameDLL.", filename));
return mTRUE;
}
else
{
META_DEBUG(5, ("is_gamedll(%s): Library isn't GameDLL.", filename));
return mFALSE;
}
}

View File

@ -1,35 +1,37 @@
#ifndef PLINFO_H
#define PLINFO_H
#include "comp_dep.h"
#pragma once
// Flags for plugin to indicate when it can be be loaded/unloaded.
// NOTE: order is crucial, as greater/less comparisons are made.
typedef enum {
enum PLUG_LOADTIME
{
PT_NEVER = 0,
PT_STARTUP, // should only be loaded/unloaded at initial hlds execution
PT_CHANGELEVEL, // can be loaded/unloaded between maps
PT_ANYTIME, // can be loaded/unloaded at any time
PT_ANYPAUSE, // can be loaded/unloaded at any time, and can be "paused" during a map
} PLUG_LOADTIME;
};
// Flags to indicate why the plugin is being unloaded.
typedef enum {
enum PL_UNLOAD_REASON
{
PNL_NULL = 0,
PNL_INI_DELETED, // was deleted from plugins.ini
PNL_FILE_NEWER, // file on disk is newer than last load
PNL_COMMAND, // requested by server/console command
PNL_CMD_FORCED, // forced by server/console command
PNL_DELAYED, // delayed from previous request; can't tell origin
// only used for 'real_reason' on MPlugin::unload()
PNL_PLUGIN, // requested by plugin function call
PNL_PLG_FORCED, // forced by plugin function call
// only used internally for 'meta reload'
PNL_RELOAD, // forced unload by reload()
} PL_UNLOAD_REASON;
};
// Information plugin provides about itself.
typedef struct {
struct plugin_info_t
{
char *ifvers; // meta_interface version
char *name; // full name of plugin
char *version; // version
@ -39,12 +41,10 @@ typedef struct {
char *logtag; // log message prefix (unused right now)
PLUG_LOADTIME loadable; // when loadable
PLUG_LOADTIME unloadable; // when unloadable
} plugin_info_t;
};
extern plugin_info_t Plugin_info;
// Plugin identifier, passed to all Meta Utility Functions.
typedef plugin_info_t *plid_t;
#define PLID &Plugin_info
#endif /* PLINFO_H */

View File

@ -8,7 +8,6 @@
#endif /* DEBUG */
#include "enginecallbacks.h"
#include "comp_dep.h"
#include <util.h>
// Also, create some additional macros for engine callback functions, which

View File

@ -1,12 +1,7 @@
#pragma once
#include "comp_dep.h"
// Our own boolean type, for stricter type matching.
typedef enum mBOOL {
mFALSE = 0,
mTRUE,
} mBOOL;
enum mBOOL { mFALSE = 0, mTRUE, };
// Like C's errno, for our various functions; describes causes of failure
// or mFALSE returns.

View File

@ -17,8 +17,12 @@
\#define APP_VERSION_D ${verInfo.format('.', '-', true)}
\#define APP_VERSION_C ${verInfo.majorVersion},${verInfo.minorVersion},0,${verInfo.countCommit}
\#define APP_VERSION_STRD "${verInfo.majorVersion}.${verInfo.minorVersion}.${verInfo.countCommit}"
\#define APP_VERSION_STRD_RC "${verInfo.majorVersion}.${verInfo.minorVersion}.${verInfo.countCommit}"
\#define APP_VERSION_STRD "${verInfo.majorVersion}.${verInfo.minorVersion}.${verInfo.countCommit}${formatSpecialVersion}"
\#define APP_VERSION_STRD_RC "${verInfo.majorVersion}.${verInfo.minorVersion}.${verInfo.countCommit}${formatSpecialVersion}"
\#define APP_VERSION_FLAGS ${appFlags}
\#define APP_VERSION_SPECIALBUILD "${verInfo.specialVersion}"
#set ( $commitYMD = $_DateTimeFormat.forPattern('yyyy-MM-dd').print($verInfo.lastCommitDate) )
\#define APP_VERSION_YMD_STR "${commitYMD}"