From ffb560abea631f2a86bed5ea7f5df6c250a93f06 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 7 Oct 2007 03:12:19 +0000 Subject: [PATCH] initial import of unfinished new sample plugin this one is more based on valve's sample... --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40464 --- sample_mm/engine_wrappers.h | 44 ++++ sample_mm/msvc8/sample_mm.sln | 26 +++ sample_mm/msvc8/sample_mm.vcproj | 367 +++++++++++++++++++++++++++++++ sample_mm/sample_mm.cpp | 329 +++++++++++++++++++++++++++ sample_mm/sample_mm.h | 78 +++++++ 5 files changed, 844 insertions(+) create mode 100644 sample_mm/engine_wrappers.h create mode 100644 sample_mm/msvc8/sample_mm.sln create mode 100644 sample_mm/msvc8/sample_mm.vcproj create mode 100644 sample_mm/sample_mm.cpp create mode 100644 sample_mm/sample_mm.h diff --git a/sample_mm/engine_wrappers.h b/sample_mm/engine_wrappers.h new file mode 100644 index 0000000..05b6ee5 --- /dev/null +++ b/sample_mm/engine_wrappers.h @@ -0,0 +1,44 @@ +/** + * vim: set ts=4 : + * ====================================================== + * Metamod:Source Sample Plugin + * Written by AlliedModders LLC. + * ====================================================== + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * This sample plugin is public domain. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCE_ENGINE_WRAPPERS_ +#define _INCLUDE_SOURCE_ENGINE_WRAPPERS_ + +#include + +extern IVEngineServer *engine; + +#if !defined ORANGEBOX_BUILD +class CCommand +{ +public: + const char *ArgS() + { + return engine->Cmd_Args(); + } + int ArgC() + { + return engine->Cmd_Argc(); + } + + const char *Arg(int index) + { + return engine->Cmd_Argv(index); + } +}; +#endif + +#endif //_INCLUDE_SOURCE_ENGINE_WRAPPERS_ diff --git a/sample_mm/msvc8/sample_mm.sln b/sample_mm/msvc8/sample_mm.sln new file mode 100644 index 0000000..37c4ebc --- /dev/null +++ b/sample_mm/msvc8/sample_mm.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample plugin", "sample_mm.vcproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug - Orange Box|Win32 = Debug - Orange Box|Win32 + Debug|Win32 = Debug|Win32 + Release - Orange Box|Win32 = Release - Orange Box|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug|Win32.Build.0 = Debug|Win32 + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release|Win32.ActiveCfg = Release|Win32 + {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/sample_mm/msvc8/sample_mm.vcproj b/sample_mm/msvc8/sample_mm.vcproj new file mode 100644 index 0000000..e294cbd --- /dev/null +++ b/sample_mm/msvc8/sample_mm.vcproj @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sample_mm/sample_mm.cpp b/sample_mm/sample_mm.cpp new file mode 100644 index 0000000..6178dfa --- /dev/null +++ b/sample_mm/sample_mm.cpp @@ -0,0 +1,329 @@ +/** + * vim: set ts=4 : + * ====================================================== + * Metamod:Source Sample Plugin + * Written by AlliedModders LLC. + * ====================================================== + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * This sample plugin is public domain. + * + * Version: $Id$ + */ + +#include +#include "sample_mm.h" + +SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const *, char const *, char const *, char const *, bool, bool); +SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int); +SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool); +SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0); +SH_DECL_HOOK2_void(IServerGameClients, ClientActive, SH_NOATTRIB, 0, edict_t *, bool); +SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *); +SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, char const *); +SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, 0, int); +SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *); +SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char*, const char *, char *, int); +SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool); + +#if defined ORANGEBOX_BUILD +SH_DECL_HOOK2_void(IServerGameClients, NetworkIDValidated, SH_NOATTRIB, 0, const char *, const char *); +SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &); +#else +SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); +#endif + +StubPlugin g_StubPlugin; +IServerGameDLL *server = NULL; +IServerGameClients *gameclients = NULL; +IVEngineServer *engine = NULL; +IServerPluginHelpers *helpers = NULL; +IGameEventManager2 *gameevents = NULL; +IServerPluginCallbacks *vsp_callbacks = NULL; +IPlayerInfoManager *playerinfomanager = NULL; + +PLUGIN_EXPOSE(StubPlugin, g_StubPlugin); +bool StubPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) +{ + PLUGIN_SAVEVARS(); + + GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); + GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); + GET_V_IFACE_CURRENT(GetEngineFactory, helpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS); + GET_V_IFACE_ANY(GetServerFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); + GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); + GET_V_IFACE_ANY(GetServerFactory, playerinfomanager, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER); + + META_LOG(g_PLAPI, "Starting plugin."); + + /* Load the VSP listener. Most people won't need this. */ + if ((vsp_callbacks = ismm->GetVSPInfo(NULL)) == NULL) + { + ismm->AddListener(this, this); + ismm->EnableVSPListener(); + } + + m_hooks.push_back(SH_ADD_HOOK(IServerGameDLL, LevelInit, server, SH_MEMBER(this, &StubPlugin::Hook_LevelInit), true)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameDLL, ServerActivate, server, SH_MEMBER(this, &StubPlugin::Hook_ServerActivate), true)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameDLL, GameFrame, server, SH_MEMBER(this, &StubPlugin::Hook_GameFrame), true)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameDLL, LevelShutdown, server, SH_MEMBER(this, &StubPlugin::Hook_LevelShutdown), false)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameClients, ClientActive, gameclients, SH_MEMBER(this, &StubPlugin::Hook_ClientActive), true)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameClients, ClientDisconnect, gameclients, SH_MEMBER(this, &StubPlugin::Hook_ClientDisconnect), true)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameClients, ClientPutInServer, gameclients, SH_MEMBER(this, &StubPlugin::Hook_ClientPutInServer), true)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameClients, SetCommandClient, gameclients, SH_MEMBER(this, &StubPlugin::Hook_SetCommandClient), true)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameClients, ClientSettingsChanged, gameclients, SH_MEMBER(this, &StubPlugin::Hook_ClientSettingsChanged), false)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameClients, ClientConnect, gameclients, SH_MEMBER(this, &StubPlugin::Hook_ClientConnect), false)); + m_hooks.push_back(SH_ADD_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &StubPlugin::Hook_ClientCommand), false)); + + SH_CALL(engine, &IVEngineServer::LogPrint)("All hooks started!\n"); + + return true; +} + +bool StubPlugin::Unload(char *error, size_t maxlen) +{ + for (size_t i = 0; i < m_hooks.size(); i++) + { + if (m_hooks[i] != 0) + { + SH_REMOVE_HOOK_ID(m_hooks[i]); + } + } + m_hooks.clear(); + + return true; +} + +void StubPlugin::OnVSPListening(IServerPluginCallbacks *iface) +{ + vsp_callbacks = iface; +} + +void StubPlugin::Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) +{ + META_LOG(g_PLAPI, "ServerActivate() called: edictCount = %d, clientMax = %d", edictCount, clientMax); +} + +void StubPlugin::AllPluginsLoaded() +{ + /* This is where we'd do stuff that relies on the mod or other plugins + * being initialized (for example, cvars added and events registered). + */ +} + +void StubPlugin::Hook_ClientActive(edict_t *pEntity, bool bLoadGame) +{ + META_LOG(g_PLAPI, "Hook_ClientActive(%d, %d)", engine->IndexOfEdict(pEntity), bLoadGame); +} + +#if defined ORANGEBOX_BUILD +void StubPlugin::Hook_ClientCommand(edict_t *pEntity, const CCommand &args) +#else +void StubPlugin::Hook_ClientCommand(edict_t *pEntity) +#endif +{ +#if !defined ORANGEBOX_BUILD + CCommand args; +#endif + + if (!pEntity || !pEntity->IsFree()) + { + return; + } + + const char *cmd = args.Arg(0); + if (strcmp(cmd, "menu") == 0) + { + KeyValues *kv = new KeyValues("menu"); + kv->SetString("title", "You've got options, hit ESC"); + kv->SetInt("level", 1); + kv->SetColor("color", Color(255, 0, 0, 255)); + kv->SetInt("time", 20); + kv->SetString("msg", "Pick an option\nOr don't."); + + for (int i = 1; i < 9; i++) + { + char num[10], msg[10], cmd[10]; + g_SMAPI->Format( num, sizeof(num), "%i", i ); + g_SMAPI->Format( msg, sizeof(msg), "Option %i", i ); + g_SMAPI->Format( cmd, sizeof(cmd), "option %i", i ); + + KeyValues *item1 = kv->FindKey(num, true); + item1->SetString("msg", msg); + item1->SetString("command", cmd); + } + + helpers->CreateMessage(pEntity, DIALOG_MENU, kv, vsp_callbacks); + kv->deleteThis(); + RETURN_META(MRES_SUPERCEDE); + } + else if (strcmp(cmd, "rich") == 0) + { + KeyValues *kv = new KeyValues("menu"); + kv->SetString("title", "A rich message"); + kv->SetInt("level", 1); + kv->SetInt("time", 20); + kv->SetString("msg", "This is a long long long text string.\n\nIt also has line breaks."); + + helpers->CreateMessage(pEntity, DIALOG_TEXT, kv, vsp_callbacks); + kv->deleteThis(); + RETURN_META(MRES_SUPERCEDE); + } + else if (strcmp(cmd, "msg") == 0) + { + KeyValues *kv = new KeyValues("menu"); + kv->SetString("title", "Just a simple hello"); + kv->SetInt("level", 1); + kv->SetInt("time", 20); + + helpers->CreateMessage(pEntity, DIALOG_MSG, kv, vsp_callbacks); + kv->deleteThis(); + RETURN_META(MRES_SUPERCEDE); + } + else if (strcmp(cmd, "entry") == 0) + { + KeyValues *kv = new KeyValues("entry"); + kv->SetString("title", "Stuff"); + kv->SetString("msg", "Enter something"); + kv->SetString("command", "say"); // anything they enter into the dialog turns into a say command + kv->SetInt("level", 1); + kv->SetInt("time", 20); + + helpers->CreateMessage(pEntity, DIALOG_ENTRY, kv, vsp_callbacks); + kv->deleteThis(); + RETURN_META(MRES_SUPERCEDE); + } +} + +void StubPlugin::Hook_ClientSettingsChanged(edict_t *pEdict) +{ + if (playerinfomanager) + { + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo(pEdict); + + const char *name = engine->GetClientConVarValue(engine->IndexOfEdict(pEdict), "name"); + + if (playerinfo != NULL + && name != NULL + && playerinfo->GetName() != NULL + && strcmp(name, playerinfo->GetName()) == 0) + { + char msg[128]; + g_SMAPI->Format(msg, sizeof(msg), "Your name changed to \"%s\" (from \"%s\")\n", name, playerinfo->GetName()); + engine->ClientPrintf(pEdict, msg); + } + } +} + +bool StubPlugin::Hook_ClientConnect(edict_t *pEntity, + const char *pszName, + const char *pszAddress, + char *reject, + int maxrejectlen) +{ + META_LOG(g_PLAPI, "Hook_ClientConnect(%d, \"%s\", \"%s\")", engine->IndexOfEdict(pEntity), pszName, pszAddress); + + return true; +} + +void StubPlugin::Hook_ClientPutInServer(edict_t *pEntity, char const *playername) +{ + KeyValues *kv = new KeyValues( "msg" ); + kv->SetString( "title", "Hello" ); + kv->SetString( "msg", "Hello there" ); + kv->SetColor( "color", Color( 255, 0, 0, 255 )); + kv->SetInt( "level", 5); + kv->SetInt( "time", 10); + helpers->CreateMessage(pEntity, DIALOG_MSG, kv, vsp_callbacks); + kv->deleteThis(); +} + +void StubPlugin::Hook_ClientDisconnect(edict_t *pEntity) +{ + META_LOG(g_PLAPI, "Hook_ClientDisconnect(%d)", engine->IndexOfEdict(pEntity)); +} + +void StubPlugin::Hook_GameFrame(bool simulating) +{ + /** + * simulating: + * *********** + * true | game is ticking + * false | game is not ticking + */ +} + +bool StubPlugin::Hook_LevelInit(const char *pMapName, + char const *pMapEntities, + char const *pOldLevel, + char const *pLandmarkName, + bool loadGame, + bool background) +{ + META_LOG(g_PLAPI, "Hook_LevelInit(%s)", pMapName); + + return true; +} + +void StubPlugin::Hook_LevelShutdown() +{ + META_LOG(g_PLAPI, "Hook_LevelShutdown()"); +} + +void StubPlugin::Hook_SetCommandClient(int index) +{ + META_LOG(g_PLAPI, "Hook_SetCommandClient(%d)", index); +} + +bool StubPlugin::Pause(char *error, size_t maxlen) +{ + return true; +} + +bool StubPlugin::Unpause(char *error, size_t maxlen) +{ + return true; +} + +const char *StubPlugin::GetLicense() +{ + return "Public Domain"; +} + +const char *StubPlugin::GetVersion() +{ + return "1.0.0.0"; +} + +const char *StubPlugin::GetDate() +{ + return __DATE__; +} + +const char *StubPlugin::GetLogTag() +{ + return "SAMPLE"; +} + +const char *StubPlugin::GetAuthor() +{ + return "AlliedModders LLC"; +} + +const char *StubPlugin::GetDescription() +{ + return "Sample basic plugin"; +} + +const char *StubPlugin::GetName() +{ + return "Sample Plugin"; +} + +const char *StubPlugin::GetURL() +{ + return "http://www.sourcemm.net/"; +} diff --git a/sample_mm/sample_mm.h b/sample_mm/sample_mm.h new file mode 100644 index 0000000..4a0c0b9 --- /dev/null +++ b/sample_mm/sample_mm.h @@ -0,0 +1,78 @@ +/** + * vim: set ts=4 : + * ====================================================== + * Metamod:Source Sample Plugin + * Written by AlliedModders LLC. + * ====================================================== + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * This sample plugin is public domain. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ +#define _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ + +#include +#include +#include +#include +#include "engine_wrappers.h" + +class StubPlugin : public ISmmPlugin, public IMetamodListener +{ +public: + bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); + bool Unload(char *error, size_t maxlen); + bool Pause(char *error, size_t maxlen); + bool Unpause(char *error, size_t maxlen); + void AllPluginsLoaded(); +public: //IMetamodListener stuff + void OnVSPListening(IServerPluginCallbacks *iface); +public: //hooks + void Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax); + bool Hook_LevelInit(const char *pMapName, + char const *pMapEntities, + char const *pOldLevel, + char const *pLandmarkName, + bool loadGame, + bool background); + void Hook_GameFrame(bool simulating); + void Hook_LevelShutdown(void); + void Hook_ClientActive(edict_t *pEntity, bool bLoadGame); + void Hook_ClientDisconnect(edict_t *pEntity); + void Hook_ClientPutInServer(edict_t *pEntity, char const *playername); + void Hook_SetCommandClient(int index); + void Hook_ClientSettingsChanged(edict_t *pEdict); + bool Hook_ClientConnect(edict_t *pEntity, + const char *pszName, + const char *pszAddress, + char *reject, + int maxrejectlen); +#if defined ORANGEBOX_BUILD + void Hook_ClientCommand(edict_t *pEntity, const CCommand &args); +#else + void Hook_ClientCommand(edict_t *pEntity); +#endif +public: + const char *GetAuthor(); + const char *GetName(); + const char *GetDescription(); + const char *GetURL(); + const char *GetLicense(); + const char *GetVersion(); + const char *GetDate(); + const char *GetLogTag(); +private: + SourceHook::CVector m_hooks; +}; + +extern StubPlugin g_StubPlugin; + +PLUGIN_GLOBALVARS(); + +#endif //_INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_