Spring Cleaning, Part Ichi (1)

Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401971
This commit is contained in:
Scott Ehlert
2008-03-30 07:00:22 +00:00
commit 251cced1f8
801 changed files with 280074 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
#define _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
#include <irecipientfilter.h>
#include <sp_vm_types.h>
class CellRecipientFilter : public IRecipientFilter
{
public:
CellRecipientFilter() : m_IsReliable(false), m_IsInitMessage(false), m_Size(0) {}
~CellRecipientFilter() {}
public: //IRecipientFilter
bool IsReliable() const;
bool IsInitMessage() const;
int GetRecipientCount() const;
int GetRecipientIndex(int slot) const;
public:
void Initialize(cell_t *ptr, size_t count);
void SetToReliable(bool isreliable);
void SetToInit(bool isinitmsg);
void Reset();
private:
cell_t m_Players[255];
bool m_IsReliable;
bool m_IsInitMessage;
size_t m_Size;
};
inline void CellRecipientFilter::Reset()
{
m_IsReliable = false;
m_IsInitMessage = false;
m_Size = 0;
}
inline bool CellRecipientFilter::IsReliable() const
{
return m_IsReliable;
}
inline bool CellRecipientFilter::IsInitMessage() const
{
return m_IsInitMessage;
}
inline int CellRecipientFilter::GetRecipientCount() const
{
return m_Size;
}
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
{
if ((slot < 0) || (slot >= GetRecipientCount()))
{
return -1;
}
return static_cast<int>(m_Players[slot]);
}
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
{
m_IsInitMessage = isinitmsg;
}
inline void CellRecipientFilter::SetToReliable(bool isreliable)
{
m_IsReliable = isreliable;
}
inline void CellRecipientFilter::Initialize(cell_t *ptr, size_t count)
{
memcpy(m_Players, ptr, count * sizeof(cell_t));
m_Size = count;
}
#endif //_INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
+106
View File
@@ -0,0 +1,106 @@
#(C)2004-2008 Metamod:Source Development Team
# Makefile written by David "BAILOPAN" Anderson
HL2SDK_ORIG = ../../../hl2sdk
HL2SDK_OB = ../../../hl2sdk-ob
SOURCEMM14 = ../../../sourcemm-1.4
SOURCEMM16 = ../../../sourcemm-1.6
SRCDS_BASE = ~/srcds
SMSDK = ../..
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
PROJECT = sdktools
OBJECTS = sdk/smsdk_ext.cpp extension.cpp vdecoder.cpp vcallbuilder.cpp vcaller.cpp \
vnatives.cpp vsound.cpp tenatives.cpp trnatives.cpp tempents.cpp vstringtable.cpp \
vhelpers.cpp vglobals.cpp voice.cpp inputnatives.cpp teamnatives.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -g -ggdb3
CPP_GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden
CPP = gcc-4.1
ifeq "$(ENGINE)" "original"
HL2SDK = $(HL2SDK_ORIG)
HL2PUB = $(HL2SDK_ORIG)/public
HL2LIB = $(HL2SDK_ORIG)/linux_sdk
METAMOD = $(SOURCEMM14)
INCLUDE += -I$(HL2SDK)/public/dlls
SRCDS = $(SRCDS_BASE)
endif
ifeq "$(ENGINE)" "orangebox"
HL2SDK = $(HL2SDK_OB)
HL2PUB = $(HL2SDK_OB)/public
HL2LIB = $(HL2SDK_OB)/linux_sdk
CFLAGS += -DORANGEBOX_BUILD
METAMOD = $(SOURCEMM16)
INCLUDE += -I$(HL2SDK)/public/game/server -I$(HL2SDK)/common
SRCDS = $(SRCDS_BASE)/orangebox
endif
ifeq "$(ENGINE)" ""
echo "You must supply ENGINE=orangebox or ENGINE=original"
false
endif
LINK_HL2 = $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so tier0_i486.so
LINK += $(LINK_HL2) -static-libgcc
INCLUDE += -I. -I.. -Isdk -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook -I$(METAMOD)/sourcemm \
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions \
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror -Wno-switch \
-Wno-unused -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -m32
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti -fno-threadsafe-statics
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug.$(ENGINE)
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release.$(ENGINE)
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
BINARY = $(PROJECT).ext.so
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/sdk
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
$(MAKE) -f Makefile extension
extension: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
default: all
clean:
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/sdk/*.o
rm -rf $(BIN_DIR)/$(BINARY)
+331
View File
@@ -0,0 +1,331 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
#include "vcallbuilder.h"
#include "vnatives.h"
#include "vhelpers.h"
#include "vglobals.h"
#include "tempents.h"
#include "vsound.h"
#if defined ORANGEBOX_BUILD
#define SDKTOOLS_GAME_FILE "sdktools.games.ep2"
#else
#define SDKTOOLS_GAME_FILE "sdktools.games"
#endif
/**
* @file extension.cpp
* @brief Implements SDK Tools extension code.
*/
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
SDKTools g_SdkTools; /**< Global singleton for extension's main interface */
IServerGameEnts *gameents = NULL;
IEngineTrace *enginetrace = NULL;
IEngineSound *engsound = NULL;
INetworkStringTableContainer *netstringtables = NULL;
IServerPluginHelpers *pluginhelpers = NULL;
IBinTools *g_pBinTools = NULL;
IGameConfig *g_pGameConf = NULL;
IGameHelpers *g_pGameHelpers = NULL;
IServerGameClients *serverClients = NULL;
IVoiceServer *voiceserver = NULL;
IPlayerInfoManager *playerinfomngr = NULL;
ICvar *icvar = NULL;
IServer *iserver = NULL;
SourceHook::CallClass<IVEngineServer> *enginePatch = NULL;
SourceHook::CallClass<IEngineSound> *enginesoundPatch = NULL;
HandleType_t g_CallHandle = 0;
HandleType_t g_TraceHandle = 0;
SMEXT_LINK(&g_SdkTools);
extern sp_nativeinfo_t g_CallNatives[];
extern sp_nativeinfo_t g_TENatives[];
extern sp_nativeinfo_t g_TRNatives[];
extern sp_nativeinfo_t g_StringTableNatives[];
extern sp_nativeinfo_t g_VoiceNatives[];
extern sp_nativeinfo_t g_EntInputNatives[];
extern sp_nativeinfo_t g_TeamNatives[];
bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
sharesys->AddDependency(myself, "bintools.ext", true, true);
sharesys->AddNatives(myself, g_CallNatives);
sharesys->AddNatives(myself, g_Natives);
sharesys->AddNatives(myself, g_TENatives);
sharesys->AddNatives(myself, g_SoundNatives);
sharesys->AddNatives(myself, g_TRNatives);
sharesys->AddNatives(myself, g_StringTableNatives);
sharesys->AddNatives(myself, g_VoiceNatives);
sharesys->AddNatives(myself, g_EntInputNatives);
sharesys->AddNatives(myself, g_TeamNatives);
SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers);
if (!gameconfs->LoadGameConfigFile(SDKTOOLS_GAME_FILE, &g_pGameConf, error, maxlength))
{
return false;
}
playerhelpers->AddClientListener(&g_SdkTools);
g_CallHandle = handlesys->CreateType("ValveCall", this, 0, NULL, NULL, myself->GetIdentity(), NULL);
g_TraceHandle = handlesys->CreateType("TraceRay", this, 0, NULL, NULL, myself->GetIdentity(), NULL);
#if defined ORANGEBOX_BUILD
g_pCVar = icvar;
#endif
CONVAR_REGISTER(this);
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &SDKTools::OnServerActivate, false);
playerhelpers->RegisterCommandTargetProcessor(this);
MathLib_Init(2.2f, 2.2f, 0.0f, 2);
return true;
}
void SDKTools::OnHandleDestroy(HandleType_t type, void *object)
{
if (type == g_CallHandle)
{
ValveCall *v = (ValveCall *)object;
delete v;
}
else if (type == g_TraceHandle)
{
trace_t *tr = (trace_t *)object;
delete tr;
}
}
void SDKTools::SDK_OnUnload()
{
SourceHook::List<ValveCall *>::iterator iter;
for (iter = g_RegCalls.begin();
iter != g_RegCalls.end();
iter++)
{
delete (*iter);
}
g_RegCalls.clear();
ShutdownHelpers();
if (g_pAcceptInput)
{
g_pAcceptInput->Destroy();
g_pAcceptInput = NULL;
}
g_TEManager.Shutdown();
s_TempEntHooks.Shutdown();
s_SoundHooks.Shutdown();
gameconfs->CloseGameConfigFile(g_pGameConf);
playerhelpers->RemoveClientListener(&g_SdkTools);
playerhelpers->UnregisterCommandTargetProcessor(this);
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &SDKTools::OnServerActivate, false);
if (enginePatch)
{
SH_RELEASE_CALLCLASS(enginePatch);
enginePatch = NULL;
}
if (enginesoundPatch)
{
SH_RELEASE_CALLCLASS(enginesoundPatch);
enginesoundPatch = NULL;
}
}
bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
{
GET_V_IFACE_ANY(GetServerFactory, gameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS);
GET_V_IFACE_ANY(GetEngineFactory, engsound, IEngineSound, IENGINESOUND_SERVER_INTERFACE_VERSION);
GET_V_IFACE_ANY(GetEngineFactory, enginetrace, IEngineTrace, INTERFACEVERSION_ENGINETRACE_SERVER);
GET_V_IFACE_ANY(GetEngineFactory, netstringtables, INetworkStringTableContainer, INTERFACENAME_NETWORKSTRINGTABLESERVER);
GET_V_IFACE_ANY(GetEngineFactory, pluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS);
GET_V_IFACE_ANY(GetServerFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
GET_V_IFACE_ANY(GetEngineFactory, voiceserver, IVoiceServer, INTERFACEVERSION_VOICESERVER);
GET_V_IFACE_ANY(GetServerFactory, playerinfomngr, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER);
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
enginePatch = SH_GET_CALLCLASS(engine);
enginesoundPatch = SH_GET_CALLCLASS(engsound);
return true;
}
void SDKTools::SDK_OnAllLoaded()
{
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
if (!g_pBinTools)
{
return;
}
g_TEManager.Initialize();
s_TempEntHooks.Initialize();
s_SoundHooks.Initialize();
InitializeValveGlobals();
GetIServer();
}
bool SDKTools::QueryRunning(char *error, size_t maxlength)
{
SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
return true;
}
bool SDKTools::QueryInterfaceDrop(SMInterface *pInterface)
{
if (pInterface == g_pBinTools)
{
return false;
}
return IExtensionInterface::QueryInterfaceDrop(pInterface);
}
void SDKTools::NotifyInterfaceDrop(SMInterface *pInterface)
{
SourceHook::List<ValveCall *>::iterator iter;
for (iter = g_RegCalls.begin();
iter != g_RegCalls.end();
iter++)
{
delete (*iter);
}
g_RegCalls.clear();
ShutdownHelpers();
g_TEManager.Shutdown();
s_TempEntHooks.Shutdown();
if (g_pAcceptInput)
{
g_pAcceptInput->Destroy();
g_pAcceptInput = NULL;
}
}
bool SDKTools::RegisterConCommandBase(ConCommandBase *pVar)
{
#if defined METAMOD_PLAPI_VERSION
return g_SMAPI->RegisterConCommandBase(g_PLAPI, pVar);
#else
return g_SMAPI->RegisterConCmdBase(g_PLAPI, pVar);
#endif
}
bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
{
const char *name;
char key[32];
int count, n = 1;
if (!(name=g_pGameConf->GetKeyValue("SlapSoundCount")))
{
RETURN_META_VALUE(MRES_IGNORED, true);
}
count = atoi(name);
while (n <= count)
{
snprintf(key, sizeof(key), "SlapSound%d", n);
if ((name=g_pGameConf->GetKeyValue(key)))
{
engsound->PrecacheSound(name, true);
}
n++;
}
RETURN_META_VALUE(MRES_IGNORED, true);
}
bool SDKTools::ProcessCommandTarget(cmd_target_info_t *info)
{
if (strcmp(info->pattern, "@aim") != 0)
{
return false;
}
IGamePlayer *pAdmin = info->admin ? playerhelpers->GetGamePlayer(info->admin) : NULL;
/* The server can't aim, of course. */
if (pAdmin == NULL)
{
return false;
}
int player_index;
if ((player_index = GetClientAimTarget(pAdmin->GetEdict(), true)) < 1)
{
info->reason = COMMAND_TARGET_NONE;
info->num_targets = 0;
return true;
}
IGamePlayer *pTarget = playerhelpers->GetGamePlayer(player_index);
if (pTarget == NULL)
{
info->reason = COMMAND_TARGET_NONE;
info->num_targets = 0;
return true;
}
info->reason = playerhelpers->FilterCommandTarget(pAdmin, pTarget, info->flags);
if (info->reason != COMMAND_TARGET_VALID)
{
info->num_targets = 0;
return true;
}
info->targets[0] = player_index;
info->num_targets = 1;
info->reason = COMMAND_TARGET_VALID;
info->target_name_style = COMMAND_TARGETNAME_RAW;
snprintf(info->target_name, info->target_name_maxlength, "%s", pTarget->GetName());
return true;
}
+120
View File
@@ -0,0 +1,120 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
/**
* @file extension.h
* @brief SDK Tools extension code header.
*/
#include "smsdk_ext.h"
#include <IBinTools.h>
#include <IPlayerHelpers.h>
#include <IGameHelpers.h>
#include <IEngineTrace.h>
#include <IEngineSound.h>
#include <ivoiceserver.h>
#include <iplayerinfo.h>
#include <convar.h>
#include <iserver.h>
#include <cdll_int.h>
#include <compat_wrappers.h>
/**
* @brief Implementation of the SDK Tools extension.
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
*/
class SDKTools :
public SDKExtension,
public IHandleTypeDispatch,
public IConCommandBaseAccessor,
public IClientListener,
public ICommandTargetProcessor
{
public: //public IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
public: //public SDKExtension
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
virtual void SDK_OnUnload();
virtual void SDK_OnAllLoaded();
//virtual void SDK_OnPauseChange(bool paused);
virtual bool QueryRunning(char *error, size_t maxlength);
virtual bool QueryInterfaceDrop(SMInterface *pInterface);
virtual void NotifyInterfaceDrop(SMInterface *pInterface);
public:
#if defined SMEXT_CONF_METAMOD
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late);
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen);
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen);
#endif
public: //IConCommandBaseAccessor
bool RegisterConCommandBase(ConCommandBase *pVar);
public: //IClientListner
void OnClientDisconnecting(int client);
public: // IVoiceServer
bool OnSetClientListening(int iReceiver, int iSender, bool bListen);
public: //ICommandTargetProcessor
bool ProcessCommandTarget(cmd_target_info_t *info);
public:
bool LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
};
extern SDKTools g_SdkTools;
/* Interfaces from engine or gamedll */
extern IServerGameEnts *gameents;
extern IEngineTrace *enginetrace;
extern IEngineSound *engsound;
extern INetworkStringTableContainer *netstringtables;
extern IServerPluginHelpers *pluginhelpers;
extern IServerGameClients *serverClients;
extern IVoiceServer *voiceserver;
extern IPlayerInfoManager *playerinfomngr;
extern ICvar *icvar;
extern IServer *iserver;
/* Interfaces from SourceMod */
extern IBinTools *g_pBinTools;
extern IGameConfig *g_pGameConf;
extern IGameHelpers *g_pGameHelpers;
/* Handle types */
extern HandleType_t g_CallHandle;
extern HandleType_t g_TraceHandle;
/* Call Wrappers */
extern ICallWrapper *g_pAcceptInput;
/* Call classes */
extern SourceHook::CallClass<IVEngineServer> *enginePatch;
extern SourceHook::CallClass<IEngineSound> *enginesoundPatch;
#define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func)
#endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
+288
View File
@@ -0,0 +1,288 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
#include <datamap.h>
#define SIZEOF_VARIANT_T 20
ICallWrapper *g_pAcceptInput = NULL;
unsigned char g_Variant_t[SIZEOF_VARIANT_T] = {0};
#define ENTINDEX_TO_CBASEENTITY(index, buffer) \
pEdict = engine->PEntityOfEntIndex(index); \
if (!pEdict || pEdict->IsFree()) \
{ \
return pContext->ThrowNativeError("Entity %d is not valid or is freed", index); \
} \
pUnk = pEdict->GetUnknown(); \
if (!pUnk) \
{ \
return pContext->ThrowNativeError("Entity %d is a not an IServerUnknown", index); \
} \
buffer = pUnk->GetBaseEntity(); \
if (!buffer) \
{ \
return pContext->ThrowNativeError("Entity %d is not a CBaseEntity", index); \
}
/* Hack to init the variant_t object for the first time */
class VariantFirstTimeInit
{
public:
VariantFirstTimeInit()
{
*(unsigned int *)(&g_Variant_t[12]) = INVALID_EHANDLE_INDEX;
}
} g_VariantFirstTimeInit;
inline void _init_variant_t()
{
unsigned char *vptr = g_Variant_t;
*(int *)vptr = 0;
vptr += sizeof(int)*3;
*(unsigned long *)vptr = INVALID_EHANDLE_INDEX;
vptr += sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_VOID;
}
static cell_t AcceptEntityInput(IPluginContext *pContext, const cell_t *params)
{
if (!g_pAcceptInput)
{
int offset;
if (!g_pGameConf->GetOffset("AcceptInput", &offset))
{
return pContext->ThrowNativeError("\"AcceptEntityInput\" not supported by this mod");
}
PassInfo pass[6];
pass[0].type = PassType_Basic;
pass[0].flags = PASSFLAG_BYVAL;
pass[0].size = sizeof(const char *);
pass[1].type = pass[2].type = PassType_Basic;
pass[1].flags = pass[2].flags = PASSFLAG_BYVAL;
pass[1].size = pass[2].size = sizeof(CBaseEntity *);
pass[3].type = PassType_Object;
pass[3].flags = PASSFLAG_BYVAL|PASSFLAG_OCTOR|PASSFLAG_ODTOR|PASSFLAG_OASSIGNOP;
pass[3].size = SIZEOF_VARIANT_T;
pass[4].type = PassType_Basic;
pass[4].flags = PASSFLAG_BYVAL;
pass[4].size = sizeof(int);
pass[5].type = PassType_Basic;
pass[5].flags = PASSFLAG_BYVAL;
pass[5].size = sizeof(bool);
if (!(g_pAcceptInput=g_pBinTools->CreateVCall(offset, 0, 0, &pass[5], pass, 5)))
{
pContext->ThrowNativeError("\"AcceptEntityInput\" wrapper failed to initialized");
}
}
CBaseEntity *pActivator, *pCaller, *pDest;
edict_t *pEdict;
IServerUnknown *pUnk;
char *inputname;
unsigned char vstk[sizeof(void *) + sizeof(const char *) + sizeof(CBaseEntity *)*2 + SIZEOF_VARIANT_T + sizeof(int)];
unsigned char *vptr = vstk;
ENTINDEX_TO_CBASEENTITY(params[1], pDest);
pContext->LocalToString(params[2], &inputname);
if (params[3] == -1)
{
pActivator = NULL;
} else {
ENTINDEX_TO_CBASEENTITY(params[3], pActivator);
}
if (params[4] == -1)
{
pCaller = NULL;
} else {
ENTINDEX_TO_CBASEENTITY(params[4], pCaller);
}
*(void **)vptr = pDest;
vptr += sizeof(void *);
*(const char **)vptr = inputname;
vptr += sizeof(const char *);
*(CBaseEntity **)vptr = pActivator;
vptr += sizeof(CBaseEntity *);
*(CBaseEntity **)vptr = pCaller;
vptr += sizeof(CBaseEntity *);
memcpy(vptr, g_Variant_t, SIZEOF_VARIANT_T);
vptr += SIZEOF_VARIANT_T;
*(int *)vptr = params[5];
bool ret;
g_pAcceptInput->Execute(vstk, &ret);
_init_variant_t();
return (ret) ? 1 : 0;
}
static cell_t SetVariantBool(IPluginContext *pContext, const cell_t *params)
{
unsigned char *vptr = g_Variant_t;
*(bool *)vptr = (params[1]) ? true : false;
vptr += sizeof(int)*3 + sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_BOOLEAN;
return 1;
}
static cell_t SetVariantString(IPluginContext *pContext, const cell_t *params)
{
char *str;
unsigned char *vptr = g_Variant_t;
pContext->LocalToString(params[1], &str);
*(string_t *)vptr = MAKE_STRING(str);
vptr += sizeof(int)*3 + sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_STRING;
return 1;
}
static cell_t SetVariantInt(IPluginContext *pContext, const cell_t *params)
{
unsigned char *vptr = g_Variant_t;
*(int *)vptr = params[1];
vptr += sizeof(int)*3 + sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_INTEGER;
return 1;
}
static cell_t SetVariantFloat(IPluginContext *pContext, const cell_t *params)
{
unsigned char *vptr = g_Variant_t;
*(float *)vptr = sp_ctof(params[1]);
vptr += sizeof(int)*3 + sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_FLOAT;
return 1;
}
static cell_t SetVariantVector3D(IPluginContext *pContext, const cell_t *params)
{
cell_t *val;
unsigned char *vptr = g_Variant_t;
pContext->LocalToPhysAddr(params[1], &val);
*(float *)vptr = sp_ctof(val[0]);
vptr += sizeof(float);
*(float *)vptr = sp_ctof(val[1]);
vptr += sizeof(float);
*(float *)vptr = sp_ctof(val[2]);
vptr += sizeof(float) + sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_VECTOR;
return 1;
}
static cell_t SetVariantPosVector3D(IPluginContext *pContext, const cell_t *params)
{
cell_t *val;
unsigned char *vptr = g_Variant_t;
pContext->LocalToPhysAddr(params[1], &val);
*(float *)vptr = sp_ctof(val[0]);
vptr += sizeof(float);
*(float *)vptr = sp_ctof(val[1]);
vptr += sizeof(float);
*(float *)vptr = sp_ctof(val[2]);
vptr += sizeof(float) + sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_POSITION_VECTOR;
return 1;
}
static cell_t SetVariantColor(IPluginContext *pContext, const cell_t *params)
{
cell_t *val;
unsigned char *vptr = g_Variant_t;
pContext->LocalToPhysAddr(params[1], &val);
*(unsigned char *)vptr = val[0];
vptr += sizeof(unsigned char);
*(unsigned char *)vptr = val[1];
vptr += sizeof(unsigned char);
*(unsigned char *)vptr = val[2];
vptr += sizeof(unsigned char);
*(unsigned char *)vptr = val[3];
vptr += sizeof(unsigned char) + sizeof(int)*2 + sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_COLOR32;
return 1;
}
static cell_t SetVariantEntity(IPluginContext *pContext, const cell_t *params)
{
CBaseEntity *pEntity;
edict_t *pEdict;
IServerUnknown *pUnk;
unsigned char *vptr = g_Variant_t;
CBaseHandle bHandle;
ENTINDEX_TO_CBASEENTITY(params[1], pEntity);
bHandle = reinterpret_cast<IHandleEntity *>(pEntity)->GetRefEHandle();
vptr += sizeof(int)*3;
*(unsigned long *)vptr = (unsigned long)(bHandle.ToInt());
vptr += sizeof(unsigned long);
*(fieldtype_t *)vptr = FIELD_EHANDLE;
return 1;
}
sp_nativeinfo_t g_EntInputNatives[] =
{
{"AcceptEntityInput", AcceptEntityInput},
{"SetVariantBool", SetVariantBool},
{"SetVariantString", SetVariantString},
{"SetVariantInt", SetVariantInt},
{"SetVariantFloat", SetVariantFloat},
{"SetVariantVector3D", SetVariantVector3D},
{"SetVariantPosVector3D", SetVariantPosVector3D},
{"SetVariantColor", SetVariantColor},
{"SetVariantEntity", SetVariantEntity},
{NULL, NULL},
};
+32
View File
@@ -0,0 +1,32 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdktools", "sdktools.vcproj", "{7A740927-C751-4312-BF9D-6367F8C508F8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - Episode 1|Win32 = Debug - Episode 1|Win32
Debug - Old Metamod|Win32 = Debug - Old Metamod|Win32
Debug - Orange Box|Win32 = Debug - Orange Box|Win32
Release - Episode 1|Win32 = Release - Episode 1|Win32
Release - Old Metamod|Win32 = Release - Old Metamod|Win32
Release - Orange Box|Win32 = Release - Orange Box|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.ActiveCfg = Debug - Episode 1|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.Build.0 = Debug - Episode 1|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Old Metamod|Win32.ActiveCfg = Debug - Old Metamod|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Old Metamod|Win32.Build.0 = Debug - Old Metamod|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.ActiveCfg = Release - Episode 1|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.Build.0 = Release - Episode 1|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Old Metamod|Win32.ActiveCfg = Release - Old Metamod|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Old Metamod|Win32.Build.0 = Release - Old Metamod|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+649
View File
@@ -0,0 +1,649 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="sdktools"
ProjectGUID="{7A740927-C751-4312-BF9D-6367F8C508F8}"
RootNamespace="sdk"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug - Old Metamod|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;&quot;$(HL2SDK)\public&quot;;&quot;$(HL2SDK)\public\dlls&quot;;&quot;$(HL2SDK)\public\engine&quot;;&quot;$(HL2SDK)\public\tier0&quot;;&quot;$(HL2SDK)\public\tier1&quot;;&quot;$(SOURCEMM14)&quot;;&quot;$(SOURCEMM14)\sourcemm&quot;;&quot;$(SOURCEMM14)\sourcehook&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
EnableEnhancedInstructionSet="1"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="&quot;$(HL2SDK)\lib\public\tier0.lib&quot; &quot;$(HL2SDK)\lib\public\tier1.lib&quot; &quot;$(HL2SDK)\lib\public\vstdlib.lib&quot; &quot;$(HL2SDK)\lib\public\mathlib.lib&quot;"
OutputFile="$(OutDir)\sdktools.ext.dll"
LinkIncremental="2"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release - Old Metamod|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;&quot;$(HL2SDK)\public&quot;;&quot;$(HL2SDK)\public\dlls&quot;;&quot;$(HL2SDK)\public\engine&quot;;&quot;$(HL2SDK)\public\tier0&quot;;&quot;$(HL2SDK)\public\tier1&quot;;&quot;$(SOURCEMM14)&quot;;&quot;$(SOURCEMM14)\sourcemm&quot;;&quot;$(SOURCEMM14)\sourcehook&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
RuntimeLibrary="0"
EnableEnhancedInstructionSet="1"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="&quot;$(HL2SDK)\lib\public\tier0.lib&quot; &quot;$(HL2SDK)\lib\public\tier1.lib&quot; &quot;$(HL2SDK)\lib\public\vstdlib.lib&quot; &quot;$(HL2SDK)\lib\public\mathlib.lib&quot;"
OutputFile="$(OutDir)\sdktools.ext.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug - Orange Box|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;&quot;$(HL2SDKOB)\common&quot;;&quot;$(HL2SDKOB)\public&quot;;&quot;$(HL2SDKOB)\public\engine&quot;;&quot;$(HL2SDKOB)\public\game\server&quot;;&quot;$(HL2SDKOB)\public\tier0&quot;;&quot;$(HL2SDKOB)\public\tier1&quot;;&quot;$(SOURCEMM16)&quot;;&quot;$(SOURCEMM16)\sourcemm&quot;;&quot;$(SOURCEMM16)\sourcehook&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
EnableEnhancedInstructionSet="1"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="&quot;$(HL2SDKOB)\lib\public\tier0.lib&quot; &quot;$(HL2SDKOB)\lib\public\tier1.lib&quot; &quot;$(HL2SDKOB)\lib\public\vstdlib.lib&quot; &quot;$(HL2SDKOB)\lib\public\mathlib.lib&quot;"
OutputFile="$(OutDir)\sdktools.ext.dll"
LinkIncremental="2"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release - Orange Box|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;&quot;$(HL2SDKOB)\common&quot;;&quot;$(HL2SDKOB)\public&quot;;&quot;$(HL2SDKOB)\public\engine&quot;;&quot;$(HL2SDKOB)\public\game\server&quot;;&quot;$(HL2SDKOB)\public\tier0&quot;;&quot;$(HL2SDKOB)\public\tier1&quot;;&quot;$(SOURCEMM16)&quot;;&quot;$(SOURCEMM16)\sourcemm&quot;;&quot;$(SOURCEMM16)\sourcehook&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
RuntimeLibrary="0"
EnableEnhancedInstructionSet="1"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="&quot;$(HL2SDKOB)\lib\public\tier0.lib&quot; &quot;$(HL2SDKOB)\lib\public\tier1.lib&quot; &quot;$(HL2SDKOB)\lib\public\vstdlib.lib&quot; &quot;$(HL2SDKOB)\lib\public\mathlib.lib&quot;"
OutputFile="$(OutDir)\sdktools.ext.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug - Episode 1|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;&quot;$(HL2SDK)\public&quot;;&quot;$(HL2SDK)\public\dlls&quot;;&quot;$(HL2SDK)\public\engine&quot;;&quot;$(HL2SDK)\public\tier0&quot;;&quot;$(HL2SDK)\public\tier1&quot;;&quot;$(SOURCEMM16)&quot;;&quot;$(SOURCEMM16)\sourcemm&quot;;&quot;$(SOURCEMM16)\sourcehook&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
EnableEnhancedInstructionSet="1"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="&quot;$(HL2SDK)\lib\public\tier0.lib&quot; &quot;$(HL2SDK)\lib\public\tier1.lib&quot; &quot;$(HL2SDK)\lib\public\vstdlib.lib&quot; &quot;$(HL2SDK)\lib\public\mathlib.lib&quot;"
OutputFile="$(OutDir)\sdktools.ext.dll"
LinkIncremental="2"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release - Episode 1|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;&quot;$(HL2SDK)\public&quot;;&quot;$(HL2SDK)\public\dlls&quot;;&quot;$(HL2SDK)\public\engine&quot;;&quot;$(HL2SDK)\public\tier0&quot;;&quot;$(HL2SDK)\public\tier1&quot;;&quot;$(SOURCEMM16)&quot;;&quot;$(SOURCEMM16)\sourcemm&quot;;&quot;$(SOURCEMM16)\sourcehook&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
RuntimeLibrary="0"
EnableEnhancedInstructionSet="1"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="&quot;$(HL2SDK)\lib\public\tier0.lib&quot; &quot;$(HL2SDK)\lib\public\tier1.lib&quot; &quot;$(HL2SDK)\lib\public\vstdlib.lib&quot; &quot;$(HL2SDK)\lib\public\mathlib.lib&quot;"
OutputFile="$(OutDir)\sdktools.ext.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{3FC90E55-360F-4370-ACE2-67D7691AFB97}"
>
<File
RelativePath="..\extension.cpp"
>
</File>
<File
RelativePath="..\inputnatives.cpp"
>
</File>
<File
RelativePath="..\teamnatives.cpp"
>
</File>
<File
RelativePath="..\tempents.cpp"
>
</File>
<File
RelativePath="..\tenatives.cpp"
>
</File>
<File
RelativePath="..\trnatives.cpp"
>
</File>
<File
RelativePath="..\vcallbuilder.cpp"
>
</File>
<File
RelativePath="..\vcaller.cpp"
>
</File>
<File
RelativePath="..\vdecoder.cpp"
>
</File>
<File
RelativePath="..\vglobals.cpp"
>
</File>
<File
RelativePath="..\vhelpers.cpp"
>
</File>
<File
RelativePath="..\vnatives.cpp"
>
</File>
<File
RelativePath="..\voice.cpp"
>
</File>
<File
RelativePath="..\vsound.cpp"
>
</File>
<File
RelativePath="..\vstringtable.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{046AC4F8-1F40-462f-B652-698F87CDCA5F}"
>
<File
RelativePath="..\CellRecipientFilter.h"
>
</File>
<File
RelativePath="..\extension.h"
>
</File>
<File
RelativePath="..\tempents.h"
>
</File>
<File
RelativePath="..\vcallbuilder.h"
>
</File>
<File
RelativePath="..\vdecoder.h"
>
</File>
<File
RelativePath="..\vglobals.h"
>
</File>
<File
RelativePath="..\vhelpers.h"
>
</File>
<File
RelativePath="..\vnatives.h"
>
</File>
<File
RelativePath="..\vsound.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{4B7443F9-4DC9-4e59-BC1B-465800502EBC}"
>
<File
RelativePath="..\version.rc"
>
</File>
</Filter>
<Filter
Name="SourceMod SDK"
UniqueIdentifier="{223A2FA5-451B-4af5-9E85-162BF3598F7B}"
>
<File
RelativePath="..\sdk\smsdk_config.h"
>
</File>
<File
RelativePath="..\sdk\smsdk_ext.cpp"
>
</File>
<File
RelativePath="..\sdk\smsdk_ext.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+75
View File
@@ -0,0 +1,75 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
/**
* @file smsdk_config.h
* @brief Contains macros for configuring basic extension information.
*/
#include "svn_version.h"
/* Basic information exposed publicly */
#define SMEXT_CONF_NAME "SDK Tools"
#define SMEXT_CONF_DESCRIPTION "Source SDK Tools"
#define SMEXT_CONF_VERSION SVN_FULL_VERSION
#define SMEXT_CONF_AUTHOR "AlliedModders LLC"
#define SMEXT_CONF_URL "http://www.sourcemod.net/"
#define SMEXT_CONF_LOGTAG "SDKTOOLS"
#define SMEXT_CONF_LICENSE "GPL"
#define SMEXT_CONF_DATESTRING __DATE__
/**
* @brief Exposes plugin's main interface.
*/
#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name;
/**
* @brief Sets whether or not this plugin required Metamod.
* NOTE: Uncomment to enable, comment to disable.
*/
#define SMEXT_CONF_METAMOD
/** Enable interfaces you want to use here by uncommenting lines */
//#define SMEXT_ENABLE_FORWARDSYS
#define SMEXT_ENABLE_HANDLESYS
#define SMEXT_ENABLE_PLAYERHELPERS
//#define SMEXT_ENABLE_DBMANAGER
#define SMEXT_ENABLE_GAMECONF
#define SMEXT_ENABLE_MEMUTILS
#define SMEXT_ENABLE_GAMEHELPERS
//#define SMEXT_ENABLE_TIMERSYS
#define SMEXT_ENABLE_ADTFACTORY
#define SMEXT_ENABLE_PLUGINSYS
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
+422
View File
@@ -0,0 +1,422 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Base Extension Code
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <stdio.h>
#include <malloc.h>
#include "smsdk_ext.h"
/**
* @file smsdk_ext.cpp
* @brief Contains wrappers for making Extensions easier to write.
*/
IExtension *myself = NULL; /**< Ourself */
IShareSys *g_pShareSys = NULL; /**< Share system */
IShareSys *sharesys = NULL; /**< Share system */
ISourceMod *g_pSM = NULL; /**< SourceMod helpers */
ISourceMod *smutils = NULL; /**< SourceMod helpers */
#if defined SMEXT_ENABLE_FORWARDSYS
IForwardManager *g_pForwards = NULL; /**< Forward system */
IForwardManager *forwards = NULL; /**< Forward system */
#endif
#if defined SMEXT_ENABLE_HANDLESYS
IHandleSys *g_pHandleSys = NULL; /**< Handle system */
IHandleSys *handlesys = NULL; /**< Handle system */
#endif
#if defined SMEXT_ENABLE_PLAYERHELPERS
IPlayerManager *playerhelpers = NULL; /**< Player helpers */
#endif //SMEXT_ENABLE_PLAYERHELPERS
#if defined SMEXT_ENABLE_DBMANAGER
IDBManager *dbi = NULL; /**< DB Manager */
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMECONF
IGameConfigManager *gameconfs = NULL; /**< Game config manager */
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_MEMUTILS
IMemoryUtils *memutils = NULL;
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMEHELPERS
IGameHelpers *gamehelpers = NULL;
#endif
#if defined SMEXT_ENABLE_TIMERSYS
ITimerSystem *timersys = NULL;
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
IADTFactory *adtfactory = NULL;
#endif
#if defined SMEXT_ENABLE_THREADER
IThreader *threader = NULL;
#endif
#if defined SMEXT_ENABLE_LIBSYS
ILibrarySys *libsys = NULL;
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
SourceMod::IPluginManager *plsys;
#endif
/** Exports the main interface */
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
{
return g_pExtensionIface;
}
SDKExtension::SDKExtension()
{
#if defined SMEXT_CONF_METAMOD
m_SourceMMLoaded = false;
m_WeAreUnloaded = false;
m_WeGotPauseChange = false;
#endif
}
bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late)
{
g_pShareSys = sharesys = sys;
myself = me;
#if defined SMEXT_CONF_METAMOD
m_WeAreUnloaded = true;
if (!m_SourceMMLoaded)
{
if (error)
{
snprintf(error, maxlength, "Metamod attach failed");
}
return false;
}
#endif
SM_GET_IFACE(SOURCEMOD, g_pSM);
smutils = g_pSM;
#if defined SMEXT_ENABLE_HANDLESYS
SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys);
handlesys = g_pHandleSys;
#endif
#if defined SMEXT_ENABLE_FORWARDSYS
SM_GET_IFACE(FORWARDMANAGER, g_pForwards);
forwards = g_pForwards;
#endif
#if defined SMEXT_ENABLE_PLAYERHELPERS
SM_GET_IFACE(PLAYERMANAGER, playerhelpers);
#endif
#if defined SMEXT_ENABLE_DBMANAGER
SM_GET_IFACE(DBI, dbi);
#endif
#if defined SMEXT_ENABLE_GAMECONF
SM_GET_IFACE(GAMECONFIG, gameconfs);
#endif
#if defined SMEXT_ENABLE_MEMUTILS
SM_GET_IFACE(MEMORYUTILS, memutils);
#endif
#if defined SMEXT_ENABLE_GAMEHELPERS
SM_GET_IFACE(GAMEHELPERS, gamehelpers);
#endif
#if defined SMEXT_ENABLE_TIMERSYS
SM_GET_IFACE(TIMERSYS, timersys);
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
SM_GET_IFACE(ADTFACTORY, adtfactory);
#endif
#if defined SMEXT_ENABLE_THREADER
SM_GET_IFACE(THREADER, threader);
#endif
#if defined SMEXT_ENABLE_LIBSYS
SM_GET_IFACE(LIBRARYSYS, libsys);
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
SM_GET_IFACE(PLUGINSYSTEM, plsys);
#endif
if (SDK_OnLoad(error, maxlength, late))
{
#if defined SMEXT_CONF_METAMOD
m_WeAreUnloaded = true;
#endif
return true;
}
return false;
}
bool SDKExtension::IsMetamodExtension()
{
#if defined SMEXT_CONF_METAMOD
return true;
#else
return false;
#endif
}
void SDKExtension::OnExtensionPauseChange(bool state)
{
#if defined SMEXT_CONF_METAMOD
m_WeGotPauseChange = true;
#endif
SDK_OnPauseChange(state);
}
void SDKExtension::OnExtensionsAllLoaded()
{
SDK_OnAllLoaded();
}
void SDKExtension::OnExtensionUnload()
{
#if defined SMEXT_CONF_METAMOD
m_WeAreUnloaded = true;
#endif
SDK_OnUnload();
}
const char *SDKExtension::GetExtensionAuthor()
{
return SMEXT_CONF_AUTHOR;
}
const char *SDKExtension::GetExtensionDateString()
{
return SMEXT_CONF_DATESTRING;
}
const char *SDKExtension::GetExtensionDescription()
{
return SMEXT_CONF_DESCRIPTION;
}
const char *SDKExtension::GetExtensionVerString()
{
return SMEXT_CONF_VERSION;
}
const char *SDKExtension::GetExtensionName()
{
return SMEXT_CONF_NAME;
}
const char *SDKExtension::GetExtensionTag()
{
return SMEXT_CONF_LOGTAG;
}
const char *SDKExtension::GetExtensionURL()
{
return SMEXT_CONF_URL;
}
bool SDKExtension::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
return true;
}
void SDKExtension::SDK_OnUnload()
{
}
void SDKExtension::SDK_OnPauseChange(bool paused)
{
}
void SDKExtension::SDK_OnAllLoaded()
{
}
#if defined SMEXT_CONF_METAMOD
PluginId g_PLID = 0; /**< Metamod plugin ID */
ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */
SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */
ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */
IVEngineServer *engine = NULL; /**< IVEngineServer pointer */
IServerGameDLL *gamedll = NULL; /**< IServerGameDLL pointer */
/** Exposes the extension to Metamod */
SMM_API void *PL_EXPOSURE(const char *name, int *code)
{
if (name && !strcmp(name, METAMOD_PLAPI_NAME))
{
if (code)
{
*code = IFACE_OK;
}
return static_cast<void *>(g_pExtensionIface);
}
if (code)
{
*code = IFACE_FAILED;
}
return NULL;
}
bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
{
PLUGIN_SAVEVARS();
GET_V_IFACE_ANY(GetServerFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
m_SourceMMLoaded = true;
return SDK_OnMetamodLoad(ismm, error, maxlen, late);
}
bool SDKExtension::Unload(char *error, size_t maxlen)
{
if (!m_WeAreUnloaded)
{
if (error)
{
snprintf(error, maxlen, "This extension must be unloaded by SourceMod.");
}
return false;
}
return SDK_OnMetamodUnload(error, maxlen);
}
bool SDKExtension::Pause(char *error, size_t maxlen)
{
if (!m_WeGotPauseChange)
{
if (error)
{
snprintf(error, maxlen, "This extension must be paused by SourceMod.");
}
return false;
}
m_WeGotPauseChange = false;
return SDK_OnMetamodPauseChange(true, error, maxlen);
}
bool SDKExtension::Unpause(char *error, size_t maxlen)
{
if (!m_WeGotPauseChange)
{
if (error)
{
snprintf(error, maxlen, "This extension must be unpaused by SourceMod.");
}
return false;
}
m_WeGotPauseChange = false;
return SDK_OnMetamodPauseChange(false, error, maxlen);
}
const char *SDKExtension::GetAuthor()
{
return GetExtensionAuthor();
}
const char *SDKExtension::GetDate()
{
return GetExtensionDateString();
}
const char *SDKExtension::GetDescription()
{
return GetExtensionDescription();
}
const char *SDKExtension::GetLicense()
{
return SMEXT_CONF_LICENSE;
}
const char *SDKExtension::GetLogTag()
{
return GetExtensionTag();
}
const char *SDKExtension::GetName()
{
return GetExtensionName();
}
const char *SDKExtension::GetURL()
{
return GetExtensionURL();
}
const char *SDKExtension::GetVersion()
{
return GetExtensionVerString();
}
bool SDKExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late)
{
return true;
}
bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t maxlength)
{
return true;
}
bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength)
{
return true;
}
#endif
/* Overload a few things to prevent libstdc++ linking */
#if defined __linux__
extern "C" void __cxa_pure_virtual(void)
{
}
void *operator new(size_t size)
{
return malloc(size);
}
void *operator new[](size_t size)
{
return malloc(size);
}
void operator delete(void *ptr)
{
free(ptr);
}
void operator delete[](void * ptr)
{
free(ptr);
}
#endif
+310
View File
@@ -0,0 +1,310 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Base Extension Code
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
/**
* @file smsdk_ext.h
* @brief Contains wrappers for making Extensions easier to write.
*/
#include "smsdk_config.h"
#include <IExtensionSys.h>
#include <IHandleSys.h>
#include <sp_vm_api.h>
#include <sm_platform.h>
#include <ISourceMod.h>
#if defined SMEXT_ENABLE_FORWARDSYS
#include <IForwardSys.h>
#endif //SMEXT_ENABLE_FORWARDSYS
#if defined SMEXT_ENABLE_PLAYERHELPERS
#include <IPlayerHelpers.h>
#endif //SMEXT_ENABLE_PlAYERHELPERS
#if defined SMEXT_ENABLE_DBMANAGER
#include <IDBDriver.h>
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMECONF
#include <IGameConfigs.h>
#endif
#if defined SMEXT_ENABLE_MEMUTILS
#include <IMemoryUtils.h>
#endif
#if defined SMEXT_ENABLE_GAMEHELPERS
#include <IGameHelpers.h>
#endif
#if defined SMEXT_ENABLE_TIMERSYS
#include <ITimerSystem.h>
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
#include <IADTFactory.h>
#endif
#if defined SMEXT_ENABLE_THREADER
#include <IThreader.h>
#endif
#if defined SMEXT_ENABLE_LIBSYS
#include <ILibrarySys.h>
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
#include <IPluginSys.h>
#endif
#if defined SMEXT_CONF_METAMOD
#include <ISmmPlugin.h>
#include <eiface.h>
#endif
#if !defined METAMOD_PLAPI_VERSION
#include <metamod_wrappers.h>
#endif
using namespace SourceMod;
using namespace SourcePawn;
class SDKExtension :
#if defined SMEXT_CONF_METAMOD
public ISmmPlugin,
#endif
public IExtensionInterface
{
public:
/** Constructor */
SDKExtension();
public:
/**
* @brief This is called after the initial loading sequence has been processed.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @param late Whether or not the module was loaded after map load.
* @return True to succeed loading, false to fail.
*/
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
/**
* @brief This is called right before the extension is unloaded.
*/
virtual void SDK_OnUnload();
/**
* @brief This is called once all known extensions have been loaded.
*/
virtual void SDK_OnAllLoaded();
/**
* @brief Called when the pause state is changed.
*/
virtual void SDK_OnPauseChange(bool paused);
#if defined SMEXT_CONF_METAMOD
/**
* @brief Called when Metamod is attached, before the extension version is called.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @param late Whether or not Metamod considers this a late load.
* @return True to succeed, false to fail.
*/
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
/**
* @brief Called when Metamod is detaching, after the extension version is called.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
/**
* @brief Called when Metamod's pause state is changing.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param paused Pause state being set.
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
#endif
public: //IExtensionInterface
virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late);
virtual void OnExtensionUnload();
virtual void OnExtensionsAllLoaded();
/** Returns whether or not this is a Metamod-based extension */
virtual bool IsMetamodExtension();
/**
* @brief Called when the pause state changes.
*
* @param state True if being paused, false if being unpaused.
*/
virtual void OnExtensionPauseChange(bool state);
/** Returns name */
virtual const char *GetExtensionName();
/** Returns URL */
virtual const char *GetExtensionURL();
/** Returns log tag */
virtual const char *GetExtensionTag();
/** Returns author */
virtual const char *GetExtensionAuthor();
/** Returns version string */
virtual const char *GetExtensionVerString();
/** Returns description string */
virtual const char *GetExtensionDescription();
/** Returns date string */
virtual const char *GetExtensionDateString();
#if defined SMEXT_CONF_METAMOD
public: //ISmmPlugin
/** Called when the extension is attached to Metamod. */
virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late);
/** Returns the author to MM */
virtual const char *GetAuthor();
/** Returns the name to MM */
virtual const char *GetName();
/** Returns the description to MM */
virtual const char *GetDescription();
/** Returns the URL to MM */
virtual const char *GetURL();
/** Returns the license to MM */
virtual const char *GetLicense();
/** Returns the version string to MM */
virtual const char *GetVersion();
/** Returns the date string to MM */
virtual const char *GetDate();
/** Returns the logtag to MM */
virtual const char *GetLogTag();
/** Called on unload */
virtual bool Unload(char *error, size_t maxlength);
/** Called on pause */
virtual bool Pause(char *error, size_t maxlength);
/** Called on unpause */
virtual bool Unpause(char *error, size_t maxlength);
private:
bool m_SourceMMLoaded;
bool m_WeAreUnloaded;
bool m_WeGotPauseChange;
#endif
};
extern SDKExtension *g_pExtensionIface;
extern IExtension *myself;
extern IShareSys *g_pShareSys;
extern IShareSys *sharesys; /* Note: Newer name */
extern ISourceMod *g_pSM;
extern ISourceMod *smutils; /* Note: Newer name */
/* Optional interfaces are below */
#if defined SMEXT_ENABLE_FORWARDSYS
extern IForwardManager *g_pForwards;
extern IForwardManager *forwards; /* Note: Newer name */
#endif //SMEXT_ENABLE_FORWARDSYS
#if defined SMEXT_ENABLE_HANDLESYS
extern IHandleSys *g_pHandleSys;
extern IHandleSys *handlesys; /* Note: Newer name */
#endif //SMEXT_ENABLE_HANDLESYS
#if defined SMEXT_ENABLE_PLAYERHELPERS
extern IPlayerManager *playerhelpers;
#endif //SMEXT_ENABLE_PLAYERHELPERS
#if defined SMEXT_ENABLE_DBMANAGER
extern IDBManager *dbi;
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMECONF
extern IGameConfigManager *gameconfs;
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_MEMUTILS
extern IMemoryUtils *memutils;
#endif
#if defined SMEXT_ENABLE_GAMEHELPERS
extern IGameHelpers *gamehelpers;
#endif
#if defined SMEXT_ENABLE_TIMERSYS
extern ITimerSystem *timersys;
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
extern IADTFactory *adtfactory;
#endif
#if defined SMEXT_ENABLE_THREADER
extern IThreader *threader;
#endif
#if defined SMEXT_ENABLE_LIBSYS
extern ILibrarySys *libsys;
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
extern SourceMod::IPluginManager *plsys;
#endif
#if defined SMEXT_CONF_METAMOD
PLUGIN_GLOBALVARS();
extern IVEngineServer *engine;
extern IServerGameDLL *gamedll;
#endif
/** Creates a SourceMod interface macro pair */
#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION
/** Automates retrieving SourceMod interfaces */
#define SM_GET_IFACE(prefix, addr) \
if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) \
{ \
if (error != NULL && maxlength) \
{ \
size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
if (len >= maxlength) \
{ \
error[maxlength - 1] = '\0'; \
} \
} \
return false; \
}
/** Automates retrieving SourceMod interfaces when needed outside of SDK_OnLoad() */
#define SM_GET_LATE_IFACE(prefix, addr) \
g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)
/** Validates a SourceMod interface pointer */
#define SM_CHECK_IFACE(prefix, addr) \
if (!addr) \
{ \
if (error != NULL && maxlength) \
{ \
size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
if (len >= maxlength) \
{ \
error[maxlength - 1] = '\0'; \
} \
} \
return false; \
}
#endif // _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
+42
View File
@@ -0,0 +1,42 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
/**
* Autogenerated by build scripts
*/
#ifndef _INCLUDE_SDKTOOLS_VERSION_H_
#define _INCLUDE_SDKTOOLS_VERSION_H_
#define SVN_FULL_VERSION "1.0.0.1930"
#define SVN_FILE_VERSION 1,0,0,1930
#endif //_INCLUDE_SDKTOOLS_VERSION_H_
+42
View File
@@ -0,0 +1,42 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
/**
* Autogenerated by build scripts
*/
#ifndef _INCLUDE_SDKTOOLS_VERSION_H_
#define _INCLUDE_SDKTOOLS_VERSION_H_
#define SVN_FULL_VERSION "$PMAJOR$.$PMINOR$.$PREVISION$.$LOCAL_BUILD$"
#define SVN_FILE_VERSION $PMAJOR$,$PMINOR$,$PREVISION$,$LOCAL_BUILD$
#endif //_INCLUDE_SDKTOOLS_VERSION_H_
+176
View File
@@ -0,0 +1,176 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
#include <sh_vector.h>
struct TeamInfo
{
const char *ClassName;
CBaseEntity *pEnt;
};
SourceHook::CVector<TeamInfo> g_Teams;
bool FindTeamEntities(SendTable *pTable, const char *name)
{
int props = pTable->GetNumProps();
SendProp *prop;
for (int i=0; i<props; i++)
{
prop = pTable->GetProp(i);
if (prop->GetDataTable())
{
if (strcmp(prop->GetDataTable()->GetName(), name) == 0)
{
return true;
}
if (FindTeamEntities(prop->GetDataTable(), name))
{
return true;
}
}
}
return false;
}
void SDKTools::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
{
g_Teams.clear();
g_Teams.resize(1);
for (int i=0; i<edictCount; i++)
{
edict_t *pEdict = engine->PEntityOfEntIndex(i);
if (!pEdict || pEdict->IsFree())
{
continue;
}
if (!pEdict->GetNetworkable())
{
continue;
}
ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
if (FindTeamEntities(pClass->m_pTable, "DT_Team"))
{
SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
if (pTeamNumProp != NULL)
{
int offset = pTeamNumProp->GetOffset();
CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
if (TeamIndex >= (int)g_Teams.size())
{
g_Teams.resize(TeamIndex+1);
}
g_Teams[TeamIndex].ClassName = pClass->GetName();
g_Teams[TeamIndex].pEnt = pEnt;
}
}
}
}
static cell_t GetTeamCount(IPluginContext *pContext, const cell_t *params)
{
return g_Teams.size();
}
static cell_t GetTeamName(IPluginContext *pContext, const cell_t *params)
{
int teamindex = params[1];
if (teamindex > (int)g_Teams.size())
{
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
}
static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_szTeamname")->GetOffset();
char *name = (char *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
pContext->StringToLocalUTF8(params[2], params[3], name, NULL);
return 1;
}
static cell_t GetTeamScore(IPluginContext *pContext, const cell_t *params)
{
int teamindex = params[1];
if (teamindex > (int)g_Teams.size())
{
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
}
static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
return *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
}
static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params)
{
int teamindex = params[1];
if (teamindex > (int)g_Teams.size())
{
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
}
static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
*(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset) = params[2];
return 1;
}
static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params)
{
int teamindex = params[1];
if (teamindex > (int)g_Teams.size())
{
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
}
SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\"");
ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy();
return fn(g_Teams[teamindex].pEnt, 0);
}
sp_nativeinfo_t g_TeamNatives[] =
{
{"GetTeamCount", GetTeamCount},
{"GetTeamName", GetTeamName},
{"GetTeamScore", GetTeamScore},
{"SetTeamScore", SetTeamScore},
{"GetTeamClientCount", GetTeamClientCount},
{NULL, NULL}
};
+493
View File
@@ -0,0 +1,493 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "tempents.h"
TempEntityManager g_TEManager;
ICallWrapper *g_GetServerClass = NULL;
CON_COMMAND(sm_print_telist, "Prints the temp entity list")
{
if (!g_TEManager.IsAvailable())
{
META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
return;
}
g_TEManager.DumpList();
}
CON_COMMAND(sm_dump_teprops, "Dumps tempentity props to a file")
{
#if !defined ORANGEBOX_BUILD
CCommand args;
#endif
if (!g_TEManager.IsAvailable())
{
META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
return;
}
int argc = args.ArgC();
if (argc < 2)
{
META_CONPRINT("Usage: sm_dump_teprops <file>\n");
return;
}
const char *arg = args.Arg(1);
if (!arg || arg[0] == '\0')
{
META_CONPRINTF("Usage: sm_dump_teprops <file>\n");
return;
}
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", arg);
FILE *fp = NULL;
if ((fp = fopen(path, "wt")) == NULL)
{
META_CONPRINTF("Could not open file \"%s\"\n", path);
return;
}
g_TEManager.DumpProps(fp);
fclose(fp);
}
/*************************
* *
* Temp Entities Wrappers *
* *
**************************/
TempEntityInfo::TempEntityInfo(const char *name, void *me)
{
m_Name.assign(name);
m_Me = me;
g_GetServerClass->Execute(&m_Me, &m_Sc);
}
const char *TempEntityInfo::GetName()
{
return m_Name.c_str();
}
ServerClass *TempEntityInfo::GetServerClass()
{
return m_Sc;
}
bool TempEntityInfo::IsValidProp(const char *name)
{
return (g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name)) ? true : false;
}
int TempEntityInfo::_FindOffset(const char *name, int *size)
{
int offset;
SendProp *prop = g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name);
if (!prop)
{
return -1;
}
offset = prop->GetOffset();
if (size)
{
*size = prop->m_nBits;
}
return offset;
}
bool TempEntityInfo::TE_SetEntData(const char *name, int value)
{
/* Search for our offset */
int size;
int offset = _FindOffset(name, &size);
if (offset < 0)
{
return false;
}
if (size <= 8)
{
*((uint8_t *)m_Me + offset) = value;
} else if (size <= 16) {
*(short *)((uint8_t *)m_Me + offset) = value;
} else if (size <= 32) {
*(int *)((uint8_t *)m_Me + offset) = value;
} else {
return false;
}
return true;
}
bool TempEntityInfo::TE_GetEntData(const char *name, int *value)
{
/* Search for our offset */
int size;
int offset = _FindOffset(name, &size);
if (offset < 0)
{
return false;
}
if (size <= 8)
{
*value = *((uint8_t *)m_Me + offset);
} else if (size <= 16) {
*value = *(short *)((uint8_t *)m_Me + offset);
} else if (size <= 32) {
*value = *(int *)((uint8_t *)m_Me + offset);
} else {
return false;
}
return true;
}
bool TempEntityInfo::TE_SetEntDataFloat(const char *name, float value)
{
/* Search for our offset */
int offset = _FindOffset(name);
if (offset < 0)
{
return false;
}
*(float *)((uint8_t *)m_Me + offset) = value;
return true;
}
bool TempEntityInfo::TE_GetEntDataFloat(const char *name, float *value)
{
/* Search for our offset */
int offset = _FindOffset(name);
if (offset < 0)
{
return false;
}
*value = *(float *)((uint8_t *)m_Me + offset);
return true;
}
bool TempEntityInfo::TE_SetEntDataVector(const char *name, float vector[3])
{
/* Search for our offset */
int offset = _FindOffset(name);
if (offset < 0)
{
return false;
}
Vector *v = (Vector *)((uint8_t *)m_Me + offset);
v->x = vector[0];
v->y = vector[1];
v->z = vector[2];
return true;
}
bool TempEntityInfo::TE_GetEntDataVector(const char *name, float vector[3])
{
/* Search for our offset */
int offset = _FindOffset(name);
if (offset < 0)
{
return false;
}
Vector *v = (Vector *)((uint8_t *)m_Me + offset);
vector[0] = v->x;
vector[1] = v->y;
vector[2] = v->z;
return true;
}
bool TempEntityInfo::TE_SetEntDataFloatArray(const char *name, cell_t *array, int size)
{
/* Search for our offset */
int offset = _FindOffset(name);
if (offset < 0)
{
return false;
}
float *base = (float *)((uint8_t *)m_Me + offset);
for (int i=0; i<size; i++)
{
base[i] = sp_ctof(array[i]);
}
return true;
}
void TempEntityInfo::Send(IRecipientFilter &filter, float delay)
{
engine->PlaybackTempEntity(filter, delay, m_Me, m_Sc->m_pTable, m_Sc->m_ClassID);
}
/**********************
* *
* Temp Entity Manager *
* *
***********************/
void TempEntityManager::Initialize()
{
void *addr;
int offset;
m_Loaded = false;
/* Read our sigs and offsets from the config file */
#if defined PLATFORM_WINDOWS
if (!g_pGameConf->GetMemSig("CBaseTempEntity", &addr) || !addr)
{
return;
}
if (!g_pGameConf->GetOffset("s_pTempEntities", &offset))
{
return;
}
/* Store the head of the TE linked list */
m_ListHead = **(void ***)((unsigned char *)addr + offset);
#else
if (!g_pGameConf->GetMemSig("s_pTempEntities", &addr) || !addr)
{
return;
}
/* Store the head of the TE linked list */
m_ListHead = *(void **)addr;
#endif
if (!g_pGameConf->GetOffset("GetTEName", &m_NameOffs))
{
return;
}
if (!g_pGameConf->GetOffset("GetTENext", &m_NextOffs))
{
return;
}
if (!g_pGameConf->GetOffset("TE_GetServerClass", &m_GetClassNameOffs))
{
return;
}
/* Create our trie */
m_TempEntInfo = adtfactory->CreateBasicTrie();
/* Create the GetServerClass call */
PassInfo retinfo;
retinfo.flags = PASSFLAG_BYVAL;
retinfo.type = PassType_Basic;
retinfo.size = sizeof(ServerClass *);
g_GetServerClass = g_pBinTools->CreateVCall(m_GetClassNameOffs, 0, 0, &retinfo, NULL, 0);
/* We're done */
m_Loaded = true;
}
bool TempEntityManager::IsAvailable()
{
return m_Loaded;
}
void TempEntityManager::Shutdown()
{
if (!IsAvailable())
{
return;
}
SourceHook::List<TempEntityInfo *>::iterator iter;
for (iter=m_TEList.begin(); iter!=m_TEList.end(); iter++)
{
delete (*iter);
}
m_TEList.clear();
m_TempEntInfo->Destroy();
g_GetServerClass->Destroy();
g_GetServerClass = NULL;
m_ListHead = NULL;
m_NextOffs = m_NameOffs = m_GetClassNameOffs = 0;
m_Loaded = false;
}
TempEntityInfo *TempEntityManager::GetTempEntityInfo(const char *name)
{
/* If the system is unloaded skip the search */
if (!IsAvailable())
{
return NULL;
}
TempEntityInfo *te = NULL;
/* Start searching for the TE inside the engine */
if (!m_TempEntInfo->Retrieve(name, reinterpret_cast<void **>(&te)))
{
void *iter = m_ListHead;
while (iter)
{
const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
if (!realname)
{
continue;
}
if (strcmp(name, realname) == 0)
{
te = new TempEntityInfo(name, iter);
m_TempEntInfo->Insert(name, (void *)te);
m_TEList.push_back(te);
return te;
}
iter = *(void **)((unsigned char *)iter + m_NextOffs);
}
return NULL;
}
return te;
}
const char *TempEntityManager::GetNameFromThisPtr(void *me)
{
return *(const char **)((unsigned char *)me + m_NameOffs);
}
void TempEntityManager::DumpList()
{
unsigned int index = 0;
META_CONPRINT("Listing temp entities:\n");
void *iter = m_ListHead;
while (iter)
{
const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
if (!realname)
{
break;
}
TempEntityInfo *info = GetTempEntityInfo(realname);
if (!info)
{
continue;
}
ServerClass *sc = info->GetServerClass();
META_CONPRINTF("[%02d] %s (%s)\n", index++, realname, sc->GetName());
iter = *(void **)((unsigned char *)iter + m_NextOffs);
}
META_CONPRINTF("%d tempent%s found.\n", index, (index == 1) ? " was" : "s were");
}
const char *SendPropTypeToString(SendPropType type)
{
if (type == DPT_Int)
{
return "int";
} else if (type == DPT_Float) {
return "float";
} else if (type == DPT_Vector) {
return "vector";
} else if (type == DPT_String) {
return "string";
} else if (type == DPT_Array) {
return "array";
} else if (type == DPT_DataTable) {
return "datatable";
} else {
return "unknown";
}
}
void _DumpProps(FILE *fp, SendTable *pTable)
{
SendTable *pOther;
for (int i=0; i<pTable->GetNumProps(); i++)
{
SendProp *prop = pTable->GetProp(i);
if ((pOther = prop->GetDataTable()) != NULL)
{
_DumpProps(fp, pOther);
} else {
fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n",
prop->GetName() ? prop->GetName() : "unknown",
SendPropTypeToString(prop->GetType()));
}
}
}
void TempEntityManager::DumpProps(FILE *fp)
{
unsigned int index = 0;
void *iter = m_ListHead;
fprintf(fp, "\"TempEnts\"\n{\n");
while (iter)
{
const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
if (!realname)
{
break;
}
TempEntityInfo *info = GetTempEntityInfo(realname);
if (!info)
{
continue;
}
ServerClass *sc = info->GetServerClass();
fprintf(fp, "\t\"%s\"\n", sc->GetName());
fprintf(fp, "\t{\n");
fprintf(fp, "\t\t\"name\"\t\t\"%s\"\n", realname);
fprintf(fp, "\t\t\"index\"\t\t\"%d\"\n", index++);
fprintf(fp, "\t\t\"SendTable\"\n\t\t{\n");
_DumpProps(fp, sc->m_pTable);
fprintf(fp, "\t\t}\n\t}\n");
iter = *(void **)((unsigned char *)iter + m_NextOffs);
}
fprintf(fp, "}\n");
META_CONPRINTF("%d tempent%s written to file.\n", index, (index == 1) ? " was" : "s were");
}
+118
View File
@@ -0,0 +1,118 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_TEMPENTS_H_
#define _INCLUDE_SOURCEMOD_TEMPENTS_H_
#include "extension.h"
#include <irecipientfilter.h>
#include <sh_list.h>
#include <sh_string.h>
#include <stdio.h>
class TempEntityInfo
{
public:
TempEntityInfo(const char *name, void *me);
public:
const char *GetName();
ServerClass *GetServerClass();
bool IsValidProp(const char *name);
bool TE_SetEntData(const char *name, int value);
bool TE_SetEntDataFloat(const char *name, float value);
bool TE_SetEntDataVector(const char *name, float vector[3]);
bool TE_SetEntDataFloatArray(const char *name, cell_t *array, int size);
bool TE_GetEntData(const char *name, int *value);
bool TE_GetEntDataFloat(const char *name, float *value);
bool TE_GetEntDataVector(const char *name, float vector[3]);
void Send(IRecipientFilter &filter, float delay);
private:
int _FindOffset(const char *name, int *size=NULL);
private:
void *m_Me;
ServerClass *m_Sc;
SourceHook::String m_Name;
};
class TempEntityManager
{
public:
TempEntityManager() : m_NameOffs(0), m_NextOffs(0), m_GetClassNameOffs(0), m_Loaded(false) {}
public:
void Initialize();
bool IsAvailable();
void Shutdown();
public:
TempEntityInfo *GetTempEntityInfo(const char *name);
const char *GetNameFromThisPtr(void *me);
public:
void DumpList();
void DumpProps(FILE *fp);
private:
SourceHook::List<TempEntityInfo *> m_TEList;
IBasicTrie *m_TempEntInfo;
void *m_ListHead;
int m_NameOffs;
int m_NextOffs;
int m_GetClassNameOffs;
bool m_Loaded;
};
struct TEHookInfo
{
TempEntityInfo *te;
SourceHook::List<IPluginFunction *> lst;
};
class TempEntHooks : public IPluginsListener
{
public: //IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public:
void Initialize();
void Shutdown();
bool AddHook(const char *name, IPluginFunction *pFunc);
bool RemoveHook(const char *name, IPluginFunction *pFunc);
void OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID);
private:
void _IncRefCounter();
void _DecRefCounter();
size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter);
private:
IBasicTrie *m_TEHooks;
SourceHook::List<TEHookInfo *> m_HookInfo;
size_t m_HookCount;
};
extern TempEntityManager g_TEManager;
extern TempEntHooks s_TempEntHooks;
#endif //_INCLUDE_SOURCEMOD_TEMPENTS_H_
+542
View File
@@ -0,0 +1,542 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "tempents.h"
#include "CellRecipientFilter.h"
#include <IForwardSys.h>
SH_DECL_HOOK5_void(IVEngineServer, PlaybackTempEntity, SH_NOATTRIB, 0, IRecipientFilter &, float, const void *, const SendTable *, int);
CellRecipientFilter g_TERecFilter;
TempEntityInfo *g_CurrentTE = NULL;
int g_TEPlayers[256];
bool tenatives_initialized = false;
/*************************
* *
* Temp Entity Hook Class *
* *
**************************/
void TempEntHooks::Initialize()
{
m_TEHooks = adtfactory->CreateBasicTrie();
plsys->AddPluginsListener(this);
tenatives_initialized = true;
}
void TempEntHooks::Shutdown()
{
if (!tenatives_initialized)
{
return;
}
plsys->RemovePluginsListener(this);
SourceHook::List<TEHookInfo *>::iterator iter;
for (iter=m_HookInfo.begin(); iter!=m_HookInfo.end(); iter++)
{
delete (*iter);
}
if (m_HookCount)
{
m_HookCount = 1;
_DecRefCounter();
}
m_TEHooks->Destroy();
tenatives_initialized = false;
}
void TempEntHooks::OnPluginUnloaded(IPlugin *plugin)
{
SourceHook::List<TEHookInfo *>::iterator iter = m_HookInfo.begin();
IPluginContext *pContext = plugin->GetBaseContext();
/* For each hook list... */
while (iter != m_HookInfo.end())
{
SourceHook::List<IPluginFunction *>::iterator f_iter = (*iter)->lst.begin();
/* Find the hooks on the given temp entity */
while (f_iter != (*iter)->lst.end())
{
/* If it matches, remove it and dec the ref count */
if ((*f_iter)->GetParentContext() == pContext)
{
f_iter = (*iter)->lst.erase(f_iter);
_DecRefCounter();
}
else
{
f_iter++;
}
}
/* If there are no more hooks left, we can safely
* remove it from the cache and remove its list.
*/
if ((*iter)->lst.size() == 0)
{
m_TEHooks->Delete((*iter)->te->GetName());
delete (*iter);
iter = m_HookInfo.erase(iter);
}
else
{
iter++;
}
}
}
void TempEntHooks::_IncRefCounter()
{
if (m_HookCount++ == 0)
{
SH_ADD_HOOK_MEMFUNC(IVEngineServer, PlaybackTempEntity, engine, this, &TempEntHooks::OnPlaybackTempEntity, false);
}
}
void TempEntHooks::_DecRefCounter()
{
if (--m_HookCount == 0)
{
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, PlaybackTempEntity, engine, this, &TempEntHooks::OnPlaybackTempEntity, false);
}
}
size_t TempEntHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
{
size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
for (size_t i=0; i<size; i++)
{
pl_array[i] = pFilter->GetRecipientIndex(i);
}
return size;
}
bool TempEntHooks::AddHook(const char *name, IPluginFunction *pFunc)
{
TEHookInfo *pInfo;
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&pInfo)))
{
pInfo->lst.push_back(pFunc);
} else {
TempEntityInfo *te;
if (!(te=g_TEManager.GetTempEntityInfo(name)))
{
return false;
}
pInfo = new TEHookInfo;
pInfo->te = te;
pInfo->lst.push_back(pFunc);
m_TEHooks->Insert(name, reinterpret_cast<void *>(pInfo));
m_HookInfo.push_back(pInfo);
}
_IncRefCounter();
return true;
}
bool TempEntHooks::RemoveHook(const char *name, IPluginFunction *pFunc)
{
TEHookInfo *pInfo;
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&pInfo)))
{
SourceHook::List<IPluginFunction *>::iterator iter;
if ((iter=pInfo->lst.find(pFunc)) != pInfo->lst.end())
{
pInfo->lst.erase(iter);
if (pInfo->lst.empty())
{
m_HookInfo.remove(pInfo);
m_TEHooks->Delete(name);
delete pInfo;
}
_DecRefCounter();
} else {
return false;
}
} else {
return false;
}
return true;
}
void TempEntHooks::OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID)
{
TEHookInfo *pInfo;
const char *name = g_TEManager.GetNameFromThisPtr(const_cast<void *>(pSender));
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&pInfo)))
{
SourceHook::List<IPluginFunction *>::iterator iter;
IPluginFunction *pFunc;
size_t size;
cell_t res = static_cast<ResultType>(Pl_Continue);
TempEntityInfo *oldinfo = g_CurrentTE;
g_CurrentTE = pInfo->te;
size = _FillInPlayers(g_TEPlayers, &filter);
for (iter=pInfo->lst.begin(); iter!=pInfo->lst.end(); iter++)
{
pFunc = (*iter);
pFunc->PushString(name);
pFunc->PushArray(g_TEPlayers, size);
pFunc->PushCell(size);
pFunc->PushFloat(delay);
pFunc->Execute(&res);
if (res != Pl_Continue)
{
g_CurrentTE = oldinfo;
RETURN_META(MRES_SUPERCEDE);
}
}
g_CurrentTE = oldinfo;
RETURN_META(MRES_IGNORED);
}
}
/**********************
* *
* Temp Entity Natives *
* *
***********************/
TempEntHooks s_TempEntHooks;
static cell_t smn_TEStart(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
char *name;
pContext->LocalToString(params[1], &name);
g_CurrentTE = g_TEManager.GetTempEntityInfo(name);
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("Invalid TempEntity name: \"%s\"", name);
}
return 1;
}
static cell_t smn_TEWriteNum(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
pContext->LocalToString(params[1], &prop);
if (!g_CurrentTE->TE_SetEntData(prop, params[2]))
{
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
}
return 1;
}
static cell_t smn_TEReadNum(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
int val;
pContext->LocalToString(params[1], &prop);
if (!g_CurrentTE->TE_GetEntData(prop, &val))
{
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
}
return val;
}
static cell_t smn_TE_WriteFloat(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
pContext->LocalToString(params[1], &prop);
if (!g_CurrentTE->TE_SetEntDataFloat(prop, sp_ctof(params[2])))
{
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
}
return 1;
}
static cell_t smn_TE_ReadFloat(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
float val;
pContext->LocalToString(params[1], &prop);
if (!g_CurrentTE->TE_GetEntDataFloat(prop, &val))
{
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
}
return sp_ftoc(val);
}
static cell_t smn_TEWriteVector(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
pContext->LocalToString(params[1], &prop);
cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);
float vec[3] = {sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])};
if (!g_CurrentTE->TE_SetEntDataVector(prop, vec))
{
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
}
return 1;
}
static cell_t smn_TEReadVector(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
pContext->LocalToString(params[1], &prop);
cell_t *addr;
float vec[3];
pContext->LocalToPhysAddr(params[2], &addr);
if (!g_CurrentTE->TE_GetEntDataVector(prop, vec))
{
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
}
addr[0] = sp_ftoc(vec[0]);
addr[1] = sp_ftoc(vec[1]);
addr[2] = sp_ftoc(vec[2]);
return 1;
}
static cell_t smn_TEWriteFloatArray(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
pContext->LocalToString(params[1], &prop);
cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);
if (!g_CurrentTE->TE_SetEntDataFloatArray(prop, addr, params[3]))
{
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
}
return 1;
}
static cell_t smn_TESend(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
cell_t *cl_array;
pContext->LocalToPhysAddr(params[1], &cl_array);
g_TERecFilter.Reset();
g_TERecFilter.Initialize(cl_array, params[2]);
g_CurrentTE->Send(g_TERecFilter, sp_ctof(params[3]));
g_CurrentTE = NULL;
return 1;
}
static cell_t smn_TEIsValidProp(IPluginContext *pContext, const cell_t *params)
{
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
if (!g_CurrentTE)
{
return pContext->ThrowNativeError("No TempEntity call is in progress");
}
char *prop;
pContext->LocalToString(params[1], &prop);
return g_CurrentTE->IsValidProp(prop) ? 1 : 0;
}
static cell_t smn_AddTempEntHook(IPluginContext *pContext, const cell_t *params)
{
char *name;
IPluginFunction *pFunc;
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
pContext->LocalToString(params[1], &name);
pFunc = pContext->GetFunctionById(params[2]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
}
if (!s_TempEntHooks.AddHook(name, pFunc))
{
return pContext->ThrowNativeError("Invalid TempEntity name: \"%s\"", name);
}
return 1;
}
static cell_t smn_RemoveTempEntHook(IPluginContext *pContext, const cell_t *params)
{
char *name;
IPluginFunction *pFunc;
if (!g_TEManager.IsAvailable())
{
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
}
pContext->LocalToString(params[1], &name);
pFunc = pContext->GetFunctionById(params[2]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
}
if (!s_TempEntHooks.RemoveHook(name, pFunc))
{
return pContext->ThrowNativeError("Invalid hooked TempEntity name or function");
}
return 1;
}
sp_nativeinfo_t g_TENatives[] =
{
{"TE_Start", smn_TEStart},
{"TE_WriteNum", smn_TEWriteNum},
{"TE_ReadNum", smn_TEReadNum},
{"TE_WriteFloat", smn_TE_WriteFloat},
{"TE_ReadFloat", smn_TE_ReadFloat},
{"TE_WriteVector", smn_TEWriteVector},
{"TE_ReadVector", smn_TEReadVector},
{"TE_WriteAngles", smn_TEWriteVector},
{"TE_Send", smn_TESend},
{"TE_IsValidProp", smn_TEIsValidProp},
{"TE_WriteFloatArray", smn_TEWriteFloatArray},
{"AddTempEntHook", smn_AddTempEntHook},
{"RemoveTempEntHook", smn_RemoveTempEntHook},
{NULL, NULL}
};
+444
View File
@@ -0,0 +1,444 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
#include <worldsize.h>
class CSMTraceFilter : public CTraceFilter
{
public:
bool ShouldHitEntity(IHandleEntity *pEntity, int contentsMask)
{
cell_t res = 1;
edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(pEntity));
m_pFunc->PushCell(engine->IndexOfEdict(pEdict));
m_pFunc->PushCell(contentsMask);
m_pFunc->PushCell(m_Data);
m_pFunc->Execute(&res);
return (res) ? true : false;
}
void SetFunctionPtr(IPluginFunction *pFunc, cell_t data)
{
m_pFunc = pFunc;
m_Data = data;
}
private:
IPluginFunction *m_pFunc;
cell_t m_Data;
};
/* Used for the global trace version */
Ray_t g_Ray;
trace_t g_Trace;
Vector g_StartVec;
Vector g_EndVec;
QAngle g_DirAngles;
CTraceFilterHitAll g_HitAllFilter;
CSMTraceFilter g_SMTraceFilter;
enum
{
RayType_EndPoint,
RayType_Infinite
};
static cell_t smn_TRTraceRay(IPluginContext *pContext, const cell_t *params)
{
cell_t *startaddr, *endaddr;
pContext->LocalToPhysAddr(params[1], &startaddr);
pContext->LocalToPhysAddr(params[2], &endaddr);
g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
switch (params[4])
{
case RayType_EndPoint:
{
g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
break;
}
case RayType_Infinite:
{
g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
AngleVectors(g_DirAngles, &g_EndVec);
/* Make it unitary and get the ending point */
g_EndVec.NormalizeInPlace();
g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
break;
}
}
g_Ray.Init(g_StartVec, g_EndVec);
enginetrace->TraceRay(g_Ray, params[3], &g_HitAllFilter, &g_Trace);
return 1;
}
static cell_t smn_TRTraceRayFilter(IPluginContext *pContext, const cell_t *params)
{
cell_t *startaddr, *endaddr;
IPluginFunction *pFunc;
cell_t data;
pFunc = pContext->GetFunctionById(params[5]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
}
if (params[0] >= 6)
{
data = params[6];
}
else
{
data = 0;
}
g_SMTraceFilter.SetFunctionPtr(pFunc, data);
pContext->LocalToPhysAddr(params[1], &startaddr);
pContext->LocalToPhysAddr(params[2], &endaddr);
g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
switch (params[4])
{
case RayType_EndPoint:
{
g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
break;
}
case RayType_Infinite:
{
g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
AngleVectors(g_DirAngles, &g_EndVec);
/* Make it unitary and get the ending point */
g_EndVec.NormalizeInPlace();
g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
break;
}
}
g_Ray.Init(g_StartVec, g_EndVec);
enginetrace->TraceRay(g_Ray, params[3], &g_SMTraceFilter, &g_Trace);
return 1;
}
static cell_t smn_TRTraceRayEx(IPluginContext *pContext, const cell_t *params)
{
cell_t *startaddr, *endaddr;
pContext->LocalToPhysAddr(params[1], &startaddr);
pContext->LocalToPhysAddr(params[2], &endaddr);
Vector StartVec, EndVec;
Ray_t ray;
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
switch (params[4])
{
case RayType_EndPoint:
{
EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
break;
}
case RayType_Infinite:
{
QAngle DirAngles;
DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
AngleVectors(DirAngles, &EndVec);
/* Make it unitary and get the ending point */
EndVec.NormalizeInPlace();
EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
break;
}
}
trace_t *tr = new trace_t;
ray.Init(StartVec, EndVec);
enginetrace->TraceRay(ray, params[3], &g_HitAllFilter, tr);
HandleError herr;
Handle_t hndl;
if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
{
delete tr;
return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
}
return hndl;
}
static cell_t smn_TRTraceRayFilterEx(IPluginContext *pContext, const cell_t *params)
{
IPluginFunction *pFunc;
cell_t *startaddr, *endaddr;
cell_t data;
pFunc = pContext->GetFunctionById(params[5]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
}
pContext->LocalToPhysAddr(params[1], &startaddr);
pContext->LocalToPhysAddr(params[2], &endaddr);
Vector StartVec, EndVec;
CSMTraceFilter smfilter;
Ray_t ray;
if (params[0] >= 6)
{
data = params[6];
}
else
{
data = 0;
}
smfilter.SetFunctionPtr(pFunc, data);
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
switch (params[4])
{
case RayType_EndPoint:
{
EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
break;
}
case RayType_Infinite:
{
QAngle DirAngles;
DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
AngleVectors(DirAngles, &EndVec);
/* Make it unitary and get the ending point */
EndVec.NormalizeInPlace();
EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
break;
}
}
trace_t *tr = new trace_t;
ray.Init(StartVec, EndVec);
enginetrace->TraceRay(ray, params[3], &smfilter, tr);
HandleError herr;
Handle_t hndl;
if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
{
delete tr;
return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
}
return hndl;
}
static cell_t smn_TRGetFraction(IPluginContext *pContext, const cell_t *params)
{
trace_t *tr;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
if (params[1] == BAD_HANDLE)
{
tr = &g_Trace;
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}
return sp_ftoc(tr->fraction);
}
static cell_t smn_TRGetPlaneNormal(IPluginContext *pContext, const cell_t *params)
{
trace_t *tr;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
if (params[1] == BAD_HANDLE)
{
tr = &g_Trace;
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}
Vector *normal = &tr->plane.normal;
cell_t *r;
pContext->LocalToPhysAddr(params[2], &r);
r[0] = sp_ftoc(normal->x);
r[1] = sp_ftoc(normal->y);
r[2] = sp_ftoc(normal->z);
return 1;
}
static cell_t smn_TRGetEndPosition(IPluginContext *pContext, const cell_t *params)
{
trace_t *tr;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
if (params[2] == BAD_HANDLE)
{
tr = &g_Trace;
} else if ((err = handlesys->ReadHandle(params[2], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[2], err);
}
cell_t *addr;
pContext->LocalToPhysAddr(params[1], &addr);
addr[0] = sp_ftoc(tr->endpos.x);
addr[1] = sp_ftoc(tr->endpos.y);
addr[2] = sp_ftoc(tr->endpos.z);
return 1;
}
static cell_t smn_TRDidHit(IPluginContext *pContext, const cell_t *params)
{
trace_t *tr;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
if (params[1] == BAD_HANDLE)
{
tr = &g_Trace;
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}
return tr->DidHit() ? 1 : 0;
}
static cell_t smn_TRGetHitGroup(IPluginContext *pContext, const cell_t *params)
{
trace_t *tr;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
if (params[1] == BAD_HANDLE)
{
tr = &g_Trace;
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}
return tr->hitgroup;
}
static cell_t smn_TRGetEntityIndex(IPluginContext *pContext, const cell_t *params)
{
trace_t *tr;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
if (params[1] == BAD_HANDLE)
{
tr = &g_Trace;
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}
edict_t *pEdict = gameents->BaseEntityToEdict(tr->m_pEnt);
return engine->IndexOfEdict(pEdict);
}
static cell_t smn_TRGetPointContents(IPluginContext *pContext, const cell_t *params)
{
cell_t *vec, *ent;
IHandleEntity *hentity;
Vector pos;
int mask;
pContext->LocalToPhysAddr(params[1], &vec);
pContext->LocalToPhysAddr(params[2], &ent);
pos.x = sp_ctof(vec[0]);
pos.y = sp_ctof(vec[1]);
pos.z = sp_ctof(vec[2]);
if (*ent == -1)
{
mask = enginetrace->GetPointContents(pos);
} else {
mask = enginetrace->GetPointContents(pos, &hentity);
edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(hentity));
*ent = engine->IndexOfEdict(pEdict);
}
return mask;
}
static cell_t smn_TRGetPointContentsEnt(IPluginContext *pContext, const cell_t *params)
{
edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
if (!pEdict || pEdict->IsFree())
{
return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
}
cell_t *addr;
Vector pos;
pContext->LocalToPhysAddr(params[2], &addr);
pos.x = sp_ctof(addr[0]);
pos.y = sp_ctof(addr[1]);
pos.z = sp_ctof(addr[2]);
return enginetrace->GetPointContents_Collideable(pEdict->GetCollideable(), pos);
}
sp_nativeinfo_t g_TRNatives[] =
{
{"TR_TraceRay", smn_TRTraceRay},
{"TR_TraceRayEx", smn_TRTraceRayEx},
{"TR_GetFraction", smn_TRGetFraction},
{"TR_GetEndPosition", smn_TRGetEndPosition},
{"TR_GetEntityIndex", smn_TRGetEntityIndex},
{"TR_DidHit", smn_TRDidHit},
{"TR_GetHitGroup", smn_TRGetHitGroup},
{"TR_GetPointContents", smn_TRGetPointContents},
{"TR_GetPointContentsEnt", smn_TRGetPointContentsEnt},
{"TR_TraceRayFilter", smn_TRTraceRayFilter},
{"TR_TraceRayFilterEx", smn_TRTraceRayFilterEx},
{"TR_GetPlaneNormal", smn_TRGetPlaneNormal},
{NULL, NULL}
};
+72
View File
@@ -0,0 +1,72 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id: vcallbuilder.h 1566 2007-10-14 22:12:46Z faluco $
*/
#ifndef _INCLUDE_SOURCEMOD_UTIL_H_
#define _INCLUDE_SOURCEMOD_UTIL_H_
#include "utldict.h"
abstract_class IEntityFactory
{
public:
virtual IServerNetworkable *Create( const char *pClassName ) = 0;
virtual void Destroy( IServerNetworkable *pNetworkable ) = 0;
virtual size_t GetEntitySize() = 0;
};
abstract_class IEntityFactoryDictionary
{
public:
virtual void InstallFactory( IEntityFactory *pFactory, const char *pClassName ) = 0;
virtual IServerNetworkable *Create( const char *pClassName ) = 0;
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0;
virtual IEntityFactory *FindFactory( const char *pClassName ) = 0;
virtual const char *GetCannonicalName( const char *pClassName ) = 0;
};
class CEntityFactoryDictionary : public IEntityFactoryDictionary
{
public:
CEntityFactoryDictionary();
virtual void InstallFactory( IEntityFactory *pFactory, const char *pClassName );
virtual IServerNetworkable *Create( const char *pClassName );
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable );
virtual const char *GetCannonicalName( const char *pClassName );
void ReportEntitySizes();
private:
IEntityFactory *FindFactory( const char *pClassName );
public:
CUtlDict< IEntityFactory *, unsigned short > m_Factories;
};
#endif //_INCLUDE_SOURCEMOD_UTIL_H_
+369
View File
@@ -0,0 +1,369 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "vcallbuilder.h"
#include "extension.h"
ValveCall::ValveCall()
{
call = NULL;
vparams = NULL;
retinfo = NULL;
thisinfo = NULL;
retbuf = NULL;
}
ValveCall::~ValveCall()
{
while (!stk.empty())
{
unsigned char *ptr = stk.front();
delete [] ptr;
stk.pop();
}
if (call)
{
call->Destroy();
}
delete [] retbuf;
delete [] vparams;
}
unsigned char *ValveCall::stk_get()
{
unsigned char *ptr;
if (stk.empty())
{
ptr = new unsigned char[stackSize];
} else {
ptr = stk.front();
stk.pop();
}
return ptr;
}
void ValveCall::stk_put(unsigned char *ptr)
{
stk.push(ptr);
}
ValveCall *CreateValveCall(void *addr,
ValveCallType vcalltype,
const ValvePassInfo *retInfo,
const ValvePassInfo *params,
unsigned int numParams)
{
if (numParams > 32)
{
return NULL;
}
ValveCall *vc = new ValveCall;
vc->type = vcalltype;
size_t size = 0;
vc->stackSize = 0;
/* Get return information - encode only */
PassInfo retBuf;
size_t retBufSize = 0;
bool retbuf_needs_extra;
if (retInfo)
{
if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
{
delete vc;
return NULL;
}
retBufSize = retBuf.size;
}
/* Get parameter info */
PassInfo paramBuf[32];
size_t sizes[32];
size_t normSize = 0;
size_t extraSize = 0;
for (unsigned int i=0; i<numParams; i++)
{
bool needs_extra;
if ((size = ValveParamToBinParam(params[i].vtype,
params[i].type,
params[i].flags,
&paramBuf[i],
needs_extra)) == 0)
{
delete vc;
return NULL;
}
if (needs_extra)
{
sizes[i] = size;
} else {
sizes[i] = 0;
}
normSize += paramBuf[i].size;
extraSize += sizes[i];
}
/* Get thisinfo if needed */
ValvePassInfo thisbuf;
ValvePassInfo *thisinfo = NULL;
CallConvention cv = CallConv_Cdecl;
if (vcalltype != ValveCall_Static)
{
thisinfo = &thisbuf;
thisinfo->type = PassType_Basic;
switch (vcalltype)
{
case ValveCall_Entity:
thisinfo->vtype = Valve_CBaseEntity;
thisinfo->flags = PASSFLAG_BYVAL;
thisinfo->decflags |= VDECODE_FLAG_ALLOWWORLD;
break;
case ValveCall_Player:
thisinfo->vtype = Valve_CBasePlayer;
thisinfo->flags = PASSFLAG_BYVAL;
thisinfo->decflags = 0;
break;
default:
thisinfo->vtype = Valve_POD;
thisinfo->flags = PASSFLAG_ASPOINTER;
thisinfo->decflags = 0;
break;
}
thisinfo->encflags = 0;
thisinfo->offset = 0;
normSize += sizeof(void *);
cv = CallConv_ThisCall;
}
/* Now we can try creating the call */
if ((vc->call = g_pBinTools->CreateCall(addr,
cv,
(retInfo ? &retBuf : NULL),
paramBuf,
numParams))
== NULL)
{
if (!vc->call)
{
delete vc;
return NULL;
}
}
/* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
vc->vparams = new ValvePassInfo[numParams + 2];
/* We've got the call and everything is encoded.
* It's time to save the valve specific information and helper variables.
*/
if (retInfo)
{
/* Allocate and copy */
vc->retinfo = &(vc->vparams[numParams]);
*vc->retinfo = *retInfo;
vc->retinfo->offset = 0;
vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
/* Allocate stack space */
vc->retbuf = new unsigned char[retBufSize];
} else {
vc->retinfo = NULL;
vc->retbuf = NULL;
}
if (thisinfo)
{
/* Allocate and copy */
vc->thisinfo = &(vc->vparams[numParams + 1]);
*vc->thisinfo = *thisinfo;
vc->thisinfo->offset = 0;
vc->thisinfo->obj_offset = 0;
} else {
vc->thisinfo = NULL;
}
/* Now, save info about each parameter. */
size_t last_extra_offset = 0;
for (unsigned int i=0; i<numParams; i++)
{
/* Copy */
vc->vparams[i] = params[i];
vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
vc->vparams[i].obj_offset = last_extra_offset;
last_extra_offset += sizes[i];
}
vc->stackSize = normSize + extraSize;
vc->stackEnd = normSize;
return vc;
}
ValveCall *CreateValveVCall(unsigned int vtableIdx,
ValveCallType vcalltype,
const ValvePassInfo *retInfo,
const ValvePassInfo *params,
unsigned int numParams)
{
if (numParams > 32)
{
return NULL;
}
ValveCall *vc = new ValveCall;
vc->type = vcalltype;
size_t size = 0;
vc->stackSize = 0;
/* Get return information - encode only */
PassInfo retBuf;
size_t retBufSize = 0;
bool retbuf_needs_extra;
if (retInfo)
{
if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
{
delete vc;
return NULL;
}
retBufSize = retBuf.size;
}
/* Get parameter info */
PassInfo paramBuf[32];
size_t sizes[32];
size_t normSize = 0;
size_t extraSize = 0;
for (unsigned int i=0; i<numParams; i++)
{
bool needs_extra;
if ((size = ValveParamToBinParam(params[i].vtype,
params[i].type,
params[i].flags,
&paramBuf[i],
needs_extra)) == 0)
{
delete vc;
return NULL;
}
if (needs_extra)
{
sizes[i] = size;
} else {
sizes[i] = 0;
}
normSize += paramBuf[i].size;
extraSize += sizes[i];
}
/* Now we can try creating the call */
if ((vc->call = g_pBinTools->CreateVCall(vtableIdx,
0,
0,
(retInfo ? &retBuf : NULL),
paramBuf,
numParams))
== NULL)
{
if (!vc->call)
{
delete vc;
return NULL;
}
}
/* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
vc->vparams = new ValvePassInfo[numParams + 2];
/* We've got the call and everything is encoded.
* It's time to save the valve specific information and helper variables.
*/
if (retInfo)
{
/* Allocate and copy */
vc->retinfo = &(vc->vparams[numParams]);
*vc->retinfo = *retInfo;
vc->retinfo->offset = 0;
vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
/* Allocate stack space */
vc->retbuf = new unsigned char[retBufSize];
} else {
vc->retinfo = NULL;
vc->retbuf = NULL;
}
/* Save the this info for the dynamic decoder */
vc->thisinfo = &(vc->vparams[numParams + 1]);
vc->thisinfo->type = PassType_Basic;
switch (vcalltype)
{
case ValveCall_Entity:
vc->thisinfo->vtype = Valve_CBaseEntity;
vc->thisinfo->flags = PASSFLAG_BYVAL;
vc->thisinfo->decflags = VDECODE_FLAG_ALLOWWORLD;
break;
case ValveCall_Player:
vc->thisinfo->vtype = Valve_CBasePlayer;
vc->thisinfo->flags = PASSFLAG_BYVAL;
vc->thisinfo->decflags = 0;
break;
default:
vc->thisinfo->vtype = Valve_POD;
vc->thisinfo->flags = PASSFLAG_ASPOINTER;
vc->thisinfo->decflags = 0;
break;
}
vc->thisinfo->encflags = 0;
vc->thisinfo->offset = 0;
vc->thisinfo->obj_offset = 0;
normSize += sizeof(void *);
/* Now, save info about each parameter. */
size_t last_extra_offset = 0;
for (unsigned int i=0; i<numParams; i++)
{
/* Copy */
vc->vparams[i] = params[i];
vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
vc->vparams[i].obj_offset = last_extra_offset;
last_extra_offset += sizes[i];
}
vc->stackSize = normSize + extraSize;
vc->stackEnd = normSize;
return vc;
}
+74
View File
@@ -0,0 +1,74 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_VALVE_CALLER_H_
#define _INCLUDE_SOURCEMOD_VALVE_CALLER_H_
#include <sh_stack.h>
#include <extensions/IBinTools.h>
#include "vdecoder.h"
using namespace SourceMod;
/**
* @brief Info necessary to call a Valve function
*/
struct ValveCall
{
ICallWrapper *call; /**< From IBinTools */
ValveCallType type; /**< Call type */
ValvePassInfo *vparams; /**< Valve parameter info */
ValvePassInfo *retinfo; /**< Return buffer info */
ValvePassInfo *thisinfo; /**< Thiscall info */
size_t stackSize; /**< Stack size */
size_t stackEnd; /**< End of the bintools stack */
unsigned char *retbuf; /**< Return buffer */
SourceHook::CStack<unsigned char *> stk; /**< Parameter stack */
unsigned char *stk_get();
void stk_put(unsigned char *ptr);
ValveCall();
~ValveCall();
};
ValveCall *CreateValveVCall(unsigned int vtableIdx,
ValveCallType vcalltype,
const ValvePassInfo *retInfo,
const ValvePassInfo *params,
unsigned int numParams);
ValveCall *CreateValveCall(void *addr,
ValveCallType vcalltype,
const ValvePassInfo *retInfo,
const ValvePassInfo *params,
unsigned int numParams);
#endif //_INCLUDE_SOURCEMOD_VALVE_CALLER_H_
+455
View File
@@ -0,0 +1,455 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
#include "vcallbuilder.h"
#include "vglobals.h"
enum SDKLibrary
{
SDKLibrary_Server, /**< server.dll/server_i486.so */
SDKLibrary_Engine, /**< engine.dll/engine_*.so */
};
enum SDKPassMethod
{
SDKPass_Pointer, /**< Pass as a pointer */
SDKPass_Plain, /**< Pass as plain data */
SDKPass_ByValue, /**< Pass an object by value */
SDKPass_ByRef, /**< Pass an object by reference */
};
int s_vtbl_index = -1;
void *s_call_addr = NULL;
ValveCallType s_vcalltype = ValveCall_Static;
bool s_has_return = false;
ValvePassInfo s_return;
unsigned int s_numparams = 0;
ValvePassInfo s_params[SP_MAX_EXEC_PARAMS];
inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &type, unsigned int &flags)
{
if (method == SDKPass_Pointer || method == SDKPass_ByRef)
{
type = PassType_Basic;
if (vtype == Valve_POD
|| vtype == Valve_Float
|| vtype == Valve_Bool)
{
flags = PASSFLAG_BYVAL | PASSFLAG_ASPOINTER;
} else {
flags = PASSFLAG_BYVAL;
}
} else if (method == SDKPass_Plain) {
type = PassType_Basic;
flags = PASSFLAG_BYVAL;
} else if (method == SDKPass_ByValue) {
if (vtype == Valve_Vector
|| vtype == Valve_QAngle)
{
type = PassType_Object;
} else {
type = PassType_Basic;
}
flags = PASSFLAG_BYVAL;
}
}
static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params)
{
s_numparams = 0;
s_vtbl_index = -1;
s_call_addr = NULL;
s_has_return = false;
s_vcalltype = (ValveCallType)params[1];
return 1;
}
static cell_t PrepSDKCall_SetVirtual(IPluginContext *pContext, const cell_t *params)
{
s_vtbl_index = params[1];
return 1;
}
static cell_t PrepSDKCall_SetSignature(IPluginContext *pContext, const cell_t *params)
{
void *addrInBase = NULL;
if (params[1] == SDKLibrary_Server)
{
addrInBase = (void *)g_SMAPI->GetServerFactory(false);
} else if (params[1] == SDKLibrary_Engine) {
addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
}
if (addrInBase == NULL)
{
return 0;
}
char *sig;
pContext->LocalToString(params[2], &sig);
#if defined PLATFORM_LINUX
if (sig[0] == '@')
{
Dl_info info;
if (dladdr(addrInBase, &info) == 0)
{
return 0;
}
void *handle = dlopen(info.dli_fname, RTLD_NOW);
if (!handle)
{
return 0;
}
s_call_addr = dlsym(handle, &sig[1]);
dlclose(handle);
return (s_call_addr != NULL) ? 1 : 0;
}
#endif
s_call_addr = memutils->FindPattern(addrInBase, sig, params[3]);
return (s_call_addr != NULL) ? 1 : 0;
}
static cell_t PrepSDKCall_SetFromConf(IPluginContext *pContext, const cell_t *params)
{
IGameConfig *conf;
if (params[1] == BAD_HANDLE)
{
conf = g_pGameConf;
} else {
HandleError err;
if ((conf = gameconfs->ReadHandle(params[1], pContext->GetIdentity(), &err)) == NULL)
{
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}
}
char *key;
pContext->LocalToString(params[3], &key);
if (params[2] == 0)
{
return conf->GetOffset(key, &s_vtbl_index) ? 1 : 0;
} else if (params[2] == 1) {
bool result = conf->GetMemSig(key, &s_call_addr) ? 1 : 0;
return (result && s_call_addr != NULL) ? 1 : 0;
}
return 0;
}
static cell_t PrepSDKCall_SetReturnInfo(IPluginContext *pContext, const cell_t *params)
{
s_has_return = true;
s_return.vtype = (ValveType)params[1];
DecodePassMethod(s_return.vtype, (SDKPassMethod)params[2], s_return.type, s_return.flags);
s_return.decflags = params[3];
s_return.encflags = params[4];
return 1;
}
static cell_t PrepSDKCall_AddParameter(IPluginContext *pContext, const cell_t *params)
{
if (s_numparams >= SP_MAX_EXEC_PARAMS)
{
return pContext->ThrowNativeError("Parameter limit for SDK calls reached");
}
ValvePassInfo *info = &s_params[s_numparams++];
info->vtype = (ValveType)params[1];
SDKPassMethod method = (SDKPassMethod)params[2];
DecodePassMethod(info->vtype, method, info->type, info->flags);
info->decflags = params[3] | VDECODE_FLAG_BYREF;
info->encflags = params[4];
/* Since SDKPass_ByRef acts like SDKPass_Pointer we can't allow NULL, just in case */
if (method == SDKPass_ByRef)
{
info->decflags &= ~VDECODE_FLAG_ALLOWNULL;
}
return 1;
}
static cell_t EndPrepSDKCall(IPluginContext *pContext, const cell_t *params)
{
ValveCall *vc = NULL;
if (s_vtbl_index > -1)
{
vc = CreateValveVCall(s_vtbl_index, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
} else if (s_call_addr) {
vc = CreateValveCall(s_call_addr, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
}
if (!vc)
{
return BAD_HANDLE;
}
if (vc->thisinfo)
{
vc->thisinfo->decflags |= VDECODE_FLAG_BYREF;
}
Handle_t hndl = handlesys->CreateHandle(g_CallHandle, vc, pContext->GetIdentity(), myself->GetIdentity(), NULL);
if (!hndl)
{
delete vc;
}
return hndl;
}
static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
{
ValveCall *vc;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
if ((err = handlesys->ReadHandle(params[1], g_CallHandle, &sec, (void **)&vc)) != HandleError_None)
{
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}
unsigned char *ptr = vc->stk_get();
unsigned int numparams = (unsigned)params[0];
unsigned int startparam = 2;
/* Do we need to write a thispointer? */
if (vc->thisinfo)
{
switch (vc->type)
{
case ValveCall_Entity:
case ValveCall_Player:
{
if (startparam > numparams)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("Expected 1 parameter for entity pointer; found none");
}
if (DecodeValveParam(pContext,
params[startparam],
vc,
vc->thisinfo,
ptr) == Data_Fail)
{
vc->stk_put(ptr);
return 0;
}
startparam++;
}
break;
case ValveCall_GameRules:
{
if (g_pGameRules == NULL)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("GameRules unsupported or not available; file a bug report");
}
void *gamerules = *g_pGameRules;
if (gamerules == NULL)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("GameRules not available before map is loaded");
}
*(void **)ptr = gamerules;
}
break;
case ValveCall_EntityList:
{
if (g_EntList == NULL)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("EntityList unsupported or not available; file a bug report");
}
*(void **)ptr = g_EntList;
}
break;
}
}
/* See if we need to skip any more parameters */
unsigned int retparam = startparam;
if (vc->retinfo)
{
if (vc->retinfo->vtype == Valve_String)
{
startparam += 2;
} else if (vc->retinfo->vtype == Valve_Vector
|| vc->retinfo->vtype == Valve_QAngle)
{
startparam += 1;
}
}
unsigned int callparams = vc->call->GetParamCount();
bool will_copyback = false;
for (unsigned int i=0; i<callparams; i++)
{
unsigned int p = startparam + i;
if (p > numparams)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("Expected %dth parameter, found none", p);
}
if (DecodeValveParam(pContext,
params[p],
vc,
&(vc->vparams[i]),
ptr) == Data_Fail)
{
vc->stk_put(ptr);
return 0;
}
if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
{
will_copyback = true;
}
}
/* Make the actual call */
vc->call->Execute(ptr, vc->retbuf);
/* Do we need to copy anything back? */
if (will_copyback)
{
for (unsigned int i=0; i<callparams; i++)
{
if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
{
if (EncodeValveParam(pContext,
params[startparam + i],
vc,
&vc->vparams[i],
ptr) == Data_Fail)
{
vc->stk_put(ptr);
return 0;
}
}
}
}
/* Save stack once and for all */
vc->stk_put(ptr);
/* Figure out how to decode the return information */
if (vc->retinfo)
{
if (vc->retinfo->vtype == Valve_String)
{
if (numparams < 3)
{
return pContext->ThrowNativeError("Expected arguments (2,3) for string storage");
}
cell_t *addr;
size_t written;
pContext->LocalToPhysAddr(params[retparam+1], &addr);
pContext->StringToLocalUTF8(params[retparam], *addr, *(char **)vc->retbuf, &written);
return (cell_t)written;
} else if (vc->retinfo->vtype == Valve_Vector
|| vc->retinfo->vtype == Valve_QAngle)
{
if (numparams < 2)
{
return pContext->ThrowNativeError("Expected argument (2) for Float[3] storage");
}
if (EncodeValveParam(pContext, params[retparam], vc, vc->retinfo, vc->retbuf)
== Data_Fail)
{
return 0;
}
} else if (vc->retinfo->vtype == Valve_CBaseEntity
|| vc->retinfo->vtype == Valve_CBasePlayer)
{
CBaseEntity *pEntity = *(CBaseEntity **)(vc->retbuf);
if (!pEntity)
{
return -1;
}
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
if (!pEdict || pEdict->IsFree())
{
return -1;
}
return engine->IndexOfEdict(pEdict);
} else if (vc->retinfo->vtype == Valve_Edict) {
edict_t *pEdict = *(edict_t **)(vc->retbuf);
if (!pEdict || pEdict->IsFree())
{
return -1;
}
return engine->IndexOfEdict(pEdict);
} else if (vc->retinfo->vtype == Valve_Bool) {
bool *addr = (bool *)vc->retbuf;
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
{
addr = *(bool **)addr;
}
return *addr ? 1 : 0;
} else {
cell_t *addr = (cell_t *)vc->retbuf;
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
{
addr = *(cell_t **)addr;
}
return *addr;
}
}
return 0;
}
sp_nativeinfo_t g_CallNatives[] =
{
{"StartPrepSDKCall", StartPrepSDKCall},
{"PrepSDKCall_SetVirtual", PrepSDKCall_SetVirtual},
{"PrepSDKCall_SetSignature", PrepSDKCall_SetSignature},
{"PrepSDKCall_SetFromConf", PrepSDKCall_SetFromConf},
{"PrepSDKCall_SetReturnInfo", PrepSDKCall_SetReturnInfo},
{"PrepSDKCall_AddParameter", PrepSDKCall_AddParameter},
{"EndPrepSDKCall", EndPrepSDKCall},
{"SDKCall", SDKCall},
{NULL, NULL},
};
+612
View File
@@ -0,0 +1,612 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "smsdk_ext.h"
#include "extension.h"
#include "vdecoder.h"
#include "vcallbuilder.h"
using namespace SourceMod;
using namespace SourcePawn;
/**
* For object pointers, the data looks like this instead:
* 4 bytes: POINTER TO LATER
* + bytes: Object internal data
*
* We use the virtual stack as extra fake stack space and create a temp object.
* If these objects had destructors, we'd need to fake destroy toom of course.
* Of course, BinTools only reads the first four bytes and passes the pointer.
*/
size_t ValveParamToBinParam(ValveType type,
PassType pass,
unsigned int flags,
PassInfo *info,
bool &needs_extra)
{
needs_extra = false;
switch (type)
{
case Valve_Vector:
{
size_t mySize = sizeof(Vector *);
if (pass == PassType_Basic)
{
if (flags & PASSFLAG_BYREF)
{
return 0;
}
info->type = PassType_Basic;
info->flags = flags;
info->size = sizeof(Vector *);
mySize = sizeof(Vector);
needs_extra = true;
} else if (pass == PassType_Object) {
info->type = PassType_Object;
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
info->size = sizeof(Vector);
} else {
return 0;
}
return mySize;
}
case Valve_QAngle:
{
size_t mySize = sizeof(QAngle *);
if (pass == PassType_Basic)
{
if (flags & PASSFLAG_BYREF)
{
return 0;
}
info->type = PassType_Basic;
info->flags = flags;
info->size = sizeof(QAngle *);
mySize = sizeof(QAngle);
needs_extra = true;
} else if (pass == PassType_Object) {
info->type = PassType_Object;
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
info->size = sizeof(QAngle);
} else {
return 0;
}
return mySize;
}
case Valve_CBaseEntity:
case Valve_CBasePlayer:
case Valve_Edict:
case Valve_String:
{
if (pass != PassType_Basic || (flags & PASSFLAG_BYREF))
{
return 0;
}
info->type = PassType_Basic;
info->flags = flags;
info->size = sizeof(void *);
return sizeof(void *);
}
case Valve_POD:
{
info->type = PassType_Basic;
info->flags = flags;
if (flags & PASSFLAG_ASPOINTER)
{
needs_extra = true;
info->size = sizeof(int *);
return sizeof(int *) + sizeof(int);
} else {
info->size = sizeof(int);
return sizeof(int);
}
}
case Valve_Bool:
{
info->type = PassType_Basic;
info->flags = flags;
if (flags & PASSFLAG_ASPOINTER)
{
needs_extra = true;
info->size = sizeof(bool *);
return sizeof(bool *) + sizeof(bool);
} else {
info->size = sizeof(bool);
return sizeof(bool);
}
}
case Valve_Float:
{
info->flags = flags;
if (flags & PASSFLAG_ASPOINTER)
{
needs_extra = true;
info->type = PassType_Basic;
info->size = sizeof(float *);
return sizeof(float *) + sizeof(float);
} else {
info->type = PassType_Float;
info->size = sizeof(float);
return sizeof(float);
}
}
}
return 0;
}
DataStatus EncodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *data,
const void *_buffer)
{
const void *buffer = (const unsigned char *)_buffer + data->offset;
switch (data->vtype)
{
case Valve_Vector:
{
Vector *v = NULL;
if (data->type == PassType_Basic)
{
v = *(Vector **)buffer;
} else if (data->type == PassType_Object) {
v = (Vector *)buffer;
}
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
addr[0] = sp_ftoc(v->x);
addr[1] = sp_ftoc(v->y);
addr[2] = sp_ftoc(v->z);
return Data_Okay;
}
case Valve_QAngle:
{
QAngle *q = NULL;
if (data->type == PassType_Basic)
{
q = *(QAngle **)buffer;
} else if (data->type == PassType_Object) {
q = (QAngle *)buffer;
}
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
addr[0] = sp_ftoc(q->x);
addr[1] = sp_ftoc(q->y);
addr[2] = sp_ftoc(q->z);
return Data_Okay;
}
case Valve_CBaseEntity:
case Valve_CBasePlayer:
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
CBaseEntity *pEntity = *(CBaseEntity **)buffer;
if (pEntity)
{
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
*addr = engine->IndexOfEdict(pEdict);
} else {
*addr = -1;
}
return Data_Okay;
}
case Valve_Edict:
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
edict_t *pEdict = *(edict_t **)buffer;
if (pEdict)
{
*addr = engine->IndexOfEdict(pEdict);
} else {
*addr = -1;
}
return Data_Okay;
}
case Valve_POD:
case Valve_Float:
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
if (data->flags & PASSFLAG_ASPOINTER)
{
buffer = *(cell_t **)buffer;
}
*addr = *(cell_t *)buffer;
return Data_Okay;
}
case Valve_Bool:
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
if (data->flags & PASSFLAG_ASPOINTER)
{
buffer = *(bool **)buffer;
}
*addr = *(bool *)buffer ? 1 : 0;
return Data_Okay;
}
}
return Data_Fail;
}
DataStatus DecodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *data,
void *_buffer)
{
void *buffer = (unsigned char *)_buffer + data->offset;
switch (data->vtype)
{
case Valve_Vector:
{
cell_t *addr;
int err;
err = pContext->LocalToPhysAddr(param, &addr);
unsigned char *mem = (unsigned char *)buffer;
if (data->type == PassType_Basic)
{
/* Store the object in the next N bytes, and store
* a pointer to that object right beforehand.
*/
Vector **realPtr = (Vector **)buffer;
if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
{
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
{
*realPtr = NULL;
return Data_Okay;
} else {
pContext->ThrowNativeError("NULL not allowed");
return Data_Fail;
}
} else {
mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
*realPtr = (Vector *)mem;
}
}
if (err != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, "Could not read plugin data");
return Data_Fail;
}
/* Use placement new to initialize the object cleanly
* This has no destructor so we don't need to do
* DestroyValveParam() or something :]
*/
Vector *v = new (mem) Vector(
sp_ctof(addr[0]),
sp_ctof(addr[1]),
sp_ctof(addr[2]));
return Data_Okay;
}
case Valve_QAngle:
{
cell_t *addr;
int err;
err = pContext->LocalToPhysAddr(param, &addr);
unsigned char *mem = (unsigned char *)buffer;
if (data->type == PassType_Basic)
{
/* Store the object in the next N bytes, and store
* a pointer to that object right beforehand.
*/
QAngle **realPtr = (QAngle **)buffer;
if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
{
if (!(data->decflags & VDECODE_FLAG_ALLOWNULL))
{
pContext->ThrowNativeError("NULL not allowed");
return Data_Fail;
} else {
*realPtr = NULL;
return Data_Okay;
}
} else {
mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
*realPtr = (QAngle *)mem;
}
}
if (err != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, "Could not read plugin data");
return Data_Fail;
}
/* Use placement new to initialize the object cleanly
* This has no destructor so we don't need to do
* DestroyValveParam() or something :]
*/
QAngle *v = new (mem) QAngle(
sp_ctof(addr[0]),
sp_ctof(addr[1]),
sp_ctof(addr[2]));
return Data_Okay;
}
case Valve_CBasePlayer:
{
edict_t *pEdict;
if (data->decflags & VDECODE_FLAG_BYREF)
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
param = *addr;
}
if (param >= 1 && param <= playerhelpers->GetMaxClients())
{
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected())
{
pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail;
} else if (!player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail;
}
pEdict = player->GetEdict();
} else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
{
pEdict = NULL;
} else {
pContext->ThrowNativeError("NULL not allowed");
return Data_Fail;
}
} else if (param == 0) {
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
{
pEdict = engine->PEntityOfEntIndex(0);
} else {
pContext->ThrowNativeError("World not allowed");
return Data_Fail;
}
} else {
pContext->ThrowNativeError("Entity index %d is not a valid client", param);
return Data_Fail;
}
CBaseEntity *pEntity = NULL;
if (pEdict)
{
IServerUnknown *pUnknown = pEdict->GetUnknown();
if (!pUnknown)
{
pContext->ThrowNativeError("Entity %d is a not an IServerUnknown", param);
return Data_Fail;
}
pEntity = pUnknown->GetBaseEntity();
if (!pEntity)
{
pContext->ThrowNativeError("Entity %d is not a CBaseEntity", param);
return Data_Fail;
}
}
CBaseEntity **ebuf = (CBaseEntity **)buffer;
*ebuf = pEntity;
return Data_Okay;
}
case Valve_CBaseEntity:
{
edict_t *pEdict;
if (data->decflags & VDECODE_FLAG_BYREF)
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
param = *addr;
}
if (param >= 1 && param <= playerhelpers->GetMaxClients())
{
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected())
{
pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail;
} else if (!player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail;
}
pEdict = player->GetEdict();
} else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
{
pEdict = NULL;
} else {
pContext->ThrowNativeError("NULL not allowed");
return Data_Fail;
}
} else if (param == 0) {
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
{
pEdict = engine->PEntityOfEntIndex(0);
} else {
pContext->ThrowNativeError("World not allowed");
return Data_Fail;
}
} else {
pEdict = engine->PEntityOfEntIndex(param);
if (!pEdict || pEdict->IsFree())
{
pContext->ThrowNativeError("Entity %d is not valid or is freed", param);
return Data_Fail;
}
}
CBaseEntity *pEntity = NULL;
if (pEdict)
{
IServerUnknown *pUnknown = pEdict->GetUnknown();
if (!pUnknown)
{
pContext->ThrowNativeError("Entity %d is a not an IServerUnknown", param);
return Data_Fail;
}
pEntity = pUnknown->GetBaseEntity();
if (!pEntity)
{
pContext->ThrowNativeError("Entity %d is not a CBaseEntity", param);
return Data_Fail;
}
}
CBaseEntity **ebuf = (CBaseEntity **)buffer;
*ebuf = pEntity;
return Data_Okay;
}
case Valve_Edict:
{
edict_t *pEdict;
if (data->decflags & VDECODE_FLAG_BYREF)
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
param = *addr;
}
if (param >= 1 && param <= playerhelpers->GetMaxClients())
{
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected())
{
pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail;
} else if (!player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail;
}
pEdict = player->GetEdict();
} else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
{
pEdict = NULL;
} else {
pContext->ThrowNativeError("NULL not allowed");
return Data_Fail;
}
} else if (param == 0) {
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
{
pEdict = engine->PEntityOfEntIndex(0);
} else {
pContext->ThrowNativeError("World not allowed");
return Data_Fail;
}
} else {
pEdict = engine->PEntityOfEntIndex(param);
if (!pEdict || pEdict->IsFree())
{
pContext->ThrowNativeError("Entity %d is not valid or is freed", param);
return Data_Fail;
}
}
edict_t **ebuf = (edict_t **)buffer;
*ebuf = pEdict;
return Data_Okay;
}
case Valve_POD:
case Valve_Float:
{
if (data->decflags & VDECODE_FLAG_BYREF)
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
param = *addr;
}
if (data->flags & PASSFLAG_ASPOINTER)
{
*(void **)buffer = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
buffer = *(void **)buffer;
}
*(cell_t *)buffer = param;
return Data_Okay;
}
case Valve_Bool:
{
if (data->decflags & VDECODE_FLAG_BYREF)
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
param = *addr;
}
if (data->flags & PASSFLAG_ASPOINTER)
{
*(bool **)buffer = (bool *)((unsigned char *)_buffer + pCall->stackEnd + data->obj_offset);
buffer = *(bool **)buffer;
}
*(bool *)buffer = param ? true : false;
return Data_Okay;
}
case Valve_String:
{
char *addr;
pContext->LocalToString(param, &addr);
*(char **)buffer = addr;
return Data_Okay;
}
}
return Data_Fail;
}
+151
View File
@@ -0,0 +1,151 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_VDECODER_H_
#define _INCLUDE_SOURCEMOD_VDECODER_H_
#include <sm_platform.h>
#include <sp_vm_api.h>
#include <extensions/IBinTools.h>
using namespace SourceMod;
using namespace SourcePawn;
/**
* @brief Encapsulates types from the SDK
*/
enum ValveType
{
Valve_CBaseEntity, /**< CBaseEntity */
Valve_CBasePlayer, /**< CBasePlayer (disallow normal ents) */
Valve_Vector, /**< Vector */
Valve_QAngle, /**< QAngle */
Valve_POD, /**< Plain old data */
Valve_Float, /**< Float */
Valve_Edict, /**< Edict */
Valve_String, /**< String */
Valve_Bool, /**< Boolean */
};
enum DataStatus
{
Data_Fail = 0,
Data_Okay = 1,
};
#define VDECODE_FLAG_ALLOWNULL (1<<0) /**< Allow NULL for pointers */
#define VDECODE_FLAG_ALLOWNOTINGAME (1<<1) /**< Allow players not in game */
#define VDECODE_FLAG_ALLOWWORLD (1<<2) /**< Allow World entity */
#define VDECODE_FLAG_BYREF (1<<3) /**< Floats/ints by reference */
#define VENCODE_FLAG_COPYBACK (1<<0) /**< Copy back data */
#define PASSFLAG_ASPOINTER (1<<30) /**< Not an actual passflag, used internally */
/**
* @brief Valve pre-defined calling types
*/
enum ValveCallType
{
ValveCall_Static, /**< Static call */
ValveCall_Entity, /**< Thiscall (CBaseEntity implicit first parameter) */
ValveCall_Player, /**< Thiscall (CBasePlayer implicit first parameter) */
ValveCall_GameRules, /**< Thiscall (CGameRules implicit first paramater) */
ValveCall_EntityList, /**< Thiscall (CGlobalEntityList implicit first paramater) */
};
/**
* @brief Valve parameter info
*/
struct ValvePassInfo
{
ValveType vtype; /**< IN: Valve type */
unsigned int decflags; /**< IN: VDECODE_FLAG_* */
unsigned int encflags; /**< IN: VENCODE_FLAG_* */
PassType type; /**< IN: Pass information */
unsigned int flags; /**< IN: Pass flags */
size_t offset; /**< OUT: stack offset */
size_t obj_offset; /**< OUT: object offset at end of the stack */
};
struct ValveCall;
/**
* @brief Converts a valve parameter to a bintools parameter.
*
* @param type Valve type.
* @param pass Either basic or object.
* @param flags Either BYVAL or BYREF.
* @param info Buffer to store param info in.
* @return Number of bytes this will use in the virtual stack,
* or 0 if conversion was impossible.
*/
size_t ValveParamToBinParam(ValveType type,
PassType pass,
unsigned int flags,
PassInfo *info,
bool &needs_extra);
/**
* @brief Decodes data from a plugin to native data.
*
* Note: If you're going to return false, make sure to
* throw an error.
*
* @param pContext Plugin context.
* @param param Parameter value from params array.
* @param buffer Buffer space in the virutal stack.
* @return True on success, false otherwise.
*/
DataStatus DecodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *vdata,
void *buffer);
/**
* @brief Encodes native data back into a plugin.
*
* Note: If you're going to return false, make sure to
* throw an error.
*
* @param pContext Plugin context.
* @param param Parameter value from params array.
* @param buffer Buffer space in the virutal stack.
* @return True on success, false otherwise.
*/
DataStatus EncodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *vdata,
const void *buffer);
#endif //_INCLUDE_SOURCEMOD_VDECODER_H_
+104
View File
@@ -0,0 +1,104 @@
// Microsoft Visual C++ generated resource script.
//
//#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
#include "svn_version.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION SVN_FILE_VERSION
PRODUCTVERSION SVN_FILE_VERSION
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "Comments", "SDKTools Extension"
VALUE "FileDescription", "SourceMod SDKTools Extension"
VALUE "FileVersion", SVN_FULL_VERSION
VALUE "InternalName", "SourceMod SDKTools Extension"
VALUE "LegalCopyright", "Copyright (c) 2004-2008, AlliedModders LLC"
VALUE "OriginalFilename", "sdktools.ext.dll"
VALUE "ProductName", "SourceMod SDKTools Extension"
VALUE "ProductVersion", SVN_FULL_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
#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
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+162
View File
@@ -0,0 +1,162 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
void **g_pGameRules = NULL;
void *g_EntList = NULL;
#ifdef PLATFORM_WINDOWS
void InitializeValveGlobals()
{
char *addr = NULL;
int offset;
/* gEntList and/or g_pEntityList */
if (!g_pGameConf->GetMemSig("LevelShutdown", (void **)&addr) || !addr)
{
return;
}
if (!g_pGameConf->GetOffset("gEntList", &offset) || !offset)
{
return;
}
g_EntList = *reinterpret_cast<void **>(addr + offset);
/* g_pGameRules */
if (!g_pGameConf->GetMemSig("CreateGameRulesObject", (void **)&addr) || !addr)
{
return;
}
if (!g_pGameConf->GetOffset("g_pGameRules", &offset) || !offset)
{
return;
}
g_pGameRules = *reinterpret_cast<void ***>(addr + offset);
}
#elif defined PLATFORM_LINUX
void InitializeValveGlobals()
{
char *addr = NULL;
/* gEntList and/or g_pEntityList */
if (!g_pGameConf->GetMemSig("gEntList", (void **)&addr) || !addr)
{
return;
}
g_EntList = reinterpret_cast<void *>(addr);
/* g_pGameRules */
if (!g_pGameConf->GetMemSig("g_pGameRules", (void **)&addr) || !addr)
{
return;
}
g_pGameRules = reinterpret_cast<void **>(addr);
}
#endif
bool vcmp(const void *_addr1, const void *_addr2, size_t len)
{
unsigned char *addr1 = (unsigned char *)_addr1;
unsigned char *addr2 = (unsigned char *)_addr2;
for (size_t i=0; i<len; i++)
{
if (addr2[i] == '*')
continue;
if (addr1[i] != addr2[i])
return false;
}
return true;
}
#if defined PLATFORM_WINDOWS
/* Thanks to DS for the sigs */
#define ISERVER_WIN_SIG "\x8B\x44\x24\x2A\x50\xB9\x2A\x2A\x2A\x2A\xE8"
#define ISERVER_WIN_SIG_LEN 11
void GetIServer()
{
int offset;
void *vfunc = NULL;
/* Get the offset into CreateFakeClient */
if (!g_pGameConf->GetOffset("sv", &offset))
{
return;
}
#if defined METAMOD_PLAPI_VERSION
/* Get the CreateFakeClient function pointer */
if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient)))
{
return;
}
/* Check if we're on the expected function */
if (!vcmp(vfunc, ISERVER_WIN_SIG, ISERVER_WIN_SIG_LEN))
{
return;
}
/* Finally we have the interface we were looking for */
iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
#else
/* Get the interface manually */
SourceHook::MemFuncInfo info = {true, -1, 0, 0};
SourceHook::GetFuncInfo(&IVEngineServer::CreateFakeClient, info);
vfunc = enginePatch->GetOrigFunc(info.vtbloffs, info.vtblindex);
if (!vfunc)
{
void **vtable = *reinterpret_cast<void ***>(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs);
vfunc = vtable[info.vtblindex];
}
/* Check if we're on the expected function */
if (!vcmp(vfunc, ISERVER_WIN_SIG, ISERVER_WIN_SIG_LEN))
{
return;
}
iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
#endif
}
#elif defined PLATFORM_POSIX
void GetIServer()
{
void *addr;
if (!g_pGameConf->GetMemSig("sv", &addr) || !addr)
{
return;
}
iserver = reinterpret_cast<IServer *>(addr);
}
#endif
+41
View File
@@ -0,0 +1,41 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SDKTOOLS_VGLOBALS_H_
#define _INCLUDE_SDKTOOLS_VGLOBALS_H_
extern void **g_pGameRules;
extern void *g_EntList;
void InitializeValveGlobals();
void GetIServer();
#endif // _INCLUDE_SDKTOOLS_VGLOBALS_H_
+617
View File
@@ -0,0 +1,617 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
#include "util.h"
#include "vhelpers.h"
CallHelper s_Teleport;
CallHelper s_GetVelocity;
CallHelper s_EyeAngles;
class CTraceFilterSimple : public CTraceFilterEntitiesOnly
{
public:
CTraceFilterSimple(const IHandleEntity *passentity): m_pPassEnt(passentity)
{
}
virtual bool ShouldHitEntity(IHandleEntity *pServerEntity, int contentsMask)
{
if (pServerEntity == m_pPassEnt)
{
return false;
}
return true;
}
private:
const IHandleEntity *m_pPassEnt;
};
bool SetupTeleport()
{
if (s_Teleport.setup)
{
return s_Teleport.supported;
}
/* Setup Teleport */
int offset;
if (g_pGameConf->GetOffset("Teleport", &offset))
{
PassInfo info[3];
info[0].flags = info[1].flags = info[2].flags = PASSFLAG_BYVAL;
info[0].size = info[1].size = info[2].size = sizeof(void *);
info[0].type = info[1].type = info[2].type = PassType_Basic;
s_Teleport.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 3);
if (s_Teleport.call != NULL)
{
s_Teleport.supported = true;
}
}
s_Teleport.setup = true;
return s_Teleport.supported;
}
void Teleport(CBaseEntity *pEntity, Vector *origin, QAngle *ang, Vector *velocity)
{
unsigned char params[sizeof(void *) * 4];
unsigned char *vptr = params;
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
*(Vector **)vptr = origin;
vptr += sizeof(Vector *);
*(QAngle **)vptr = ang;
vptr += sizeof(QAngle *);
*(Vector **)vptr = velocity;
s_Teleport.call->Execute(params, NULL);
}
bool IsTeleportSupported()
{
return SetupTeleport();
}
bool SetupGetVelocity()
{
if (s_GetVelocity.setup)
{
return s_GetVelocity.supported;
}
int offset;
if (g_pGameConf->GetOffset("GetVelocity", &offset))
{
PassInfo info[2];
info[0].flags = info[1].flags = PASSFLAG_BYVAL;
info[0].size = info[1].size = sizeof(void *);
info[0].type = info[1].type = PassType_Basic;
s_GetVelocity.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 2);
if (s_GetVelocity.call != NULL)
{
s_GetVelocity.supported = true;
}
}
s_GetVelocity.setup = true;
return s_GetVelocity.supported;
}
void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity)
{
unsigned char params[sizeof(void *) * 3];
unsigned char *vptr = params;
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
*(Vector **)vptr = velocity;
vptr += sizeof(Vector *);
*(AngularImpulse **)vptr = angvelocity;
s_GetVelocity.call->Execute(params, NULL);
}
bool IsGetVelocitySupported()
{
return SetupGetVelocity();
}
bool SetupGetEyeAngles()
{
if (s_EyeAngles.setup)
{
return s_EyeAngles.supported;
}
int offset;
if (g_pGameConf->GetOffset("EyeAngles", &offset))
{
PassInfo info[2];
info[0].flags = info[1].flags = PASSFLAG_BYVAL;
info[0].size = info[1].size = sizeof(void *);
info[0].type = info[1].type = PassType_Basic;
s_EyeAngles.call = g_pBinTools->CreateVCall(offset, 0, 0, &info[0], &info[1], 1);
if (s_EyeAngles.call != NULL)
{
s_EyeAngles.supported = true;
}
}
s_EyeAngles.setup = true;
return s_EyeAngles.supported;
}
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles)
{
if (!IsEyeAnglesSupported())
{
return false;
}
QAngle *pRetAngle = NULL;
unsigned char params[sizeof(void *)];
unsigned char *vptr = params;
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
s_EyeAngles.call->Execute(params, &pRetAngle);
if (pRetAngle == NULL)
{
return false;
}
*pAngles = *pRetAngle;
return true;
}
int GetClientAimTarget(edict_t *pEdict, bool only_players)
{
CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
if (pEntity == NULL)
{
return -1;
}
Vector eye_position;
QAngle eye_angles;
/* Get the private information we need */
serverClients->ClientEarPosition(pEdict, &eye_position);
if (!GetEyeAngles(pEntity, &eye_angles))
{
return -2;
}
Vector aim_dir;
AngleVectors(eye_angles, &aim_dir);
VectorNormalize(aim_dir);
Vector vec_end = eye_position + aim_dir * 8000;
Ray_t ray;
ray.Init(eye_position, vec_end);
trace_t tr;
CTraceFilterSimple simple(pEdict->GetIServerEntity());
enginetrace->TraceRay(ray, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &simple, &tr);
if (tr.fraction == 1.0f || tr.m_pEnt == NULL)
{
return -1;
}
edict_t *pTarget = gameents->BaseEntityToEdict(tr.m_pEnt);
if (pTarget == NULL)
{
return -1;
}
int ent_index = engine->IndexOfEdict(pTarget);
IGamePlayer *pTargetPlayer = playerhelpers->GetGamePlayer(ent_index);
if (pTargetPlayer != NULL && !pTargetPlayer->IsInGame())
{
return -1;
}
else if (only_players && pTargetPlayer == NULL)
{
return -1;
}
return ent_index;
}
bool IsEyeAnglesSupported()
{
return SetupGetEyeAngles();
}
bool GetPlayerInfo(int client, player_info_t *info)
{
#if defined ORANGEBOX_BUILD
return engine->GetPlayerInfo(client, info);
#else
return (iserver) ? iserver->GetPlayerInfo(client-1, info) : false;
#endif
}
void ShutdownHelpers()
{
s_Teleport.Shutdown();
s_GetVelocity.Shutdown();
}
const char *GetDTTypeName(int type)
{
switch (type)
{
case DPT_Int:
{
return "integer";
}
case DPT_Float:
{
return "float";
}
case DPT_Vector:
{
return "vector";
}
case DPT_String:
{
return "string";
}
case DPT_Array:
{
return "array";
}
case DPT_DataTable:
{
return "datatable";
}
default:
{
return NULL;
}
}
return NULL;
}
void UTIL_DrawSendTable_XML(FILE *fp, SendTable *pTable, int space_count)
{
char spaces[255];
for (int i = 0; i < space_count; i++)
{
spaces[i] = ' ';
}
spaces[space_count] = '\0';
const char *type_name;
SendTable *pOtherTable;
SendProp *pProp;
fprintf(fp, " %s<sendtable name=\"%s\">\n", spaces, pTable->GetName());
for (int i = 0; i < pTable->GetNumProps(); i++)
{
pProp = pTable->GetProp(i);
fprintf(fp, " %s<property name=\"%s\">\n", spaces, pProp->GetName());
if ((type_name = GetDTTypeName(pProp->GetType())) != NULL)
{
fprintf(fp, " %s<type>%s</type>\n", spaces, type_name);
}
else
{
fprintf(fp, " %s<type>%d</type>\n", spaces, pProp->GetType());
}
fprintf(fp, " %s<offset>%d</offset>\n", spaces, pProp->GetOffset());
fprintf(fp, " %s<bits>%d</bits>\n", spaces, pProp->m_nBits);
if ((pOtherTable = pTable->GetProp(i)->GetDataTable()) != NULL)
{
UTIL_DrawSendTable_XML(fp, pOtherTable, space_count + 3);
}
fprintf(fp, " %s</property>\n", spaces);
}
fprintf(fp, " %s</sendtable>\n", spaces);
}
void UTIL_DrawServerClass_XML(FILE *fp, ServerClass *sc)
{
fprintf(fp, "<serverclass name=\"%s\">\n", sc->GetName());
UTIL_DrawSendTable_XML(fp, sc->m_pTable, 0);
fprintf(fp, "</serverclass>\n");
}
void UTIL_DrawSendTable(FILE *fp, SendTable *pTable, int level)
{
char spaces[255];
for (int i=0; i<level; i++)
spaces[i] = ' ';
spaces[level] = '\0';
const char *name, *type;
SendProp *pProp;
fprintf(fp, "%sSub-Class Table (%d Deep): %s\n", spaces, level, pTable->GetName());
for (int i=0; i<pTable->GetNumProps(); i++)
{
pProp = pTable->GetProp(i);
name = pProp->GetName();
if (pProp->GetDataTable())
{
UTIL_DrawSendTable(fp, pProp->GetDataTable(), level + 1);
}
else
{
type = GetDTTypeName(pProp->GetType());
if (type != NULL)
{
fprintf(fp,
"%s-Member: %s (offset %d) (type %s) (bits %d)\n",
spaces,
pProp->GetName(),
pProp->GetOffset(),
type,
pProp->m_nBits);
}
else
{
fprintf(fp,
"%s-Member: %s (offset %d) (type %d) (bits %d)\n",
spaces,
pProp->GetName(),
pProp->GetOffset(),
pProp->GetType(),
pProp->m_nBits);
}
}
}
}
CON_COMMAND(sm_dump_netprops_xml, "Dumps the networkable property table as an XML file")
{
#if !defined ORANGEBOX_BUILD
CCommand args;
#endif
if (args.ArgC() < 2)
{
META_CONPRINT("Usage: sm_dump_netprops_xml <file>\n");
return;
}
const char *file = args.Arg(1);
if (!file || file[0] == '\0')
{
META_CONPRINT("Usage: sm_dump_netprops_xml <file>\n");
return;
}
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
FILE *fp = NULL;
if ((fp = fopen(path, "wt")) == NULL)
{
META_CONPRINTF("Could not open file \"%s\"\n", path);
return;
}
fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
fprintf(fp, "<!-- Dump of all network properties for \"%s\" follows -->\n\n", g_pSM->GetGameFolderName());
ServerClass *pBase = gamedll->GetAllServerClasses();
while (pBase != NULL)
{
UTIL_DrawServerClass_XML(fp, pBase);
pBase = pBase->m_pNext;
}
fclose(fp);
}
CON_COMMAND(sm_dump_netprops, "Dumps the networkable property table as a text file")
{
#if !defined ORANGEBOX_BUILD
CCommand args;
#endif
if (args.ArgC() < 2)
{
META_CONPRINT("Usage: sm_dump_netprops <file>\n");
return;
}
const char *file = args.Arg(1);
if (!file || file[0] == '\0')
{
META_CONPRINT("Usage: sm_dump_netprops <file>\n");
return;
}
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
FILE *fp = NULL;
if ((fp = fopen(path, "wt")) == NULL)
{
META_CONPRINTF("Could not open file \"%s\"\n", path);
return;
}
fprintf(fp, "// Dump of all network properties for \"%s\" follows\n//\n\n", g_pSM->GetGameFolderName());
ServerClass *pBase = gamedll->GetAllServerClasses();
while (pBase != NULL)
{
fprintf(fp, "%s:\n", pBase->GetName());
UTIL_DrawSendTable(fp, pBase->m_pTable, 1);
pBase = pBase->m_pNext;
}
fclose(fp);
}
#if defined SUBPLATFORM_SECURECRT
void _ignore_invalid_parameter(
const wchar_t * expression,
const wchar_t * function,
const wchar_t * file,
unsigned int line,
uintptr_t pReserved
)
{
/* Wow we don't care, thanks Microsoft. */
}
#endif
CON_COMMAND(sm_dump_classes, "Dumps the class list as a text file")
{
#if !defined ORANGEBOX_BUILD
CCommand args;
#endif
if (args.ArgC() < 2)
{
META_CONPRINT("Usage: sm_dump_classes <file>\n");
return;
}
const char *file = args.Arg(1);
if (!file || file[0] == '\0')
{
META_CONPRINT("Usage: sm_dump_classes <file>\n");
return;
}
ICallWrapper *pWrapper = NULL;
if (!pWrapper)
{
PassInfo retData;
retData.flags = PASSFLAG_BYVAL;
retData.size = sizeof(void *);
retData.type = PassType_Basic;
void *addr;
if (!g_pGameConf->GetMemSig("EntityFactory", &addr) || addr == NULL)
{
META_CONPRINT("Failed to locate function\n");
return;
}
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retData, NULL, 0);
}
void *returnData = NULL;
pWrapper->Execute(NULL, &returnData);
pWrapper->Destroy();
if (returnData == NULL)
{
return;
}
CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )returnData;
if ( !dict )
{
return;
}
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
FILE *fp = NULL;
if ((fp = fopen(path, "wt")) == NULL)
{
META_CONPRINTF("Could not open file \"%s\"\n", path);
return;
}
char buffer[80];
buffer[0] = 0;
#if defined SUBPLATFORM_SECURECRT
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
#endif
time_t t = g_pSM->GetAdjustedTime();
size_t written = strftime(buffer, sizeof(buffer), "%d/%m/%Y", localtime(&t));
#if defined SUBPLATFORM_SECURECRT
_set_invalid_parameter_handler(handler);
#endif
fprintf(fp, "// Dump of all classes for \"%s\" as at %s\n//\n\n", g_pSM->GetGameFolderName(), buffer);
for ( int i = dict->m_Factories.First(); i != dict->m_Factories.InvalidIndex(); i = dict->m_Factories.Next( i ) )
{
IServerNetworkable *entity = dict->Create(dict->m_Factories.GetElementName(i));
ServerClass *sclass = entity->GetServerClass();
fprintf(fp,"%s - %s\n",sclass->GetName(), dict->m_Factories.GetElementName(i));
typedescription_t *datamap = gamehelpers->FindInDataMap(gamehelpers->GetDataMap(entity->GetBaseEntity()), "m_iEFlags");
int *eflags = (int *)((char *)entity->GetBaseEntity() + datamap->fieldOffset[TD_OFFSET_NORMAL]);
*eflags |= (1<<0); // EFL_KILLME
}
fclose(fp);
}
+75
View File
@@ -0,0 +1,75 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SDKTOOLS_VHELPERS_H_
#define _INCLUDE_SDKTOOLS_VHELPERS_H_
#include <sh_list.h>
#include <eiface.h>
#include <IBinTools.h>
using namespace SourceMod;
struct CallHelper
{
CallHelper() : call(NULL), supported(false), setup(false)
{
}
void Shutdown()
{
if (call)
{
call->Destroy();
call = NULL;
supported = false;
}
}
ICallWrapper *call;
bool supported;
bool setup;
};
void Teleport(CBaseEntity *pEntity, Vector *origin, QAngle *ang, Vector *velocity);
bool IsTeleportSupported();
void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity);
bool IsGetVelocitySupported();
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles);
bool IsEyeAnglesSupported();
int GetClientAimTarget(edict_t *pEdict, bool only_players);
bool GetPlayerInfo(int client, player_info_t *info);
void ShutdownHelpers();
#endif //_INCLUDE_SDKTOOLS_VHELPERS_H_
+899
View File
@@ -0,0 +1,899 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <stdlib.h>
#include <sh_string.h>
#include "extension.h"
#include "vcallbuilder.h"
#include "vnatives.h"
#include "vhelpers.h"
#include "vglobals.h"
#include "CellRecipientFilter.h"
SourceHook::List<ValveCall *> g_RegCalls;
SourceHook::List<ICallWrapper *> g_CallWraps;
inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsigned int flags, unsigned int decflags=0)
{
info.decflags = decflags;
info.encflags = 0;
info.flags = flags;
info.type = type;
info.vtype = vtype;
}
#define START_CALL() \
unsigned char *vptr = pCall->stk_get();
#define FINISH_CALL_SIMPLE(vret) \
pCall->call->Execute(vptr, vret); \
pCall->stk_put(vptr);
#define ENCODE_VALVE_PARAM(num, which, vnum) \
if (EncodeValveParam(pContext, \
params[num], \
pCall, \
&pCall->which[vnum], \
vptr) \
== Data_Fail) \
{ \
return 0; \
}
#define DECODE_VALVE_PARAM(num, which, vnum) \
if (DecodeValveParam(pContext, \
params[num], \
pCall, \
&pCall->which[vnum], \
vptr) \
== Data_Fail) \
{ \
return 0; \
}
bool CreateBaseCall(const char *name,
ValveCallType vcalltype,
const ValvePassInfo *retinfo,
const ValvePassInfo params[],
unsigned int numParams,
ValveCall **vaddr)
{
int offset;
ValveCall *call;
if (g_pGameConf->GetOffset(name, &offset))
{
call = CreateValveVCall(offset, vcalltype, retinfo, params, numParams);
if (call)
{
g_RegCalls.push_back(call);
}
*vaddr = call;
return true;
} else {
void *addr;
if (g_pGameConf->GetMemSig(name, &addr))
{
call = CreateValveCall(addr, vcalltype, retinfo, params, numParams);
if (call)
{
g_RegCalls.push_back(call);
}
*vaddr = call;
return true;
}
}
return false;
}
static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[2];
InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("RemovePlayerItem", ValveCall_Player, &pass[1], pass, 1, &pCall))
{
return pContext->ThrowNativeError("\"RemovePlayerItem\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"RemovePlayerItem\" wrapper failed to initialized");
}
}
bool ret;
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
FINISH_CALL_SIMPLE(&ret);
return ret ? 1 : 0;
}
static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[3];
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("GiveNamedItem", ValveCall_Player, &pass[2], pass, 2, &pCall))
{
return pContext->ThrowNativeError("\"GiveNamedItem\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"GiveNamedItem\" wrapper failed to initialized");
}
}
CBaseEntity *pEntity = NULL;
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
DECODE_VALVE_PARAM(3, vparams, 1);
FINISH_CALL_SIMPLE(&pEntity);
if (pEntity == NULL)
{
return -1;
}
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
if (!pEdict)
{
return -1;
}
return engine->IndexOfEdict(pEdict);
}
static cell_t GetPlayerWeaponSlot(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[2];
InitPass(pass[0], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("Weapon_GetSlot", ValveCall_Player, &pass[1], pass, 1, &pCall))
{
return pContext->ThrowNativeError("\"Weapon_GetSlot\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"Weapon_GetSlot\" wrapper failed to initialized");
}
}
CBaseEntity *pEntity;
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
FINISH_CALL_SIMPLE(&pEntity);
if (pEntity == NULL)
{
return -1;
}
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
if (!pEdict)
{
return -1;
}
return engine->IndexOfEdict(pEdict);
}
static cell_t IgniteEntity(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[4];
InitPass(pass[0], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[2], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
InitPass(pass[3], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("Ignite", ValveCall_Entity, NULL, pass, 4, &pCall))
{
return pContext->ThrowNativeError("\"Ignite\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"Ignite\" wrapper failed to initialized");
}
}
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
DECODE_VALVE_PARAM(3, vparams, 1);
DECODE_VALVE_PARAM(4, vparams, 2);
DECODE_VALVE_PARAM(5, vparams, 3);
FINISH_CALL_SIMPLE(NULL);
return 1;
}
static cell_t ExtinguishEntity(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
if (!CreateBaseCall("Extinguish", ValveCall_Entity, NULL, NULL, 0, &pCall))
{
return pContext->ThrowNativeError("\"Extinguish\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"Extinguish\" wrapper failed to initialized");
}
}
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
FINISH_CALL_SIMPLE(NULL);
return 1;
}
static cell_t TeleportEntity(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[3];
InitPass(pass[0], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
InitPass(pass[1], Valve_QAngle, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
InitPass(pass[2], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
if (!CreateBaseCall("Teleport", ValveCall_Entity, NULL, pass, 3, &pCall))
{
return pContext->ThrowNativeError("\"Teleport\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"Teleport\" wrapper failed to initialized");
}
}
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
DECODE_VALVE_PARAM(3, vparams, 1);
DECODE_VALVE_PARAM(4, vparams, 2);
FINISH_CALL_SIMPLE(NULL);
return 1;
}
#if defined ORANGEBOX_BUILD
/* :TODO: This is Team Fortress 2 specific */
static cell_t ForcePlayerSuicide(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[2];
InitPass(pass[0], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("CommitSuicide", ValveCall_Player, NULL, pass, 2, &pCall))
{
return pContext->ThrowNativeError("\"CommitSuicide\" not supported by this mod");
}
else if (!pCall)
{
return pContext->ThrowNativeError("\"CommitSuicide\" wrapper failed to initialized");
}
}
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
*(bool *)(vptr + 4) = false;
*(bool *)(vptr + 5) = false;
FINISH_CALL_SIMPLE(NULL);
return 1;
}
#else
static cell_t ForcePlayerSuicide(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
if (!CreateBaseCall("CommitSuicide", ValveCall_Player, NULL, NULL, 0, &pCall))
{
return pContext->ThrowNativeError("\"CommitSuicide\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"CommitSuicide\" wrapper failed to initialized");
}
}
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
FINISH_CALL_SIMPLE(NULL);
return 1;
}
#endif
static cell_t SetClientViewEntity(IPluginContext *pContext, const cell_t *params)
{
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
if (player == NULL)
{
return pContext->ThrowNativeError("Invalid client index %d", params[1]);
}
if (!player->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", params[1]);
}
edict_t *pEdict = engine->PEntityOfEntIndex(params[2]);
if (!pEdict || pEdict->IsFree())
{
return pContext->ThrowNativeError("Entity %d is not valid", params[2]);
}
engine->SetView(player->GetEdict(), pEdict);
return 1;
}
static SourceHook::String *g_lightstyle[MAX_LIGHTSTYLES] = {NULL};
static cell_t SetLightStyle(IPluginContext *pContext, const cell_t *params)
{
int style = params[1];
if (style >= MAX_LIGHTSTYLES)
{
return pContext->ThrowNativeError("Light style %d is invalid (range: 0-%d)", style, MAX_LIGHTSTYLES - 1);
}
if (g_lightstyle[style] == NULL)
{
/* We allocate and never free this because the Engine wants to hold onto it :\
* in theory we could hook light style and know whether we're supposed to free
* this or not on shutdown, but for ~4K of memory MAX, it doesn't seem worth it yet.
* So, it's a :TODO:!
*/
g_lightstyle[style] = new SourceHook::String();
}
char *str;
pContext->LocalToString(params[2], &str);
g_lightstyle[style]->assign(str);
engine->LightStyle(style, g_lightstyle[style]->c_str());
return 1;
}
static cell_t SlapPlayer(IPluginContext *pContext, const cell_t *params)
{
static bool s_slap_supported = false;
static bool s_slap_setup = false;
static ICallWrapper *s_teleport = NULL;
static int s_health_offs = 0;
static int s_sound_count = 0;
static int s_frag_offs = 0;
if (!s_slap_setup)
{
int tries = 0;
s_slap_setup = true;
if (IsTeleportSupported())
{
tries++;
}
if (IsGetVelocitySupported())
{
tries++;
}
/* Setup health */
if (g_pGameConf->GetOffset("m_iHealth", &s_health_offs) && s_health_offs)
{
tries++;
}
if (tries == 3)
{
s_slap_supported = true;
const char *key;
if ((key = g_pGameConf->GetKeyValue("SlapSoundCount")) != NULL)
{
s_sound_count = atoi(key);
}
}
}
if (!s_slap_supported)
{
return pContext->ThrowNativeError("This function is not supported on this mod");
}
/* First check if the client is valid */
int client = params[1];
IGamePlayer *player = playerhelpers->GetGamePlayer(client);
if (!player)
{
return pContext->ThrowNativeError("Client %d is not valid", client);
} else if (!player->IsInGame()) {
return pContext->ThrowNativeError("Client %d is not in game", client);
}
edict_t *pEdict = player->GetEdict();
CBaseEntity *pEntity = pEdict->GetUnknown()->GetBaseEntity();
/* See if we should be taking away health */
bool should_slay = false;
if (params[2])
{
int *health = (int *)((char *)pEntity + s_health_offs);
if (*health - params[2] <= 0)
{
*health = 1;
should_slay = true;
} else {
*health -= params[2];
}
}
/* Teleport in a random direction - thank you, Mani!*/
Vector velocity;
GetVelocity(pEntity, &velocity, NULL);
velocity.x += ((rand() % 180) + 50) * (((rand() % 2) == 1) ? -1 : 1);
velocity.y += ((rand() % 180) + 50) * (((rand() % 2) == 1) ? -1 : 1);
velocity.z += rand() % 200 + 100;
Teleport(pEntity, NULL, NULL, &velocity);
/* Play a random sound */
if (params[3] && s_sound_count > 0)
{
char name[48];
const char *sound_name;
cell_t player_list[256], total_players = 0;
int maxClients = playerhelpers->GetMaxClients();
int r = (rand() % s_sound_count) + 1;
snprintf(name, sizeof(name), "SlapSound%d", r);
if ((sound_name = g_pGameConf->GetKeyValue(name)) != NULL)
{
IGamePlayer *other;
for (int i=1; i<=maxClients; i++)
{
other = playerhelpers->GetGamePlayer(i);
if (other->IsInGame())
{
player_list[total_players++] = i;
}
}
const Vector & pos = pEdict->GetCollideable()->GetCollisionOrigin();
CellRecipientFilter rf;
rf.SetToReliable(true);
rf.Initialize(player_list, total_players);
engsound->EmitSound(rf, client, CHAN_AUTO, sound_name, VOL_NORM, ATTN_NORM, 0, PITCH_NORM, &pos);
}
}
if (!s_frag_offs)
{
const char *frag_prop = g_pGameConf->GetKeyValue("m_iFrags");
if (frag_prop)
{
datamap_t *pMap = gamehelpers->GetDataMap(pEntity);
typedescription_t *pType = gamehelpers->FindInDataMap(pMap, frag_prop);
if (pType != NULL)
{
s_frag_offs = pType->fieldOffset[TD_OFFSET_NORMAL];
}
}
if (!s_frag_offs)
{
s_frag_offs = -1;
}
}
int old_frags = 0;
if (s_frag_offs > 0)
{
old_frags = *(int *)((char *)pEntity + s_frag_offs);
}
/* Force suicide */
if (should_slay)
{
pluginhelpers->ClientCommand(pEdict, "kill\n");
}
if (s_frag_offs > 0)
{
*(int *)((char *)pEntity + s_frag_offs) = old_frags;
}
return 1;
}
static cell_t GetClientEyePosition(IPluginContext *pContext, const cell_t *params)
{
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
if (player == NULL)
{
return pContext->ThrowNativeError("Invalid client index %d", params[1]);
}
if (!player->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", params[1]);
}
Vector pos;
serverClients->ClientEarPosition(player->GetEdict(), &pos);
cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);
addr[0] = sp_ftoc(pos.x);
addr[1] = sp_ftoc(pos.y);
addr[2] = sp_ftoc(pos.z);
return 1;
}
static cell_t GetClientEyeAngles(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (!pPlayer)
{
return pContext->ThrowNativeError("Invalid client index %d", client);
}
else if (!pPlayer->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", client);
}
edict_t *pEdict = pPlayer->GetEdict();
CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
/* We always set the angles for backwards compatibility --
* The original function had no return value.
*/
QAngle angles;
bool got_angles = false;
if (pEntity != NULL)
{
got_angles = GetEyeAngles(pEntity, &angles);
}
cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);
addr[0] = sp_ftoc(angles.x);
addr[1] = sp_ftoc(angles.y);
addr[2] = sp_ftoc(angles.z);
return got_angles ? 1 : 0;
}
static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[3];
InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL|VDECODE_FLAG_ALLOWWORLD);
InitPass(pass[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("FindEntityByClassname", ValveCall_EntityList, &pass[2], pass, 2, &pCall))
{
return pContext->ThrowNativeError("\"FindEntityByClassname\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"FindEntityByClassname\" wrapper failed to initialized");
}
}
CBaseEntity *pEntity;
START_CALL();
*(void **)vptr = g_EntList;
DECODE_VALVE_PARAM(1, vparams, 0);
DECODE_VALVE_PARAM(2, vparams, 1);
FINISH_CALL_SIMPLE(&pEntity);
if (pEntity == NULL)
{
return -1;
}
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
if (!pEdict)
{
return -1;
}
return engine->IndexOfEdict(pEdict);
}
static cell_t CreateEntityByName(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[3];
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("CreateEntityByName", ValveCall_Static, &pass[2], pass, 2, &pCall))
{
return pContext->ThrowNativeError("\"CreateEntityByName\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"CreateEntityByName\" wrapper failed to initialized");
}
}
CBaseEntity *pEntity = NULL;
START_CALL();
DECODE_VALVE_PARAM(1, vparams, 0);
DECODE_VALVE_PARAM(2, vparams, 1);
FINISH_CALL_SIMPLE(&pEntity);
if (pEntity == NULL)
{
return -1;
}
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
if (!pEdict)
{
return -1;
}
return engine->IndexOfEdict(pEdict);
}
static cell_t DispatchSpawn(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[2];
InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("DispatchSpawn", ValveCall_Static, &pass[1], pass, 1, &pCall))
{
return pContext->ThrowNativeError("\"DispatchSpawn\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"DispatchSpawn\" wrapper failed to initialized");
}
}
int ret;
START_CALL();
DECODE_VALVE_PARAM(1, vparams, 0);
FINISH_CALL_SIMPLE(&ret);
return (ret == -1) ? 0 : 1;
}
static cell_t DispatchKeyValue(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[3];
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[2], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("DispatchKeyValue", ValveCall_Entity, &pass[2], pass, 2, &pCall))
{
return pContext->ThrowNativeError("\"DispatchKeyValue\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"DispatchKeyValue\" wrapper failed to initialized");
}
}
bool ret;
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
DECODE_VALVE_PARAM(3, vparams, 1);
FINISH_CALL_SIMPLE(&ret);
return (ret) ? 1 : 0;
}
static cell_t DispatchKeyValueFloat(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[3];
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
InitPass(pass[2], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("DispatchKeyValueFloat", ValveCall_Entity, &pass[2], pass, 2, &pCall))
{
return pContext->ThrowNativeError("\"DispatchKeyValueFloat\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"DispatchKeyValueFloat\" wrapper failed to initialized");
}
}
bool ret;
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
DECODE_VALVE_PARAM(3, vparams, 1);
FINISH_CALL_SIMPLE(&ret);
return (ret) ? 1 : 0;
}
static cell_t DispatchKeyValueVector(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[3];
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
#if defined ORANGEBOX_BUILD
InitPass(pass[1], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL);
#else
InitPass(pass[1], Valve_Vector, PassType_Object, PASSFLAG_BYVAL|PASSFLAG_OCTOR|PASSFLAG_OASSIGNOP);
#endif
InitPass(pass[2], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("DispatchKeyValueVector", ValveCall_Entity, &pass[2], pass, 2, &pCall))
{
return pContext->ThrowNativeError("\"DispatchKeyValueVector\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"DispatchKeyValueVector\" wrapper failed to initialized");
}
}
bool ret;
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
DECODE_VALVE_PARAM(3, vparams, 1);
FINISH_CALL_SIMPLE(&ret);
return (ret) ? 1 : 0;
}
static cell_t sm_GetClientAimTarget(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (!pPlayer)
{
return pContext->ThrowNativeError("Invalid client index %d", client);
}
else if (!pPlayer->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", client);
}
return GetClientAimTarget(pPlayer->GetEdict(), params[2] ? true : false);
}
static cell_t sm_SetEntityModel(IPluginContext *pContext, const cell_t *params)
{
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[1];
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("SetEntityModel", ValveCall_Entity, NULL, pass, 1, &pCall))
{
return pContext->ThrowNativeError("\"SetEntityModel\" not supported by this mod");
} else if (!pCall) {
return pContext->ThrowNativeError("\"SetEntityModel\" wrapper failed to initialized");
}
}
START_CALL();
DECODE_VALVE_PARAM(1, thisinfo, 0);
DECODE_VALVE_PARAM(2, vparams, 0);
FINISH_CALL_SIMPLE(NULL);
return 1;
}
static cell_t GetPlayerDecalFile(IPluginContext *pContext, const cell_t *params)
{
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
if (player == NULL)
{
return pContext->ThrowNativeError("Invalid client index %d", params[1]);
}
if (!player->IsInGame())
{
return pContext->ThrowNativeError("Client %d is not in game", params[1]);
}
player_info_t info;
char *buffer;
if (!GetPlayerInfo(params[1], &info) || !info.customFiles[0])
{
return 0;
}
pContext->LocalToString(params[2], &buffer);
Q_binarytohex((byte *)&info.customFiles[0], sizeof(info.customFiles[0]), buffer, params[3]);
return 1;
}
static cell_t GetServerNetStats(IPluginContext *pContext, const cell_t *params)
{
if (iserver == NULL)
{
return pContext->ThrowNativeError("IServer interface not supported, file a bug report.");
}
float in, out;
cell_t *pIn, *pOut;
pContext->LocalToPhysAddr(params[1], &pIn);
pContext->LocalToPhysAddr(params[2], &pOut);
iserver->GetNetStats(in, out);
*pIn = sp_ftoc(in);
*pOut = sp_ftoc(out);
return 1;
}
sp_nativeinfo_t g_Natives[] =
{
{"ExtinguishEntity", ExtinguishEntity},
{"ForcePlayerSuicide", ForcePlayerSuicide},
{"GivePlayerItem", GiveNamedItem},
{"GetPlayerWeaponSlot", GetPlayerWeaponSlot},
{"IgniteEntity", IgniteEntity},
{"RemovePlayerItem", RemovePlayerItem},
{"TeleportEntity", TeleportEntity},
{"SetClientViewEntity", SetClientViewEntity},
{"SetLightStyle", SetLightStyle},
{"SlapPlayer", SlapPlayer},
{"GetClientEyePosition", GetClientEyePosition},
{"GetClientEyeAngles", GetClientEyeAngles},
{"FindEntityByClassname", FindEntityByClassname},
{"CreateEntityByName", CreateEntityByName},
{"DispatchSpawn", DispatchSpawn},
{"DispatchKeyValue", DispatchKeyValue},
{"DispatchKeyValueFloat", DispatchKeyValueFloat},
{"DispatchKeyValueVector", DispatchKeyValueVector},
{"GetClientAimTarget", sm_GetClientAimTarget},
{"SetEntityModel", sm_SetEntityModel},
{"GetPlayerDecalFile", GetPlayerDecalFile},
{"GetServerNetStats", GetServerNetStats},
{NULL, NULL},
};
+41
View File
@@ -0,0 +1,41 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SDKTOOLS_VNATIVES_H_
#define _INCLUDE_SDKTOOLS_VNATIVES_H_
#include <sh_list.h>
extern SourceHook::List<ValveCall *> g_RegCalls;
extern sp_nativeinfo_t g_Natives[];
extern sp_nativeinfo_t g_SoundNatives[];
#endif //_INCLUDE_SDKTOOLS_VNATIVES_H_
+167
View File
@@ -0,0 +1,167 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <extension.h>
#define SPEAK_NORMAL 0
#define SPEAK_MUTED 1
#define SPEAK_ALL 2
#define SPEAK_LISTENALL 4
#define SPEAK_TEAM 8
#define SPEAK_LISTENTEAM 16
size_t g_VoiceFlags[65];
size_t g_VoiceFlagsCount = 0;
SH_DECL_HOOK3(IVoiceServer, SetClientListening, SH_NOATTRIB, 0, bool, int, int, bool);
bool SDKTools::OnSetClientListening(int iReceiver, int iSender, bool bListen)
{
if (g_VoiceFlags[iSender] & SPEAK_MUTED)
{
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false));
}
if ((g_VoiceFlags[iSender] & SPEAK_ALL) || (g_VoiceFlags[iReceiver] & SPEAK_LISTENALL))
{
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true));
}
if ((g_VoiceFlags[iSender] & SPEAK_TEAM) || (g_VoiceFlags[iReceiver] & SPEAK_LISTENTEAM))
{
IGamePlayer *pReceiver = playerhelpers->GetGamePlayer(iReceiver);
IGamePlayer *pSender = playerhelpers->GetGamePlayer(iSender);
if (pReceiver && pSender && pReceiver->IsInGame() && pSender->IsInGame())
{
IPlayerInfo *pRInfo = pReceiver->GetPlayerInfo();
IPlayerInfo *pSInfo = pSender->GetPlayerInfo();
if (pRInfo && pSInfo && pRInfo->GetTeamIndex() == pSInfo->GetTeamIndex())
{
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true));
}
}
}
RETURN_META_VALUE(MRES_IGNORED, bListen);
}
void SDKTools::OnClientDisconnecting(int client)
{
if (g_VoiceFlags[client])
{
g_VoiceFlags[client] = 0;
if (!--g_VoiceFlagsCount)
{
SH_REMOVE_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false);
}
}
}
static cell_t SetClientListeningFlags(IPluginContext *pContext, const cell_t *params)
{
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
if (player == NULL)
{
return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
} else if (!player->IsConnected()) {
return pContext->ThrowNativeError("Client %d is not connected", params[1]);
}
if (!params[2] && g_VoiceFlags[params[1]])
{
if (!--g_VoiceFlagsCount)
{
SH_REMOVE_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false);
}
} else if (!g_VoiceFlags[params[1]] && params[2]) {
if (!g_VoiceFlagsCount++)
{
SH_ADD_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false);
}
}
g_VoiceFlags[params[1]] = params[2];
return 1;
}
static cell_t GetClientListeningFlags(IPluginContext *pContext, const cell_t *params)
{
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
if (player == NULL)
{
return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
} else if (!player->IsConnected()) {
return pContext->ThrowNativeError("Client %d is not connected", params[1]);
}
return g_VoiceFlags[params[1]];
}
static cell_t SetClientListening(IPluginContext *pContext, const cell_t *params)
{
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
if (player == NULL)
{
return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
} else if (!player->IsConnected()) {
return pContext->ThrowNativeError("Client %d is not connected", params[1]);
}
bool bListen = !params[3] ? false : true;
return voiceserver->SetClientListening(params[1], params[2], bListen) ? 1 : 0;
}
static cell_t GetClientListening(IPluginContext *pContext, const cell_t *params)
{
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
if (player == NULL)
{
return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
} else if (!player->IsConnected()) {
return pContext->ThrowNativeError("Client %d is not connected", params[1]);
}
return voiceserver->GetClientListening(params[1], params[2]) ? 1 : 0;
}
sp_nativeinfo_t g_VoiceNatives[] =
{
{"SetClientListeningFlags", SetClientListeningFlags},
{"GetClientListeningFlags", GetClientListeningFlags},
{"SetClientListening", SetClientListening},
{"GetClientListening", GetClientListening},
{NULL, NULL},
};
+751
View File
@@ -0,0 +1,751 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "vsound.h"
#include <IForwardSys.h>
SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float);
SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 1, IRecipientFilter &, int, int, const char *, float, soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
bool g_InSoundHook = false;
/***************************
* *
* Sound Related Hook Class *
* *
****************************/
size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
{
size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
for (size_t i=0; i<size; i++)
{
pl_array[i] = pFilter->GetRecipientIndex(i);
}
return size;
}
void SoundHooks::_IncRefCounter(int type)
{
if (type == NORMAL_SOUND_HOOK)
{
if (m_NormalCount++ == 0)
{
SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
}
}
else if (type == AMBIENT_SOUND_HOOK)
{
if (m_AmbientCount++ == 0)
{
SH_ADD_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
}
}
}
void SoundHooks::_DecRefCounter(int type)
{
if (type == NORMAL_SOUND_HOOK)
{
if (--m_NormalCount == 0)
{
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
}
}
else if (type == AMBIENT_SOUND_HOOK)
{
if (--m_AmbientCount == 0)
{
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
}
}
}
void SoundHooks::Initialize()
{
plsys->AddPluginsListener(this);
}
void SoundHooks::Shutdown()
{
plsys->RemovePluginsListener(this);
if (m_NormalCount)
{
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
}
if (m_AmbientCount)
{
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
}
}
void SoundHooks::OnPluginUnloaded(IPlugin *plugin)
{
SoundHookIter iter;
IPluginContext *pContext = plugin->GetBaseContext();
if (m_AmbientCount)
{
for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); )
{
if ((*iter)->GetParentContext() == pContext)
{
iter = m_AmbientFuncs.erase(iter);
_DecRefCounter(AMBIENT_SOUND_HOOK);
}
else
{
iter++;
}
}
}
if (m_NormalCount)
{
for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); )
{
if ((*iter)->GetParentContext() == pContext)
{
iter = m_NormalFuncs.erase(iter);
_DecRefCounter(NORMAL_SOUND_HOOK);
}
else
{
iter++;
}
}
}
}
void SoundHooks::AddHook(int type, IPluginFunction *pFunc)
{
if (type == NORMAL_SOUND_HOOK)
{
m_NormalFuncs.push_back(pFunc);
_IncRefCounter(NORMAL_SOUND_HOOK);
}
else if (type == AMBIENT_SOUND_HOOK)
{
m_AmbientFuncs.push_back(pFunc);
_IncRefCounter(AMBIENT_SOUND_HOOK);
}
}
bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc)
{
SoundHookIter iter;
if (type == NORMAL_SOUND_HOOK)
{
if ((iter=m_NormalFuncs.find(pFunc)) != m_NormalFuncs.end())
{
m_NormalFuncs.erase(iter);
_DecRefCounter(NORMAL_SOUND_HOOK);
return true;
}
else
{
return false;
}
}
else if (type == AMBIENT_SOUND_HOOK)
{
if ((iter=m_AmbientFuncs.find(pFunc)) != m_AmbientFuncs.end())
{
m_AmbientFuncs.erase(iter);
_DecRefCounter(AMBIENT_SOUND_HOOK);
return true;
}
else
{
return false;
}
}
return false;
}
void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol,
soundlevel_t soundlevel, int fFlags, int pitch, float delay)
{
SoundHookIter iter;
IPluginFunction *pFunc;
cell_t vec[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
cell_t res = static_cast<ResultType>(Pl_Continue);
char buffer[PLATFORM_MAX_PATH];
strcpy(buffer, samp);
for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); iter++)
{
pFunc = (*iter);
pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
pFunc->PushCellByRef(&entindex);
pFunc->PushFloatByRef(&vol);
pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&soundlevel));
pFunc->PushCellByRef(&pitch);
pFunc->PushArray(vec, 3, SM_PARAM_COPYBACK);
pFunc->PushCellByRef(&fFlags);
pFunc->PushFloatByRef(&delay);
g_InSoundHook = true;
pFunc->Execute(&res);
g_InSoundHook = false;
switch (res)
{
case Pl_Handled:
case Pl_Stop:
{
RETURN_META(MRES_SUPERCEDE);
}
case Pl_Changed:
{
Vector vec2;
vec2.x = sp_ctof(vec[0]);
vec2.y = sp_ctof(vec[1]);
vec2.z = sp_ctof(vec[2]);
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound,
(entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay));
}
}
}
}
void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity)
{
SoundHookIter iter;
IPluginFunction *pFunc;
cell_t res = static_cast<ResultType>(Pl_Continue);
char buffer[PLATFORM_MAX_PATH];
strcpy(buffer, pSample);
for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
{
int players[64], size;
size = _FillInPlayers(players, &filter);
pFunc = (*iter);
pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
pFunc->PushCellByRef(&size);
pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
pFunc->PushCellByRef(&iEntIndex);
pFunc->PushCellByRef(&iChannel);
pFunc->PushFloatByRef(&flVolume);
pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&iSoundlevel));
pFunc->PushCellByRef(&iPitch);
pFunc->PushCellByRef(&iFlags);
g_InSoundHook = true;
pFunc->Execute(&res);
g_InSoundHook = false;
switch (res)
{
case Pl_Handled:
case Pl_Stop:
{
RETURN_META(MRES_SUPERCEDE);
}
case Pl_Changed:
{
CellRecipientFilter crf;
crf.Initialize(players, size);
RETURN_META_NEWPARAMS(
MRES_IGNORED,
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, soundlevel_t,
int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
(crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, pOrigin,
pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
);
}
}
}
}
void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity)
{
SoundHookIter iter;
IPluginFunction *pFunc;
cell_t res = static_cast<ResultType>(Pl_Continue);
cell_t sndlevel = static_cast<cell_t>(ATTN_TO_SNDLVL(flAttenuation));
char buffer[PLATFORM_MAX_PATH];
strcpy(buffer, pSample);
for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
{
int players[64], size;
size = _FillInPlayers(players, &filter);
pFunc = (*iter);
pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
pFunc->PushCellByRef(&size);
pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
pFunc->PushCellByRef(&iEntIndex);
pFunc->PushCellByRef(&iChannel);
pFunc->PushFloatByRef(&flVolume);
pFunc->PushCellByRef(&sndlevel);
pFunc->PushCellByRef(&iPitch);
pFunc->PushCellByRef(&iFlags);
g_InSoundHook = true;
pFunc->Execute(&res);
g_InSoundHook = false;
switch (res)
{
case Pl_Handled:
case Pl_Stop:
{
RETURN_META(MRES_SUPERCEDE);
}
case Pl_Changed:
{
CellRecipientFilter crf;
crf.Initialize(players, size);
RETURN_META_NEWPARAMS(
MRES_IGNORED,
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, float,
int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
(crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)),
iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
);
}
}
}
}
/************************
* *
* Sound Related Natives *
* *
*************************/
SoundHooks s_SoundHooks;
static cell_t PrefetchSound(IPluginContext *pContext, const cell_t *params)
{
char *name;
pContext->LocalToString(params[1], &name);
engsound->PrefetchSound(name);
return 1;
}
static cell_t GetSoundDuration(IPluginContext *pContext, const cell_t *params)
{
char *name;
pContext->LocalToString(params[1], &name);
return sp_ftoc(engsound->GetSoundDuration(name));
}
static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params)
{
cell_t entity;
Vector pos;
char *name;
float vol, delay;
int pitch, flags, level;
entity = params[3];
cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);
pos.x = sp_ctof(addr[0]);
pos.y = sp_ctof(addr[1]);
pos.z = sp_ctof(addr[2]);
pContext->LocalToString(params[1], &name);
vol = sp_ctof(params[6]);
level = params[4];
flags = params[5];
pitch = params[7];
delay = sp_ctof(params[8]);
if (g_InSoundHook)
{
ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
}
else
{
engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
}
return 1;
}
static cell_t FadeClientVolume(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
if (client < 1 || client > playerhelpers->GetMaxClients())
{
return pContext->ThrowNativeError("Client index %d is not valid", client);
}
IGamePlayer *player = playerhelpers->GetGamePlayer(client);
if (!player->IsInGame())
{
return pContext->ThrowNativeError("Client index %d is not in game", client);
}
engine->FadeClientVolume(player->GetEdict(),
sp_ctof(params[2]),
sp_ctof(params[3]),
sp_ctof(params[4]),
sp_ctof(params[5]));
return 1;
}
static cell_t StopSound(IPluginContext *pContext, const cell_t *params)
{
int entity = params[1];
int channel = params[2];
char *name;
pContext->LocalToString(params[3], &name);
engsound->StopSound(entity, channel, name);
return 1;
}
static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
{
cell_t *addr, *pl_addr;
CellRecipientFilter crf;
pContext->LocalToPhysAddr(params[1], &pl_addr);
crf.Initialize(pl_addr, params[2]);
char *sample;
pContext->LocalToString(params[3], &sample);
int entity = params[4];
int channel = params[5];
int level = params[6];
int flags = params[7];
float vol = sp_ctof(params[8]);
int pitch = params[9];
int speakerentity = params[10];
Vector *pOrigin = NULL, origin;
Vector *pDir = NULL, dir;
pContext->LocalToPhysAddr(params[11], &addr);
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
{
pOrigin = &origin;
origin.x = sp_ctof(addr[0]);
origin.y = sp_ctof(addr[1]);
origin.z = sp_ctof(addr[2]);
}
pContext->LocalToPhysAddr(params[12], &addr);
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
{
pDir = &dir;
dir.x = sp_ctof(addr[0]);
dir.y = sp_ctof(addr[1]);
dir.z = sp_ctof(addr[2]);
}
bool updatePos = params[13] ? true : false;
float soundtime = sp_ctof(params[14]);
CUtlVector<Vector> *pOrigVec = NULL;
CUtlVector<Vector> origvec;
if (params[0] > 14)
{
pOrigVec = &origvec;
for (cell_t i = 15; i <= params[0]; i++)
{
Vector vec;
pContext->LocalToPhysAddr(params[i], &addr);
vec.x = sp_ctof(addr[0]);
vec.y = sp_ctof(addr[1]);
vec.z = sp_ctof(addr[2]);
origvec.AddToTail(vec);
}
}
/* If we're going to a "local player" and this is a dedicated server,
* intelligently redirect each sound.
*/
if (entity == -2 && engine->IsDedicatedServer())
{
for (cell_t i=0; i<params[2]; i++)
{
cell_t player[1];
player[0] = pl_addr[i];
crf.Reset();
crf.Initialize(player, 1);
if (g_InSoundHook)
{
SH_CALL(enginesoundPatch,
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
(&IEngineSound::EmitSound))
(crf,
player[0],
channel,
sample,
vol,
(soundlevel_t)level,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity);
}
else
{
engsound->EmitSound(crf,
player[0],
channel,
sample,
vol,
(soundlevel_t)level,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity);
}
}
} else {
if (g_InSoundHook)
{
SH_CALL(enginesoundPatch,
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
(&IEngineSound::EmitSound))
(crf,
entity,
channel,
sample,
vol,
(soundlevel_t)level,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity);
}
else
{
engsound->EmitSound(crf,
entity,
channel,
sample,
vol,
(soundlevel_t)level,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity);
}
}
return 1;
}
static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params)
{
cell_t *addr;
CellRecipientFilter crf;
pContext->LocalToPhysAddr(params[1], &addr);
crf.Initialize(addr, params[2]);
int sentence = params[3];
int entity = params[4];
int channel = params[5];
int level = params[6];
int flags = params[7];
float vol = sp_ctof(params[8]);
int pitch = params[9];
int speakerentity = params[10];
Vector *pOrigin = NULL, origin;
Vector *pDir = NULL, dir;
pContext->LocalToPhysAddr(params[11], &addr);
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
{
pOrigin = &origin;
origin.x = sp_ctof(addr[0]);
origin.y = sp_ctof(addr[1]);
origin.z = sp_ctof(addr[2]);
}
pContext->LocalToPhysAddr(params[12], &addr);
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
{
pDir = &dir;
dir.x = sp_ctof(addr[0]);
dir.y = sp_ctof(addr[1]);
dir.z = sp_ctof(addr[2]);
}
bool updatePos = params[13] ? true : false;
float soundtime = sp_ctof(params[14]);
CUtlVector<Vector> *pOrigVec = NULL;
CUtlVector<Vector> origvec;
if (params[0] > 14)
{
pOrigVec = &origvec;
for (cell_t i = 15; i <= params[0]; i++)
{
Vector vec;
pContext->LocalToPhysAddr(params[i], &addr);
vec.x = sp_ctof(addr[0]);
vec.y = sp_ctof(addr[1]);
vec.z = sp_ctof(addr[2]);
origvec.AddToTail(vec);
}
}
engsound->EmitSentenceByIndex(crf,
entity,
channel,
sentence,
vol,
(soundlevel_t)level,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity);
return 1;
}
static cell_t smn_AddAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
{
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
}
s_SoundHooks.AddHook(AMBIENT_SOUND_HOOK, pFunc);
return 1;
}
static cell_t smn_AddNormalSoundHook(IPluginContext *pContext, const cell_t *params)
{
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
}
s_SoundHooks.AddHook(NORMAL_SOUND_HOOK, pFunc);
return 1;
}
static cell_t smn_RemoveAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
{
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
}
if (!s_SoundHooks.RemoveHook(AMBIENT_SOUND_HOOK, pFunc))
{
return pContext->ThrowNativeError("Invalid hooked function");
}
return 1;
}
static cell_t smn_RemoveNormalSoundHook(IPluginContext *pContext, const cell_t *params)
{
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
if (!pFunc)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
}
if (!s_SoundHooks.RemoveHook(NORMAL_SOUND_HOOK, pFunc))
{
return pContext->ThrowNativeError("Invalid hooked function");
}
return 1;
}
sp_nativeinfo_t g_SoundNatives[] =
{
{"EmitAmbientSound", EmitAmbientSound},
{"EmitSentence", EmitSentence},
{"EmitSound", EmitSound},
{"FadeClientVolume", FadeClientVolume},
{"GetSoundDuration", GetSoundDuration},
{"PrefetchSound", PrefetchSound},
{"StopSound", StopSound},
{"AddAmbientSoundHook", smn_AddAmbientSoundHook},
{"AddNormalSoundHook", smn_AddNormalSoundHook},
{"RemoveAmbientSoundHook", smn_RemoveAmbientSoundHook},
{"RemoveNormalSoundHook", smn_RemoveNormalSoundHook},
{NULL, NULL},
};
+76
View File
@@ -0,0 +1,76 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_VSOUND_H_
#define _INCLUDE_SOURCEMOD_VSOUND_H_
#include <sh_list.h>
#include "extension.h"
#include "CellRecipientFilter.h"
#define NORMAL_SOUND_HOOK 0
#define AMBIENT_SOUND_HOOK 1
typedef SourceHook::List<IPluginFunction *>::iterator SoundHookIter;
class SoundHooks : public IPluginsListener
{
public: //IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public:
void Initialize();
void Shutdown();
void AddHook(int type, IPluginFunction *pFunc);
bool RemoveHook(int type, IPluginFunction *pFunc);
void OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol,
soundlevel_t soundlevel, int fFlags, int pitch, float delay);
void OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume,
soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity);
void OnEmitSound2(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume,
float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity);
private:
size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter);
void _IncRefCounter(int type);
void _DecRefCounter(int type);
private:
SourceHook::List<IPluginFunction *> m_AmbientFuncs;
SourceHook::List<IPluginFunction *> m_NormalFuncs;
size_t m_NormalCount;
size_t m_AmbientCount;
};
extern SoundHooks s_SoundHooks;
#endif //_INCLUDE_SOURCEMOD_VSOUND_H_
+266
View File
@@ -0,0 +1,266 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SDKTools Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "extension.h"
static cell_t LockStringTables(IPluginContext *pContext, const cell_t *params)
{
bool lock = params[1] ? true : false;
return engine->LockNetworkStringTables(lock) ? 1 : 0;
}
static cell_t FindStringTable(IPluginContext *pContext, const cell_t *params)
{
char *name;
pContext->LocalToString(params[1], &name);
INetworkStringTable *pTable = netstringtables->FindTable(name);
if (!pTable)
{
return INVALID_STRING_TABLE;
}
return pTable->GetTableId();
}
static cell_t GetNumStringTables(IPluginContext *pContext, const cell_t *params)
{
return netstringtables->GetNumTables();
}
static cell_t GetStringTableNumStrings(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
return pTable->GetNumStrings();
}
static cell_t GetStringTableMaxStrings(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
return pTable->GetMaxStrings();
}
static cell_t GetStringTableName(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
size_t numBytes;
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
pContext->StringToLocalUTF8(params[2], params[3], pTable->GetTableName(), &numBytes);
return numBytes;
}
static cell_t FindStringIndex(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
char *str;
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
pContext->LocalToString(params[2], &str);
return pTable->FindStringIndex(str);
}
static cell_t ReadStringTable(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
int stringidx;
const char *value;
size_t numBytes;
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
stringidx = params[2];
value = pTable->GetString(stringidx);
if (!value)
{
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
}
pContext->StringToLocalUTF8(params[3], params[4], value, &numBytes);
return numBytes;
}
static cell_t GetStringTableDataLength(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
int stringidx;
const void *userdata;
int datalen;
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
stringidx = params[2];
if (stringidx < 0 || stringidx >= pTable->GetNumStrings())
{
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
}
userdata = pTable->GetStringUserData(stringidx, &datalen);
if (!userdata)
{
datalen = 0;
}
return datalen;
}
static cell_t GetStringTableData(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
int stringidx;
const char *userdata;
int datalen;
size_t numBytes;
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
stringidx = params[2];
if (stringidx < 0 || stringidx >= pTable->GetNumStrings())
{
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
}
userdata = (const char *)pTable->GetStringUserData(stringidx, &datalen);
if (!userdata)
{
userdata = "";
}
pContext->StringToLocalUTF8(params[3], params[4], userdata, &numBytes);
return numBytes;
}
static cell_t SetStringTableData(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
int stringidx;
char *userdata;
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
stringidx = params[2];
if (stringidx < 0 || stringidx >= pTable->GetNumStrings())
{
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
}
pContext->LocalToString(params[3], &userdata);
pTable->SetStringUserData(stringidx, params[4], userdata);
return 1;
}
static cell_t AddToStringTable(IPluginContext *pContext, const cell_t *params)
{
TABLEID idx = static_cast<TABLEID>(params[1]);
INetworkStringTable *pTable = netstringtables->GetTable(idx);
char *str, *userdata;
if (!pTable)
{
return pContext->ThrowNativeError("Invalid string table index %d", idx);
}
pContext->LocalToString(params[2], &str);
pContext->LocalToString(params[3], &userdata);
#if defined ORANGEBOX_BUILD
pTable->AddString(true, str, params[4], userdata);
#else
pTable->AddString(str, params[4], userdata);
#endif
return 1;
}
sp_nativeinfo_t g_StringTableNatives[] =
{
{"LockStringTables", LockStringTables},
{"FindStringTable", FindStringTable},
{"GetNumStringTables", GetNumStringTables},
{"GetStringTableNumStrings", GetStringTableNumStrings},
{"GetStringTableMaxStrings", GetStringTableMaxStrings},
{"GetStringTableName", GetStringTableName},
{"FindStringIndex", FindStringIndex},
{"ReadStringTable", ReadStringTable},
{"GetStringTableDataLength", GetStringTableDataLength},
{"GetStringTableData", GetStringTableData},
{"SetStringTableData", SetStringTableData},
{"AddToStringTable", AddToStringTable},
{NULL, NULL},
};