dobrograd-13-06-2022/garrysmod/addons/admin-sg/lua/modules/sh_plugin.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

390 lines
9.7 KiB
Lua
Raw Blame History

--[[
<09> 2017 Thriving Ventures Limited do not share, re-distribute or modify
without permission of its author (gustaf@thrivingventures.com).
]]
--- ## Shared
--- Library for managing plugins.
-- @module serverguard.plugin
serverguard.plugin = serverguard.plugin or {};
local stored = {};
local object = {};
object.__index = object;
--- Creates a new plugin table.
-- @treturn table Plugin table.
function serverguard.plugin.New()
local plugin = {};
plugin.hooks = {};
plugin.commands = {};
plugin.categories = {};
plugin.toggled = true;
setmetatable(plugin, object);
return plugin;
end;
--- Registers a plugin.
-- @table plugin Plugin table to register.
function serverguard.plugin.Register(plugin)
stored[plugin.unique] = plugin;
if (plugin.permissions) then
serverguard.permission:Add(plugin.permissions);
end;
end;
--- Returns a plugin table with the specified name.
-- @string unique Unique ID of the plugin.
-- @treturn table Plugin table.
function serverguard.plugin.FindByID(unique)
return stored[unique];
end;
serverguard.plugin.Get = serverguard.plugin.FindByID;
--- Returns all registered plugins.
-- @treturn table Table of plugin tables.
function serverguard.plugin.GetList()
return stored;
end;
--- Enables or disables a plugin. This toggles any registered hooks, chat commands, or UI categories.
-- @string uniqueID Unique ID of the plugin.
-- @bool bToggled Whether or not to turn the plugin on.
function serverguard.plugin:Toggle(uniqueID, bToggled)
if (!stored[uniqueID]) then
return;
end;
stored[uniqueID].toggled = bToggled;
local hooks = stored[uniqueID].hooks;
local commands = stored[uniqueID].commands;
for name, data in pairs(hooks) do
for hookUnique, callback in pairs(data) do
if (bToggled) then
hook.Add(name, hookUnique, callback);
else
hook.Remove(name, hookUnique);
end;
end;
end;
for k, v in pairs(commands) do
if (bToggled) then
serverguard.command:Add(v);
else
serverguard.command:Remove(k);
end;
end;
if (CLIENT) then
local categories = stored[uniqueID].categories;
for k, v in pairs(categories) do
if (bToggled) then
serverguard.menu.AddCategory(v);
serverguard.menu:Rebuild();
else
serverguard.menu:RemoveCategory(k);
end;
end;
end;
hook.Call("serverguard.PluginToggled", nil, uniqueID, bToggled);
end;
--
-- Add a hook.
--
function object:Hook(name, unique, callback)
self.hooks[name] = self.hooks[name] or {};
self.hooks[name][unique] = callback;
hook.Add(name, unique, callback);
end;
--
-- Add a command.
--
function object:AddCommand(commandTable)
self.commands[commandTable.command] = self.commands[commandTable.command] or commandTable;
serverguard.command:Add(commandTable);
end;
--
-- Parse a file.
--
function object:IncludeFile(fileName, state)
serverguard.ParseFile(self.path .. fileName, state)
end
if (CLIENT) then
--
-- Add a category.
--
function object:AddCategory(category)
self.categories[category.name] = self.categories[category.name] or category;
serverguard.menu.AddCategory(category);
end;
--
-- Add a subcategory.
--
function object:AddSubCategory(parent_name, data)
serverguard.menu.AddSubCategory(parent_name, data);
end;
end;
--- Load plugin files. This should **not** be called manually as it's done automatically when ServerGuard starts.
function serverguard.plugin.LoadFiles()
if (SG_DEBUG or SG_FILE_DEBUG) then
serverguard.PrintConsole("Loading plugins...\n\n");
end;
local _, folders = file.Find("plugins/*", "LUA");
for k, folder in pairs(folders) do
plugin = serverguard.plugin.FindByID(folder) or serverguard.plugin.New();
plugin.unique = folder;
plugin.path = "plugins/" .. folder.. "/";
if (SERVER) then
if (file.Exists("plugins/" .. folder.. "/init.lua", "LUA")) then
include("plugins/" .. folder.. "/init.lua");
end;
if (file.Exists("plugins/" .. folder.. "/cl_init.lua", "LUA")) then
AddCSLuaFile("plugins/" .. folder.. "/cl_init.lua");
end;
elseif (CLIENT) then
if (file.Exists("plugins/" .. folder.. "/cl_init.lua", "LUA")) then
include("plugins/" .. folder.. "/cl_init.lua");
end;
end;
if (plugin.name) then
serverguard.plugin.Register(plugin);
if (SG_DEBUG or SG_FILE_DEBUG) then
serverguard.PrintConsole("Registered plugin '" .. plugin.name .. "'\n\n");
end;
else
if (SG_DEBUG or SG_FILE_DEBUG) then
serverguard.PrintConsole("Failed to load plugin '" .. folder .. "'!\n\n");
end;
end;
plugin = nil;
end;
if (SG_DEBUG or SG_FILE_DEBUG) then
serverguard.PrintConsole("Loaded plugins.\n");
end;
end;
serverguard.plugin.LoadFiles();
if (SERVER) then
function serverguard.plugin:SaveData(bForced, uniqueIfForced)
local pluginData = {};
for unique, v in pairs(stored) do
if (bForced and unique == uniqueIfForced) then
pluginData[unique] = {toggled = v.toggled, forced = bForced};
else
pluginData[unique] = {toggled = v.toggled, forced = v.forced};
end;
end;
serverguard.config.Save("plugins", pluginData);
end;
--
-- Send the status of all plugins.
--
hook.Add("serverguard.LoadPlayerData", "plugin.LoadPlayerData", function(player)
local plugins = serverguard.plugin.GetList()
for uniqueID, data in pairs(plugins) do
serverguard.netstream.Start(player, "sgGetPluginStatus", {
uniqueID, data.toggled
});
end
end)
--
-- Load the state of all plugins.
--
serverguard.config.New("plugins", function(data)
for unique, v in pairs(data) do
if (stored[unique]) then
local toggle = v.toggled;
local forced = v.forced;
stored[unique].toggled = toggle;
stored[unique].forced = forced;
serverguard.plugin:Toggle(unique, toggle);
end;
end;
end);
hook.Add("serverguard.PostLoadConfig", "serverguard.plugin.PostLoadConfig", function()
for unique, v in pairs(stored) do
if (stored[unique]) then
local bToggled = v.toggled;
if (stored[unique].gamemodes and #stored[unique].gamemodes > 0 and !v.forced) then
if (!table.HasValue(stored[unique].gamemodes, engine.ActiveGamemode())) then
bToggled = false;
if (SG_DEBUG or SG_FILE_DEBUG) then
serverguard.PrintConsole("Force-disabled plugin '"..unique.."' - gamemode not compatible!\n");
end;
end;
end;
serverguard.plugin.Get(unique).toggled = bToggled;
serverguard.plugin:Toggle(unique, bToggled);
end;
end;
end);
elseif (CLIENT) then
serverguard.netstream.Hook("sgGetPluginStatus", function(data)
local uniqueID = data[1];
local state = tobool(data[2]);
local pluginTable = serverguard.plugin.Get(uniqueID);
if (pluginTable) then
pluginTable.toggled = state;
serverguard.plugin:Toggle(uniqueID, pluginTable.toggled);
end;
end);
--
-- Create the menu category.
--
local category = {}
category.name = "Plugins";
category.material = "serverguard/menuicons/icon_toggle.png";
category.permissions = "Manage Plugins";
function category:Create(base)
base.quality = 50
base.panel = base:Add("tiger.panel")
base.panel:SetTitle("Enabled or disabled plugins")
base.panel:Dock(FILL)
base.panel.list = base.panel:Add("tiger.list")
base.panel.list:Dock(FILL)
base.panel.list:AddColumn("PLUGIN", 400)
function base.panel:PerformLayout()
category.list = base.panel.list
end
hook.Call("serverguard.panel.PluginList", nil, base.panel.list);
local column = base.panel.list:AddColumn("ENABLED")
column:SetDisabled(true)
local plugins = serverguard.plugin.GetList()
for unique, data in pairs(plugins) do
local panel = base.panel.list:AddItem(data.name)
panel:SetToolTipSG("Version: " .. data.version .. "\n\n" .. data.description)
local toggleButton = vgui.Create("DImageButton")
toggleButton:SetSize(16, 16)
toggleButton:SetImage(octolib.icons.silk16('accept_button'))
toggleButton.unique = unique
toggleButton.whitelist = true
if (data.gamemodes and #data.gamemodes > 0) then
if (!table.HasValue(data.gamemodes, engine.ActiveGamemode())) then
toggleButton.whitelist = false
end
end
if (!toggleButton.whitelist) then
toggleButton:SetToolTipSG("This plugin is not compatible with the current running gamemode!");
end;
function toggleButton:DoClick()
if (serverguard.player:HasPermission(LocalPlayer(), "Manage Plugins")) then
if (!self.whitelist and !serverguard.plugin.Get(self.unique).toggled) then
local q = util.CreateDialog("Incompatible gamemode",
"This gamemode is incompatible with this plugin. Load it anyways?",
function() serverguard.command.Run("plugintoggle", false, self.unique); end,
"Yes",
function() end,
"No");
return;
end;
serverguard.command.Run("plugintoggle", false, self.unique);
end;
end;
function toggleButton:Think()
local pluginTable = serverguard.plugin.Get(self.unique)
if (pluginTable.toggled) then
if (self:GetImage() == octolib.icons.silk16('cancel')) then
self:SetImage(octolib.icons.silk16('accept_button'))
end
else
if (self:GetImage() == octolib.icons.silk16('accept_button')) then
self:SetImage(octolib.icons.silk16('cancel'))
end
end
end
function toggleButton:PerformLayout()
DImageButton.PerformLayout(self)
local w, h = self:GetSize()
local column = panel:GetThing(2).column
local x = column:GetPos()
self:SetPos(x +column:GetWide() /2 -w /2, column:GetTall() /2 -h /2)
end
panel:AddItem(toggleButton)
end
end
function category:Update(base)
end
serverguard.menu.AddSubCategory("Server settings", category)
hook.Add("serverguard.menu.Close", "serverguard.PluginList", function()
if (IsValid(category.list)) then
for k, v in ipairs(category.list:GetCanvas():GetChildren()) do
if (IsValid(v.tooltip_sg)) then
v:OnCursorExited();
end;
end;
end;
end);
end