diff --git a/core/interfaces/IExtensionSys.h b/core/interfaces/IExtensionSys.h index 7dd23455..16f25474 100644 --- a/core/interfaces/IExtensionSys.h +++ b/core/interfaces/IExtensionSys.h @@ -14,6 +14,11 @@ namespace SourceMod class IExtension { public: + /** + * @brief Returns whether or not the extension is properly loaded. + */ + virtual bool IsLoaded() =0; + /** * @brief Returns the extension's API interface * @@ -128,7 +133,7 @@ namespace SourceMod * @param err_max Maximum error buffer length. * @return New IExtension on success, NULL on failure. */ - virtual IExtension *LoadModule(const char *path, + virtual IExtension *LoadExtension(const char *path, ExtensionLifetime lifetime, char *error, size_t err_max) =0; @@ -158,7 +163,7 @@ namespace SourceMod * @param pExt IExtension pointer. * @return True if successful, false otherwise. */ - virtual bool UnloadModule(IExtension *pExt) =0; + virtual bool UnloadExtension(IExtension *pExt) =0; }; }; diff --git a/core/systems/ExtensionSys.cpp b/core/systems/ExtensionSys.cpp new file mode 100644 index 00000000..f7287315 --- /dev/null +++ b/core/systems/ExtensionSys.cpp @@ -0,0 +1,222 @@ +#include "ExtensionSys.h" +#include "LibrarySys.h" +#include "ShareSys.h" +#include "CLogger.h" + +CExtensionManager g_Extensions; +IdentityType_t g_ExtType; + +CExtension::CExtension(const char *filename, char *error, size_t err_max) +{ + m_File.assign(filename); + m_pAPI = NULL; + m_pIdentToken = NULL; + + char path[PLATFORM_MAX_PATH+1]; + g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename); + + m_pLib = g_LibSys.OpenLibrary(path, error, err_max); + + if (m_pLib == NULL) + { + return; + } + + typedef IExtensionInterface *(*GETAPI)(); + GETAPI pfnGetAPI = NULL; + + if ((pfnGetAPI=(GETAPI)m_pLib->GetSymbolAddress("GetSMExtAPI")) == NULL) + { + m_pLib->CloseLibrary(); + m_pLib = NULL; + snprintf(error, err_max, "Unable to find extension entry point"); + return; + } + + m_pAPI = pfnGetAPI(); + if (!m_pAPI || m_pAPI->GetExtensionVersion() > SMINTERFACE_EXTENSIONAPI_VERSION) + { + m_pLib->CloseLibrary(); + m_pLib = NULL; + snprintf(error, err_max, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION); + return; + } + + if (m_pAPI->IsMetamodExtension()) + { + /* :TODO: STUFF */ + } + + m_pIdentToken = g_ShareSys.CreateIdentity(g_ExtType); + + if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, err_max, g_SourceMod.IsLateLoadInMap())) + { + if (m_pAPI->IsMetamodExtension()) + { + /* :TODO: stuff */ + } + m_pAPI = NULL; + m_pLib->CloseLibrary(); + m_pLib = NULL; + g_ShareSys.DestroyIdentity(m_pIdentToken); + m_pIdentToken = NULL; + return; + } +} + +CExtension::~CExtension() +{ + if (m_pAPI) + { + m_pAPI->OnExtensionUnload(); + } + + if (m_pIdentToken) + { + g_ShareSys.DestroyIdentity(m_pIdentToken); + } + + if (m_pLib) + { + m_pLib->CloseLibrary(); + } +} + +void CExtension::SetError(const char *error) +{ + m_Error.assign(error); +} + +IExtensionInterface *CExtension::GetAPI() +{ + return m_pAPI; +} + +const char *CExtension::GetFilename() +{ + return m_File.c_str(); +} + +IdentityToken_t *CExtension::GetIdentity() +{ + return m_pIdentToken; +} + +bool CExtension::IsLoaded() +{ + return (m_pLib != NULL); +} + +void CExtensionManager::OnSourceModAllInitialized() +{ + g_ExtType = g_ShareSys.CreateIdentType("EXTENSION"); +} + +void CExtensionManager::OnSourceModShutdown() +{ + g_ShareSys.DestroyIdentType(g_ExtType); +} + +IExtension *CExtensionManager::LoadAutoExtension(const char *path) +{ + char error[256]; + CExtension *p = new CExtension(path, error, sizeof(error)); + + if (!p->IsLoaded()) + { + g_Logger.LogError("[SOURCEMOD] Unable to load extension \"%s\": %s", path, error); + p->SetError(error); + } + + m_Libs.push_back(p); + + return p; +} + +IExtension *CExtensionManager::FindExtensionByFile(const char *file) +{ + List::iterator iter; + CExtension *pExt; + + /* Make sure the file direction is right */ + char path[PLATFORM_MAX_PATH+1]; + g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file); + + for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + { + pExt = (*iter); + if (strcmp(pExt->GetFilename(), path) == 0) + { + return pExt; + } + } + + return NULL; +} + +IExtension *CExtensionManager::FindExtensionByName(const char *ext) +{ + List::iterator iter; + CExtension *pExt; + IExtensionInterface *pAPI; + const char *name; + + for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + { + pExt = (*iter); + if (!pExt->IsLoaded()) + { + continue; + } + if ((pAPI = pExt->GetAPI()) == NULL) + { + continue; + } + name = pAPI->GetExtensionName(); + if (!name) + { + continue; + } + if (strcmp(name, ext) == 0) + { + return pExt; + } + } + + return NULL; +} + +IExtension *CExtensionManager::LoadExtension(const char *file, ExtensionLifetime lifetime, char *error, size_t err_max) +{ + CExtension *pExt = new CExtension(file, error, err_max); + + /* :NOTE: lifetime is currently ignored */ + + if (!pExt->IsLoaded()) + { + delete pExt; + return NULL; + } + + m_Libs.push_back(pExt); + + return pExt; +} + +bool CExtensionManager::UnloadExtension(IExtension *pExt) +{ + /* :TODO: implement */ + return true; +} + +unsigned int CExtensionManager::NumberOfPluginDependents(IExtension *pExt, unsigned int *optional) +{ + /* :TODO: implement */ + return 0; +} + +bool CExtensionManager::IsExtensionUnloadable(IExtension *pExtension) +{ + /* :TODO: implement */ + return true; +} diff --git a/core/systems/ExtensionSys.h b/core/systems/ExtensionSys.h new file mode 100644 index 00000000..8d7a69cf --- /dev/null +++ b/core/systems/ExtensionSys.h @@ -0,0 +1,58 @@ +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_SYSTEM_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_SYSTEM_H_ + +#include +#include +#include +#include +#include "sm_globals.h" + +using namespace SourceMod; +using namespace SourceHook; + +class CExtension : public IExtension +{ +public: + CExtension(const char *filename, char *error, size_t maxlen); + ~CExtension(); +public: //IExtension + IExtensionInterface *GetAPI(); + const char *GetFilename(); + IdentityToken_t *GetIdentity(); + bool IsLoaded(); +public: + void SetError(const char *error); +private: + IdentityToken_t *m_pIdentToken; + IExtensionInterface *m_pAPI; + String m_File; + ILibrary *m_pLib; + String m_Error; +}; + +class CExtensionManager : + public IExtensionManager, + public SMGlobalClass +{ +public: //SMGlobalClass + void OnSourceModAllInitialized(); + void OnSourceModShutdown(); +public: //IExtensionManager + IExtension *LoadExtension(const char *path, + ExtensionLifetime lifetime, + char *error, + size_t err_max); + unsigned int NumberOfPluginDependents(IExtension *pExt, unsigned int *optional); + bool IsExtensionUnloadable(IExtension *pExtension); + bool UnloadExtension(IExtension *pExt); + IExtension *FindExtensionByFile(const char *file); + IExtension *FindExtensionByName(const char *ext); +public: + IExtension *LoadAutoExtension(const char *path); +private: + List m_Libs; +}; + +extern CExtensionManager g_Extensions; + +#endif //_INCLUDE_SOURCEMOD_EXTENSION_SYSTEM_H_ diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index d7f3bb07..627c4f9a 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -7,6 +7,7 @@ #include "sourcemod.h" #include "CTextParsers.h" #include "CLogger.h" +#include "ExtensionSys.h" CPluginManager g_PluginSys; HandleType_t g_PluginType = 0; @@ -31,6 +32,16 @@ CPlugin::CPlugin(const char *file) CPlugin::~CPlugin() { + if (m_handle) + { + HandleSecurity sec; + sec.pOwner = g_PluginSys.GetIdentity(); + sec.pIdentity = sec.pOwner; + + g_HandleSys.FreeHandle(m_handle, &sec); + g_ShareSys.DestroyIdentity(m_ident); + } + if (m_ctx.base) { delete m_ctx.base; @@ -72,16 +83,6 @@ CPlugin::~CPlugin() g_pSourcePawn->FreeFromMemory(m_plugin); m_plugin = NULL; } - - if (m_handle) - { - HandleSecurity sec; - sec.pOwner = g_PluginSys.GetIdentity(); - sec.pIdentity = sec.pOwner; - - g_HandleSys.FreeHandle(m_handle, &sec); - g_ShareSys.DestroyIdentity(m_ident); - } } void CPlugin::InitIdentity() @@ -100,18 +101,16 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength) g_LibSys.PathFormat(fullpath, sizeof(fullpath), "%s/plugins/%s", g_SourceMod.GetSMBaseDir(), file); FILE *fp = fopen(fullpath, "rb"); + CPlugin *pPlugin = new CPlugin(file); + if (!fp) { if (error) { snprintf(error, maxlength, "Unable to open file"); - return NULL; - } else { - CPlugin *pPlugin = new CPlugin(file); - snprintf(pPlugin->m_errormsg, sizeof(pPlugin->m_errormsg), "Unable to open file"); - pPlugin->m_status = Plugin_BadLoad; - return pPlugin; } + pPlugin->m_status = Plugin_BadLoad; + return pPlugin; } int err; @@ -122,19 +121,15 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength) if (error) { snprintf(error, maxlength, "Error %d while parsing plugin", err); - return NULL; - } else { - CPlugin *pPlugin = new CPlugin(file); - snprintf(pPlugin->m_errormsg, sizeof(pPlugin->m_errormsg), "Error %d while parsing plugin", err); - pPlugin->m_status = Plugin_BadLoad; - return pPlugin; } + pPlugin->m_status = Plugin_BadLoad; + return pPlugin; } fclose(fp); - CPlugin *pPlugin = new CPlugin(file); pPlugin->m_plugin = pl; + return pPlugin; } @@ -185,10 +180,8 @@ bool CPlugin::FinishMyCompile(char *error, size_t maxlength) if (!m_ctx.ctx) { memset(&m_ctx, 0, sizeof(m_ctx)); - if (!error) + if (error) { - SetErrorState(Plugin_Failed, "Failed to compile (error %d)", err); - } else { snprintf(error, maxlength, "Failed to compile (error %d)", err); } return false; @@ -377,12 +370,6 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength) return false; } - if (!error) - { - error = m_errormsg; - maxlength = sizeof(m_errormsg); - } - m_status = Plugin_Loaded; int err; @@ -676,20 +663,20 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa //well i have discovered that gabe newell is very fat, so i wrote this comment now //:TODO: remove this function, create a better wrapper for LoadPlugin()/LoadAutoPlugin() -void CPluginManager::LoadAutoPlugin(const char *file) +bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug, PluginType type, char error[], size_t err_max) { /** * Does this plugin already exist? */ CPlugin *pPlugin; - if (sm_trie_retrieve(m_LoadLookup, file, (void **)&pPlugin)) + if (sm_trie_retrieve(m_LoadLookup, path, (void **)&pPlugin)) { /* First check the type */ PluginType type = pPlugin->GetType(); if (type == PluginType_Private || type == PluginType_Global) { - return; + return true; } /* Check to see if we should try reloading it */ if (pPlugin->GetStatus() == Plugin_BadLoad @@ -700,7 +687,7 @@ void CPluginManager::LoadAutoPlugin(const char *file) } } - pPlugin = CPlugin::CreatePlugin(file, NULL, 0); + pPlugin = CPlugin::CreatePlugin(path, error, err_max); assert(pPlugin != NULL); @@ -717,8 +704,7 @@ void CPluginManager::LoadAutoPlugin(const char *file) unsigned int setcount = m_PluginInfo.GetSettingsNum(); for (unsigned int i=0; iSetCompilationOption(co, key, val)) { - pPlugin->SetErrorState(Plugin_Failed, "Unable to set option (key \"%s\") (value \"%s\")", key, val); + if (error) + { + snprintf(error, err_max, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val); + } pPlugin->CancelMyCompile(); + pPlugin->m_status = Plugin_Failed; co = NULL; break; } @@ -744,100 +734,71 @@ void CPluginManager::LoadAutoPlugin(const char *file) } } + /* Do the actual compiling */ if (co) { pPlugin->FinishMyCompile(NULL, 0); co = NULL; } - /* We don't care about the return value */ + /* Get the status */ if (pPlugin->GetStatus() == Plugin_Created) { AddCoreNativesToPlugin(pPlugin); pPlugin->InitIdentity(); - pPlugin->Call_AskPluginLoad(NULL, 0); + pPlugin->Call_AskPluginLoad(error, err_max); } - AddPlugin(pPlugin); + if (_plugin) + { + *_plugin = pPlugin; + } + + return (pPlugin->GetStatus() == Plugin_Loaded); } IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t err_max) { - /* See if this plugin is already loaded... reformat to get sep chars right */ - char checkpath[PLATFORM_MAX_PATH+1]; - g_LibSys.PathFormat(checkpath, sizeof(checkpath), "%s", path); + CPlugin *pl; - /** - * In manually loading a plugin, any sort of load error causes a deletion. - * This is because it's assumed manually loaded plugins will not be managed. - * For managed plugins, we need the UI to report them properly. - */ - - CPlugin *pPlugin; - if (sm_trie_retrieve(m_LoadLookup, checkpath, (void **)&pPlugin)) + if (!_LoadPlugin(&pl, path, debug, type, error, err_max)) { - snprintf(error, err_max, "Plugin file is already loaded"); + delete pl; return NULL; } - pPlugin = CPlugin::CreatePlugin(path, error, err_max); + AddPlugin(pl); - if (!pPlugin) + return pl; +} + +void CPluginManager::LoadAutoPlugin(const char *plugin) +{ + CPlugin *pl; + char error[255] = "Unknown error"; + + if (!_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) { - return NULL; + g_Logger.LogError("[SOURCEMOD] Failed to load plugin \"%s\": %s", plugin, error); + pl->SetErrorState(Plugin_Failed, "%s", error); } - ICompilation *co = pPlugin->StartMyCompile(g_pVM); - if (!co || (debug && !g_pVM->SetCompilationOption(co, "debug", "1"))) - { - snprintf(error, err_max, "Unable to start%s compilation", debug ? " debug" : ""); - pPlugin->CancelMyCompile(); - delete pPlugin; - return NULL; - } - - if (!pPlugin->FinishMyCompile(error, err_max)) - { - delete pPlugin; - return NULL; - } - - pPlugin->m_type = type; - - AddCoreNativesToPlugin(pPlugin); - - pPlugin->InitIdentity(); - - /* Finally, ask the plugin if it wants to be loaded */ - if (!pPlugin->Call_AskPluginLoad(error, err_max)) - { - delete pPlugin; - return NULL; - } - - AddPlugin(pPlugin); - - return pPlugin; + AddPlugin(pl); } void CPluginManager::AddPlugin(CPlugin *pPlugin) { - m_plugins.push_back(pPlugin); - sm_trie_insert(m_LoadLookup, pPlugin->m_filename, pPlugin); - List::iterator iter; IPluginsListener *pListener; + for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++) { pListener = (*iter); pListener->OnPluginCreated(pPlugin); } - /* If the second pass was already completed, we have to run the pass on this plugin */ - if (m_AllPluginsLoaded && pPlugin->GetStatus() == Plugin_Loaded) - { - RunSecondPass(pPlugin); - } + m_plugins.push_back(pPlugin); + sm_trie_insert(m_LoadLookup, pPlugin->m_filename, pPlugin); } void CPluginManager::LoadAll_SecondPass() @@ -850,16 +811,77 @@ void CPluginManager::LoadAll_SecondPass() pPlugin = (*iter); if (pPlugin->GetStatus() == Plugin_Loaded) { - RunSecondPass(pPlugin); + /* :TODO: fix */ + RunSecondPass(pPlugin, NULL, 0); } } + m_AllPluginsLoaded = true; } -void CPluginManager::RunSecondPass(CPlugin *pPlugin) +bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength) { - /* Tell this plugin to finish initializing itself */ - pPlugin->Call_OnPluginInit(); + /* Find any extensions this plugin needs */ + struct _ext + { + cell_t name; + cell_t file; + cell_t autoload; + cell_t required; + } *ext; + + IPluginContext *pBase = pPlugin->GetBaseContext(); + uint32_t num = pBase->GetPubVarsNum(); + sp_pubvar_t *pubvar; + IExtension *pExt; + char path[PLATFORM_MAX_PATH+1]; + char *file, *name; + for (uint32_t i=0; iGetPubvarByIndex(i, &pubvar) != SP_ERROR_NONE) + { + continue; + } + if (strncmp(pubvar->name, "__ext_", 6) == 0) + { + ext = (_ext *)pubvar->offs; + if (!ext->required && !ext->autoload) + { + continue; + } + if (pBase->LocalToString(ext->file, &file) != SP_ERROR_NONE) + { + continue; + } + if (pBase->LocalToString(ext->name, &name) != SP_ERROR_NONE) + { + continue; + } + snprintf(path, PLATFORM_MAX_PATH, "%s.%s", file, PLATFORM_LIB_EXT); + pExt = NULL; + /* Attempt to auto-load if necessary */ + if (ext->autoload) + { + pExt = g_Extensions.LoadAutoExtension(path); + } + if (ext->required && !pExt) + { + if ((pExt = g_Extensions.FindExtensionByFile(path)) == NULL) + { + pExt = g_Extensions.FindExtensionByName(name); + } + } + if (ext->required && (!pExt || !pExt->IsLoaded())) + { + if (error) + { + snprintf(error, maxlength, "Required extension \"%s\" (file \"%s\") not found", name, file); + } + pPlugin->m_status = Plugin_Failed; + return false; + } + } + } /* Finish by telling all listeners */ List::iterator iter; @@ -869,6 +891,11 @@ void CPluginManager::RunSecondPass(CPlugin *pPlugin) pListener = (*iter); pListener->OnPluginLoaded(pPlugin); } + + /* Tell this plugin to finish initializing itself */ + pPlugin->Call_OnPluginInit(); + + return true; } void CPluginManager::AddCoreNativesToPlugin(CPlugin *pPlugin) @@ -891,6 +918,13 @@ void CPluginManager::AddCoreNativesToPlugin(CPlugin *pPlugin) bool CPluginManager::UnloadPlugin(IPlugin *plugin) { CPlugin *pPlugin = (CPlugin *)plugin; + + /* This prevents removal during insertion or anything else weird */ + if (m_plugins.find(pPlugin) == m_plugins.end()) + { + return false; + } + List::iterator iter; IPluginsListener *pListener; @@ -1215,6 +1249,12 @@ void CPluginManager::OnSourceModAllInitialized() void CPluginManager::OnSourceModShutdown() { + List::iterator iter; + while ( (iter = m_plugins.begin()) != m_plugins.end() ) + { + UnloadPlugin((*iter)); + } + g_HandleSys.RemoveType(g_PluginType, m_MyIdent); g_ShareSys.DestroyIdentType(g_PluginIdent); g_ShareSys.DestroyIdentity(m_MyIdent); @@ -1270,4 +1310,4 @@ CPlugin *CPluginManager::GetPluginByOrder(int num) iter->Release(); return pl; -} \ No newline at end of file +} diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h index 5a585655..83c11f7a 100644 --- a/core/systems/PluginSys.h +++ b/core/systems/PluginSys.h @@ -269,17 +269,15 @@ public: */ CPlugin *GetPluginByOrder(int num); private: + bool _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t err_max); + + void LoadAutoPlugin(const char *plugin); + /** * Recursively loads all plugins in the given directory. */ void LoadPluginsFromDir(const char *basedir, const char *localdir); - /** - * Loads a plugin using automatic information. - * The file must be relative to the plugins folder. - */ - void LoadAutoPlugin(const char *file); - /** * Adds a plugin object. This is wrapped by LoadPlugin functions. */ @@ -288,7 +286,7 @@ private: /** * Runs the second loading pass on a plugin. */ - void RunSecondPass(CPlugin *pPlugin); + bool RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength); /** * Adds any globally registered natives to a plugin diff --git a/extensions/sdk/extension.cpp b/extensions/sdk/extension.cpp new file mode 100644 index 00000000..9065e47d --- /dev/null +++ b/extensions/sdk/extension.cpp @@ -0,0 +1,5 @@ +#include "extension.h" + +Sample g_Sample; + +SMEXT_LINK(&g_Sample); diff --git a/extensions/sdk/extension.h b/extensions/sdk/extension.h new file mode 100644 index 00000000..d93261e1 --- /dev/null +++ b/extensions/sdk/extension.h @@ -0,0 +1,49 @@ +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ + +#include "smsdk_ext.h" + +/** + * @brief Sample implementation of the SDK Extension. + * Note: Uncomment one of the pre-defined virtual functions in order to use it. + */ +class Sample : public 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); +public: +#if defined SMEXT_CONF_METAMOD + /** + * Read smext_base.h for documentation on these. + */ + + //virtual bool SDK_OnMetamodLoad(char *error, size_t err_max, bool late); + //virtual bool SDK_OnMetamodUnload(char *error, size_t err_max); + //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max); +#endif +}; + +#endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/sdk/sdk.sln b/extensions/sdk/sdk.sln new file mode 100644 index 00000000..99656471 --- /dev/null +++ b/extensions/sdk/sdk.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk", "sdk.vcproj", "{B3E797CF-4E77-4C9D-B8A8-7589B6902206}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug - Metamod|Win32 = Debug - Metamod|Win32 + Debug|Win32 = Debug|Win32 + Release - Metamod|Win32 = Release - Metamod|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug - Metamod|Win32.ActiveCfg = Debug - Metamod|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug - Metamod|Win32.Build.0 = Debug - Metamod|Win32 + {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 - Metamod|Win32.ActiveCfg = Release - Metamod|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release - Metamod|Win32.Build.0 = Release - Metamod|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/sdk/sdk.vcproj b/extensions/sdk/sdk.vcproj new file mode 100644 index 00000000..d4ccdd57 --- /dev/null +++ b/extensions/sdk/sdk.vcproj @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/include/core.inc b/plugins/include/core.inc new file mode 100644 index 00000000..03678840 --- /dev/null +++ b/plugins/include/core.inc @@ -0,0 +1,27 @@ +#if defined _core_included + #endinput +#endif +#define _core_included + +#define SOURCEMOD_PLUGINAPI_VERSION 1 +struct PlVers +{ + version, +}; + +public PlVers:__version = +{ + version = SOURCEMOD_PLUGINAPI_VERSION, +}; + +struct Extension +{ + const String:name[], /* Short name */ + const String:file[], /* Default file name */ + bool:autoload, /* Whether or not to auto-load */ + bool:required, /* Whether or not to require */ +}; + +#define AUTOLOAD_EXTENSIONS +#define REQUIRE_EXTENSIONS + diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index 70877e73..b942d78f 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -16,10 +16,10 @@ struct Plugin const String:url[], /* Plugin URL */ }; +#include #include #include #include -#include /** * Declare this as a struct in your plugin to expose its information.