From 74171363e9b5fa379107cae295c334c99da4159b Mon Sep 17 00:00:00 2001 From: Monera Date: Sun, 27 Aug 2023 20:52:47 +0900 Subject: [PATCH] initial commit --- README.md | 6 + scripting/ezlul.sp | 184 +++++++++++++++++++++++++ scripting/include/pluginsyswrapper.inc | 73 ++++++++++ 3 files changed, 263 insertions(+) create mode 100644 README.md create mode 100644 scripting/ezlul.sp create mode 100644 scripting/include/pluginsyswrapper.inc diff --git a/README.md b/README.md new file mode 100644 index 0000000..e178575 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# EZ Load UnLoad Plugins + +Easy load unload plugins by using PluginSys Wrapper + +```sm_ezload (string): Load plugins whose path starts with given substring +sm_ezunload (string): Unload plugins whose path starts with given substring``` diff --git a/scripting/ezlul.sp b/scripting/ezlul.sp new file mode 100644 index 0000000..76ebd63 --- /dev/null +++ b/scripting/ezlul.sp @@ -0,0 +1,184 @@ +#include +#include +#include +#include "pluginsyswrapper" + +#pragma newdecls required +#pragma semicolon 1 + +public Plugin myinfo = +{ + name = "EZ Load Unload", + author = "Monera", + description = "Plugin that allows easy load/unload plugins by utilizing pluginsys wrapper", + version = "0.0.1", + url = "" +}; + +Regex pluginExtensionRegex; + +public void OnPluginStart() +{ + pluginExtensionRegex = new Regex("\\.smx$"); + + RegServerCmd("sm_ezload", SvrCmd_EZLoad, "Load plugins whose path starts with given substring"); + RegServerCmd("sm_ezunload", SvrCmd_EZUnload, "Unload plugins whose path starts with given substring"); +} + +public Action SvrCmd_EZLoad(int args) +{ + if(args != 1) + { + PrintToServer("Usage: sm_ezload (string)"); + return Plugin_Handled; + } + + char substring[PLATFORM_MAX_PATH]; + GetCmdArg(1, substring, sizeof(substring)); + + ArrayList list = ListPlugins(substring); + int length = list.Length; + int failure = 0; + for(int i = 0; i < length; i++) + { + char path[PLATFORM_MAX_PATH]; + char err[256]; + bool wasloaded; + + list.GetString(i, path, sizeof(path)); + Handle plugin = LoadPluginEx(path, err, sizeof(err), wasloaded); + + if(plugin == null) + { + PrintToServer("[EZ] Plugin %s failed to load: %s", path, err); + failure += 1; + } + else if(wasloaded) + { + failure += 1; + } + } + + PrintToServer("[EZ] %d plugins are loaded", length - failure); + + return Plugin_Handled; +} + +public Action SvrCmd_EZUnload(int args) +{ + if(args != 1) + { + PrintToServer("Usage: sm_ezunload (string)"); + return Plugin_Handled; + } + + char substring[PLATFORM_MAX_PATH]; + GetCmdArg(1, substring, sizeof(substring)); + + ArrayList list = ListLoadedPlugins(substring); + int length = list.Length; + int failure = 0; + Handle myself = GetMyHandle(); + for(int i = 0; i < length; i++) + { + Handle plugin = list.Get(i); + if(plugin == myself) + { + char path[PLATFORM_MAX_PATH]; + GetPluginFilename(null, path, sizeof(path)); + PrintToServer("[EZ] Plugin %s failed to unload: Unloading itself is not allowed", path); + failure += 1; + continue; + } + UnloadPlugin(list.Get(i)); + } + + PrintToServer("[EZ] %d plugins are unloaded", length - failure); + + return Plugin_Handled; +} + +// BFS +stock ArrayList ListPlugins(const char[] startsWith) +{ + int startsWithLength = strlen(startsWith); + + ArrayList list = new ArrayList(PLATFORM_MAX_PATH / 4); + + char rootPath[PLATFORM_MAX_PATH]; + int rootPos; + rootPos = BuildPath(Path_SM, rootPath, sizeof(rootPath), "plugins"); + + ArrayStack stack = new ArrayStack(PLATFORM_MAX_PATH / 4); + stack.PushString(rootPath); + while(!stack.Empty) + { + char path[PLATFORM_MAX_PATH]; + int pos; + stack.PopString(path, sizeof(path), pos); + + if(pos + 1 == PLATFORM_MAX_PATH) + { + continue; + } + path[pos++] = '/'; + + DirectoryListing directoryListing = OpenDirectory(path); + FileType type; + while(directoryListing.GetNext(path[pos], sizeof(path) - pos, type)) + { + switch(type) + { + case FileType_File: + { + pluginExtensionRegex.Match(path[pos]); + if(!pluginExtensionRegex.MatchCount()) + { + continue; + } + if(strncmp(path[rootPos + 1], startsWith, startsWithLength) != 0) + { + continue; + } + list.PushString(path[rootPos + 1]); + } + case FileType_Directory: + { + if(strcmp(path[pos], ".") != 0 && strcmp(path[pos], "..") != 0) + { + stack.PushString(path); + } + } + } + } + delete directoryListing; + } + delete stack; + + return list; +} + +stock ArrayList ListLoadedPlugins(const char[] startsWith) +{ + int startsWithLength = strlen(startsWith); + + ArrayList list = new ArrayList(); + + Handle it = GetPluginIterator(); + while(MorePlugins(it)) + { + Handle plugin = ReadPlugin(it); + + char path[PLATFORM_MAX_PATH]; + GetPluginFilename(plugin, path, sizeof(path)); + + if(strncmp(path, startsWith, startsWithLength) != 0) + { + continue; + } + list.Push(plugin); + } + delete it; + + return list; +} diff --git a/scripting/include/pluginsyswrapper.inc b/scripting/include/pluginsyswrapper.inc new file mode 100644 index 0000000..026172a --- /dev/null +++ b/scripting/include/pluginsyswrapper.inc @@ -0,0 +1,73 @@ +#if defined _pluginsyswrapper_included_ + #endinput +#endif +#define _pluginsyswrapper_included_ + +public Extension __ext_pluginsyswrapper = +{ + name = "PluginSys Wrapper", + file = "pluginsyswrapper.ext", + autoload = 1, + required = 1, +}; + +enum HandleError +{ + HandleError_None = 0, /**< No error */ + HandleError_Changed, /**< The handle has been freed and reassigned */ + HandleError_Type, /**< The handle has a different type registered */ + HandleError_Freed, /**< The handle has been freed */ + HandleError_Index, /**< generic internal indexing error */ + HandleError_Access, /**< No access permitted to free this handle */ + HandleError_Limit, /**< The limited number of handles has been reached */ + HandleError_Identity, /**< The identity token was not usable */ + HandleError_Owner, /**< Owners do not match for this operation */ + HandleError_Version, /**< Unrecognized security structure version */ + HandleError_Parameter, /**< An invalid parameter was passed */ + HandleError_NoInherit, /**< This type cannot be inherited */ +}; + +/** + * @brief Attempts to load a plugin. + * + * @param path Path and filename of plugin, relative to plugins folder. + * @param error Buffer to hold any error message. + * @param maxlength Maximum length of error message buffer. + * @param wasloaded Stores if the plugin is already loaded. + * @return A new plugin handle on success, null otherwise. + */ +native Handle LoadPluginEx(const char[] path, char[] error, int maxlength, bool &wasloaded); + +/** + * @brief Attempts to load a plugin. + * + * @param path Path and filename of plugin, relative to plugins folder. + * @return A new plugin handle on success, null otherwise. + */ +stock Handle LoadPlugin(const char[] path) +{ + char error[4]; + bool wasloaded; + return LoadPluginEx(path, error, sizeof(error), wasloaded); +} + +/** + * @brief Attempts to unload a plugin. + * + * @param plugin Handle. + * @param err Error, set on handle failure. + * @return True on success, false otherwise. + */ +native bool UnloadPluginEx(Handle handle, HandleError &err); + +/** + * @brief Attempts to unload a plugin. + * + * @param plugin Handle. + * @return True on success, false otherwise. + */ +stock bool UnloadPlugin(Handle handle) +{ + HandleError err; + return UnloadPluginEx(handle, err); +} \ No newline at end of file