From 88023370eafe3e13efbf5a6234c360d0ce36006a Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 27 Feb 2007 08:21:01 +0000 Subject: [PATCH] implemented wrapper around BAT's AdminInterface --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40548 --- extensions/batsupport/BATInterface.h | 61 +++ extensions/batsupport/Makefile | 91 +++++ extensions/batsupport/extension.cpp | 235 +++++++++++ extensions/batsupport/extension.h | 46 +++ extensions/batsupport/msvc8/batsupport.sln | 20 + extensions/batsupport/msvc8/batsupport.vcproj | 380 ++++++++++++++++++ extensions/batsupport/smsdk_config.h | 33 ++ extensions/batsupport/smsdk_ext.cpp | 333 +++++++++++++++ extensions/batsupport/smsdk_ext.h | 196 +++++++++ 9 files changed, 1395 insertions(+) create mode 100644 extensions/batsupport/BATInterface.h create mode 100644 extensions/batsupport/Makefile create mode 100644 extensions/batsupport/extension.cpp create mode 100644 extensions/batsupport/extension.h create mode 100644 extensions/batsupport/msvc8/batsupport.sln create mode 100644 extensions/batsupport/msvc8/batsupport.vcproj create mode 100644 extensions/batsupport/smsdk_config.h create mode 100644 extensions/batsupport/smsdk_ext.cpp create mode 100644 extensions/batsupport/smsdk_ext.h diff --git a/extensions/batsupport/BATInterface.h b/extensions/batsupport/BATInterface.h new file mode 100644 index 00000000..7ed28961 --- /dev/null +++ b/extensions/batsupport/BATInterface.h @@ -0,0 +1,61 @@ +/* ======== Basic Admin tool ======== +* Copyright (C) 2004-2006 Erling K. Sæterdal +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Erling K. Sæterdal ( EKS ) +* Credits: +* Menu code based on code from CSDM ( http://www.tcwonline.org/~dvander/cssdm ) Created by BAILOPAN +* Helping on misc errors/functions: BAILOPAN,LDuke,sslice,devicenull,PMOnoTo,cybermind ( most who idle in #sourcemod on GameSurge realy ) +* ============================ */ + +#ifndef _INCLUDE_BATINTERFACE +#define _INCLUDE_BATINTERFACE +#include "ismmplugin.h" + +#define ADMININTERFACE_VERSION 0 +#define ADMININTERFACE_MAXACCESSLENGTHTEXT 50 // This is the maximum length of a "flag" access text. + +//#include "BATMenu.h" + +//extern menuId g_AdminMenu; +class AdminInterfaceListner +{ +public: + virtual void OnAdminInterfaceUnload()=0; + virtual void Client_Authorized(int id)=0; +}; + +class AdminInterface +{ +public: + virtual bool RegisterFlag(const char *Class,const char *Flag,const char *Description) = 0; // Registers a new admin access + virtual bool IsClient(int id) = 0; // returns false if client is bot, or NOT connected + virtual bool HasFlag(int id,const char *Flag) = 0; // returns true if the player has this access flag, lower case only + virtual int GetInterfaceVersion() = 0 ; // Returns the interface version of the admin mod + virtual const char* GetModName() = 0; // Returns the name of the current admin mod + virtual void AddEventListner(AdminInterfaceListner *ptr) = 0; // You should ALLWAYS set this, so you know when the "server" plugin gets unloaded + virtual void RemoveListner(AdminInterfaceListner *ptr) = 0; // You MUST CALL this function in your plugin unloads function, or the admin plugin will crash on next client connect. +}; + +class BATAdminInterface : public AdminInterface +{ +public: + bool RegisterFlag(const char *Class,const char *Flag,const char *Description); // Max 1 admin access at the time, returns true if done successfully + bool IsClient(int id); // returns false if client is bot, or NOT connected + bool HasFlag(int id,const char *Flag); // returns true if the player has this access flag + int GetInterfaceVersion() { return ADMININTERFACE_VERSION; } // Returns the interface version of the admin mod + const char* GetModName() { return "BAT"; } // Returns the name of the current admin mod + void AddEventListner(AdminInterfaceListner *ptr); // You should ALLWAYS set this, so you know when the "server" plugin gets unloaded + void RemoveListner(AdminInterfaceListner *ptr); +private: + char GetFlagFromInt(int CharIndex); + bool CustomAccessExistence(const char *Flag); +}; +class MyListener : public IMetamodListener +{ +public: + virtual void *OnMetamodQuery(const char *iface, int *ret); +}; +#endif \ No newline at end of file diff --git a/extensions/batsupport/Makefile b/extensions/batsupport/Makefile new file mode 100644 index 00000000..537e149c --- /dev/null +++ b/extensions/batsupport/Makefile @@ -0,0 +1,91 @@ +#(C)2004-2006 SourceMM Development Team +# Makefile written by David "BAILOPAN" Anderson + +SMSDK = ../.. +SRCDS = ~/srcds +SOURCEMM = ../../../../sourcemm + +##################################### +### EDIT BELOW FOR OTHER PROJECTS ### +##################################### + +PROJECT = sample + +#Uncomment for SourceMM-enabled extensions +#LINK_HL2 = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so + +OBJECTS = extension.cpp smsdk_ext.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 + +HL2PUB = $(HL2SDK)/public +HL2LIB = $(HL2SDK)/linux_sdk +HL2SDK = $(SOURCEMM)/hl2sdk +SMM_TRUNK = $(SOURCEMM)/trunk + +LINK = $(LINK_HL2) -static-libgcc + +INCLUDE = -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \ + -I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_TRUNK) -I$(SMM_TRUNK)/sourcehook -I$(SMM_TRUNK)/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 -fPIC -msse -DSOURCEMOD_BUILD +CPPFLAGS = -Wno-non-virtual-dtor -fno-exceptions -fno-rtti + +################################################ +### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### +################################################ + +ifeq "$(DEBUG)" "true" + BIN_DIR = Debug + CFLAGS += $(C_DEBUG_FLAGS) +else + BIN_DIR = Release + 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) +OBJ_LINUX := $(OBJECTS:%.c=$(BIN_DIR)/%.o) + +$(BIN_DIR)/%.o: %.cpp + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +$(BIN_DIR)/%.o: %.c + $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< + +all: + mkdir -p $(BIN_DIR) + ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so + ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so + $(MAKE) extension + rm -rf $(BINARY) + +extension: $(OBJ_LINUX) + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) + +debug: + $(MAKE) all DEBUG=true + +default: all + +clean: + rm -rf Release/*.o + rm -rf Release/$(BINARY) + rm -rf Debug/*.o + rm -rf Debug/$(BINARY) + diff --git a/extensions/batsupport/extension.cpp b/extensions/batsupport/extension.cpp new file mode 100644 index 00000000..96ef66cc --- /dev/null +++ b/extensions/batsupport/extension.cpp @@ -0,0 +1,235 @@ +// vim: set ts=4 : +#include +#include +#include "extension.h" + +BatSupport g_BatSupport; /**< Global singleton for your extension's main interface */ +IAdminSystem *admins = NULL; +IPlayerManager *players = NULL; +SMEXT_LINK(&g_BatSupport); + +bool BatSupport::SDK_OnLoad(char *error, size_t err_max, bool late) +{ + SM_GET_IFACE(ADMINSYS, admins); + SM_GET_IFACE(PLAYERMANAGER, players); + + players->AddClientListener(this); + + return true; +} + +void BatSupport::SDK_OnUnload() +{ + players->RemoveClientListener(this); + + List::iterator iter; + AdminInterfaceListner *hook; + + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + hook = (*iter); + hook->OnAdminInterfaceUnload(); + } + + /* In case plugins don't do this */ + m_hooks.clear(); +} + +bool BatSupport::SDK_OnMetamodLoad(char *error, size_t err_max, bool late) +{ + g_SMAPI->AddListener(this, this); + + return true; +} + +void BatSupport::OnClientAuthorized(int client, const char *authstring) +{ + List::iterator iter; + AdminInterfaceListner *hook; + + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + hook = (*iter); + hook->Client_Authorized(client); + } +} + +const char *BatSupport::GetModName() +{ + return "SourceMod"; +} + +int BatSupport::GetInterfaceVersion() +{ + return ADMININTERFACE_VERSION; +} + +void *BatSupport::OnMetamodQuery(const char *iface, int *ret) +{ + if (strcmp(iface, "AdminInterface") == 0) + { + AdminInterface *pThis = this; + if (ret) + { + *ret = IFACE_OK; + } + return pThis; + } + + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; +} + +bool BatSupport::RegisterFlag(const char *Class,const char *Flag,const char *Description) +{ + /* No empty flags */ + if (Flag[0] == '\0') + { + g_pSM->LogError(myself, "BAT AdminInterface support tried to register a blank flag"); + return false; + } + + /* We only support up to 6 custom flags for SourceMod */ + if (m_flags.size() >= 6) + { + g_pSM->LogError(myself, "BAT AdminInterface support reached maximum number of custom flags"); + return false; + } + + List::iterator iter; + for (iter=m_flags.begin(); iter!=m_flags.end(); iter++) + { + CustomFlag &cf = (*iter); + /* Ignore already registered, in case plugin is reloading */ + if (cf.name.compare(Flag) == 0) + { + return true; + } + } + + g_pSM->LogMessage(myself, + "BAT AdminInterface support registered Admin_Custom%d (class \"%s\") (flag \"%s\") (descr \"%s\")", + m_flags.size() + 1, + Class, + Flag, + Description); + + unsigned int f = (unsigned int)Admin_Custom1; + f += m_flags.size(); + + CustomFlag cf; + cf.bit = (1<GetGamePlayer(id); + + if (!pPlayer) + { + return false; + } + + if (!pPlayer->IsConnected()) + { + return false; + } + + if (pPlayer->IsFakeClient()) + { + return false; + } + + return true; +} + +void BatSupport::AddEventListner(AdminInterfaceListner *ptr) +{ + m_hooks.push_back(ptr); +} + +void BatSupport::RemoveListner(AdminInterfaceListner *ptr) +{ + m_hooks.remove(ptr); +} + +bool BatSupport::HasFlag(int id,const char *Flag) +{ + IGamePlayer *pPlayer = players->GetGamePlayer(id); + + if (!pPlayer || !pPlayer->IsConnected()) + { + return false; + } + + AdminId admin = pPlayer->GetAdminId(); + if (admin == INVALID_ADMIN_ID) + { + return false; + } + + FlagBits bits = admins->GetAdminFlags(admin, Access_Effective); + + /* Root has it all... except for immunity */ + if ((strcmp(Flag, "immunity") != 0) + && ((bits & ADMFLAG_ROOT) == ADMFLAG_ROOT)) + { + return true; + } + + if (!strcmp(Flag, "any")) + { + return ((bits & ~ADMFLAG_RESERVATION) != 0); + } else if (!strcmp(Flag, "kick")) { + return ((bits & ADMFLAG_KICK) == ADMFLAG_KICK); + } else if (!strcmp(Flag, "slap")) { + return ((bits & ADMFLAG_SLAY) == ADMFLAG_SLAY); + } else if (!strcmp(Flag, "slay")) { + return ((bits & ADMFLAG_SLAY) == ADMFLAG_SLAY); + } else if (!strcmp(Flag, "ban")) { + return ((bits & ADMFLAG_BAN) == ADMFLAG_BAN); + } else if (!strcmp(Flag, "chat")) { + return ((bits & ADMFLAG_CHAT) == ADMFLAG_CHAT); + } else if (!strcmp(Flag, "rcon")) { + return ((bits & ADMFLAG_RCON) == ADMFLAG_RCON); + } else if (!strcmp(Flag, "map")) { + return ((bits & ADMFLAG_CHANGEMAP) == ADMFLAG_CHANGEMAP); + } else if (!strcmp(Flag, "reservedslots")) { + return ((bits & ADMFLAG_RESERVATION) == ADMFLAG_RESERVATION); + } else if (!strcmp(Flag, "immunuty")) { + /* This is a bit different... */ + unsigned int count = admins->GetAdminGroupCount(admin); + for (unsigned int i=0; iGetAdminGroup(admin, i, NULL); + if (admins->GetGroupGenericImmunity(gid, Immunity_Default) + || admins->GetGroupGenericImmunity(gid, Immunity_Global)) + { + return true; + } + } + return false; + } + + List::iterator iter; + for (iter=m_flags.begin(); iter!=m_flags.end(); iter++) + { + CustomFlag &cf = (*iter); + if (cf.name.compare(Flag) == 0) + { + return ((bits & cf.bit) == cf.bit); + } + } + + return false; +} diff --git a/extensions/batsupport/extension.h b/extensions/batsupport/extension.h new file mode 100644 index 00000000..ce234f0a --- /dev/null +++ b/extensions/batsupport/extension.h @@ -0,0 +1,46 @@ +// vim: set ts=4 : +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ + +#include "smsdk_ext.h" +#include "BATInterface.h" +#include +#include + +using namespace SourceHook; + +struct CustomFlag +{ + String name; + AdminFlag flag; + FlagBits bit; +}; + +class BatSupport : + public SDKExtension, + public IMetamodListener, + public AdminInterface, + public IClientListener +{ +public: //SDKExtension + bool SDK_OnLoad(char *error, size_t err_max, bool late); + void SDK_OnUnload(); + bool SDK_OnMetamodLoad(char *error, size_t err_max, bool late); +public: //IMetamodListener + void *OnMetamodQuery(const char *iface, int *ret); +public: //AdminInterface + bool RegisterFlag(const char *Class,const char *Flag,const char *Description); + bool IsClient(int id); + bool HasFlag(int id,const char *Flag); + int GetInterfaceVersion(); + const char* GetModName(); + void AddEventListner(AdminInterfaceListner *ptr); + void RemoveListner(AdminInterfaceListner *ptr); +public: //IClientListener + void OnClientAuthorized(int client, const char *authstring); +private: + List m_hooks; + List m_flags; +}; + +#endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/batsupport/msvc8/batsupport.sln b/extensions/batsupport/msvc8/batsupport.sln new file mode 100644 index 00000000..6f8ed540 --- /dev/null +++ b/extensions/batsupport/msvc8/batsupport.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BatSupport", "BatSupport.vcproj", "{B3E797CF-4E77-4C9D-B8A8-7589B6902206}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.ActiveCfg = Debug|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.Build.0 = Debug|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.ActiveCfg = Release|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/extensions/batsupport/msvc8/batsupport.vcproj b/extensions/batsupport/msvc8/batsupport.vcproj new file mode 100644 index 00000000..43e91d83 --- /dev/null +++ b/extensions/batsupport/msvc8/batsupport.vcproj @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/batsupport/smsdk_config.h b/extensions/batsupport/smsdk_config.h new file mode 100644 index 00000000..0454a055 --- /dev/null +++ b/extensions/batsupport/smsdk_config.h @@ -0,0 +1,33 @@ +// vim: set ts=4 : +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ + +/** + * @file smsdk_config.h + * @brief Contains macros for configuring basic extension information. + */ + +/* Basic information exposed publically */ +#define SMEXT_CONF_NAME "BAT Support" +#define SMEXT_CONF_DESCRIPTION "Adds support for BAT's AdminInterface" +#define SMEXT_CONF_VERSION "1.0.0.0" +#define SMEXT_CONF_AUTHOR "AlliedModders" +#define SMEXT_CONF_URL "http://www.sourcemod.net/" +#define SMEXT_CONF_LOGTAG "BATSUPPORT" +#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. + * NOTE: This is enabled automatically if a Metamod build is chosen in + * the Visual Studio project. + */ +#define SMEXT_CONF_METAMOD + +#endif //_INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ diff --git a/extensions/batsupport/smsdk_ext.cpp b/extensions/batsupport/smsdk_ext.cpp new file mode 100644 index 00000000..2e060a7f --- /dev/null +++ b/extensions/batsupport/smsdk_ext.cpp @@ -0,0 +1,333 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. + * All rights reserved. + * =============================================================== + * + * This file is part of the SourceMod/SourcePawn SDK. This file may only be used + * or modified under the Terms and Conditions of its License Agreement, which is found + * in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins + * may change at any time. To view the latest information, see: + * http://www.sourcemod.net/license.php + * + * Version: $Id$ + */ + +#include +#include +#include "smsdk_ext.h" + +/** + * @file smsdk_ext.cpp + * @brief Contains wrappers for making Extensions easier to write. + */ + +IShareSys *g_pShareSys = NULL; /**< Share system */ +IExtension *myself = NULL; /**< Ourself */ +IHandleSys *g_pHandleSys = NULL; /**< Handle system */ +ISourceMod *g_pSM = NULL; /**< SourceMod helpers */ +IForwardManager *g_pForwards = NULL; /**< Forward system */ + +/** 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 err_max, bool late) +{ + g_pShareSys = sys; + myself = me; + +#if defined SMEXT_CONF_METAMOD + m_WeAreUnloaded = true; + + if (!m_SourceMMLoaded) + { + if (error) + { + snprintf(error, err_max, "Metamod attach failed"); + } + return false; + } +#endif + + SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys); + SM_GET_IFACE(SOURCEMOD, g_pSM); + SM_GET_IFACE(FORWARDMANAGER, g_pForwards); + + if (SDK_OnLoad(error, err_max, 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 err_max, 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, PLAPI_NAME)) + { + if (code) + { + *code = IFACE_OK; + } + return static_cast(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(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); + GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); + + m_SourceMMLoaded = true; + + return SDK_OnMetamodLoad(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(char *error, size_t err_max, bool late) +{ + return true; +} + +bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t err_max) +{ + return true; +} + +bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max) +{ + 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 + diff --git a/extensions/batsupport/smsdk_ext.h b/extensions/batsupport/smsdk_ext.h new file mode 100644 index 00000000..8d23c32e --- /dev/null +++ b/extensions/batsupport/smsdk_ext.h @@ -0,0 +1,196 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. + * All rights reserved. + * =============================================================== + * + * This file is part of the SourceMod/SourcePawn SDK. This file may only be used + * or modified under the Terms and Conditions of its License Agreement, which is found + * in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins + * may change at any time. To view the latest information, see: + * 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 +#include +#include +#include +#include +#include + +#if defined SMEXT_CONF_METAMOD +#include +#include +#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 err_max 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 err_max, 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 err_max 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(char *error, size_t err_max, 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 err_max Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodUnload(char *error, size_t err_max); + + /** + * @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 err_max Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max); +#endif + +public: //IExtensionInterface + virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, 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 maxlen); + /** Called on pause */ + virtual bool Pause(char *error, size_t maxlen); + /** Called on unpause */ + virtual bool Unpause(char *error, size_t maxlen); +private: + bool m_SourceMMLoaded; + bool m_WeAreUnloaded; + bool m_WeGotPauseChange; +#endif +}; + +extern SDKExtension *g_pExtensionIface; + +extern IShareSys *g_pShareSys; +extern IExtension *myself; +extern IHandleSys *g_pHandleSys; +extern ISourceMod *g_pSM; +extern IForwardManager *g_pForwards; + +#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) { \ + snprintf(error, err_max, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \ + } \ + return false; \ + } + +#endif //_INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_