mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-06 08:03:12 -08:00
338 lines
12 KiB
C#
338 lines
12 KiB
C#
/*
|
|
* This file is part of CounterStrikeSharp.
|
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using CounterStrikeSharp.API.Modules.Admin;
|
|
using CounterStrikeSharp.API.Modules.Commands;
|
|
using CounterStrikeSharp.API.Modules.Menu;
|
|
using CounterStrikeSharp.API.Modules.Utils;
|
|
|
|
namespace CounterStrikeSharp.API.Core
|
|
{
|
|
public sealed class GlobalContext
|
|
{
|
|
private static GlobalContext _instance = null;
|
|
public static GlobalContext Instance => _instance;
|
|
|
|
private DirectoryInfo rootDir;
|
|
|
|
private readonly List<PluginContext> _loadedPlugins = new();
|
|
|
|
public GlobalContext()
|
|
{
|
|
rootDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.Parent;
|
|
_instance = this;
|
|
}
|
|
|
|
~GlobalContext()
|
|
{
|
|
foreach (var plugin in _loadedPlugins)
|
|
{
|
|
plugin.Unload();
|
|
}
|
|
}
|
|
|
|
public void OnNativeUnload()
|
|
{
|
|
foreach (var plugin in _loadedPlugins)
|
|
{
|
|
plugin.Unload();
|
|
}
|
|
}
|
|
public void InitGlobalContext()
|
|
{
|
|
Console.WriteLine("Loading CoreConfig from \"configs/core.json\"");
|
|
CoreConfig.Load(Path.Combine(rootDir.FullName, "configs", "core.json"));
|
|
|
|
Console.WriteLine("Loading GameData from \"gamedata/gamedata.json\"");
|
|
GameData.Load(Path.Combine(rootDir.FullName, "gamedata", "gamedata.json"));
|
|
|
|
Console.WriteLine("Loading Admin Groups from \"configs/admin_groups.json\"");
|
|
AdminManager.LoadAdminGroups(Path.Combine(rootDir.FullName, "configs", "admin_groups.json"));
|
|
Console.WriteLine("Loading Admins from \"configs/admins.json\"");
|
|
AdminManager.LoadAdminData(Path.Combine(rootDir.FullName, "configs", "admins.json"));
|
|
Console.WriteLine("Loading Admin Command Overrides from \"configs/admin_overrides.json\"");
|
|
AdminManager.LoadCommandOverrides(Path.Combine(rootDir.FullName, "configs", "admin_overrides.json"));
|
|
|
|
AdminManager.MergeGroupPermsIntoAdmins();
|
|
|
|
for (var i = 1; i <= 9; i++)
|
|
{
|
|
CommandUtils.AddStandaloneCommand("css_" + i, "Command Key Handler", (player, info) =>
|
|
{
|
|
if (player == null) return;
|
|
var key = Convert.ToInt32(info.GetArg(0).Split("_")[1]);
|
|
ChatMenus.OnKeyPress(player, key);
|
|
});
|
|
}
|
|
|
|
Console.WriteLine("Loading C# plugins...");
|
|
var pluginCount = LoadAllPlugins();
|
|
Console.WriteLine($"All managed modules were loaded. {pluginCount} plugins loaded.");
|
|
|
|
RegisterPluginCommands();
|
|
}
|
|
|
|
private void LoadPlugin(string path)
|
|
{
|
|
var existingPlugin = FindPluginByModulePath(path);
|
|
if (existingPlugin != null)
|
|
{
|
|
throw new FileLoadException("Plugin is already loaded.");
|
|
}
|
|
|
|
var plugin = new PluginContext(path, _loadedPlugins.Select(x => x.PluginId).DefaultIfEmpty(0).Max() + 1);
|
|
plugin.Load();
|
|
_loadedPlugins.Add(plugin);
|
|
}
|
|
|
|
private int LoadAllPlugins()
|
|
{
|
|
DirectoryInfo modulesDirectoryInfo;
|
|
try
|
|
{
|
|
modulesDirectoryInfo = new DirectoryInfo(Path.Combine(rootDir.FullName, "plugins"));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
return 0;
|
|
}
|
|
|
|
DirectoryInfo[] properModulesDirectories;
|
|
try
|
|
{
|
|
properModulesDirectories = modulesDirectoryInfo.GetDirectories();
|
|
}
|
|
catch
|
|
{
|
|
properModulesDirectories = Array.Empty<DirectoryInfo>();
|
|
}
|
|
|
|
|
|
var filePaths = properModulesDirectories
|
|
.Where(d => d.GetFiles().Any((f) => f.Name == d.Name + ".dll"))
|
|
.Select(d => d.GetFiles().First((f) => f.Name == d.Name + ".dll").FullName)
|
|
.ToArray();
|
|
|
|
|
|
foreach (var path in filePaths)
|
|
{
|
|
Console.WriteLine($"Plugin path: {path}");
|
|
try
|
|
{
|
|
LoadPlugin(path);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine($"Failed to load plugin {path} with error {e}");
|
|
}
|
|
}
|
|
|
|
return _loadedPlugins.Count;
|
|
}
|
|
|
|
public void UnloadAllPlugins()
|
|
{
|
|
foreach (var plugin in _loadedPlugins)
|
|
{
|
|
plugin.Unload();
|
|
_loadedPlugins.Remove(plugin);
|
|
}
|
|
}
|
|
|
|
private PluginContext? FindPluginByType(Type moduleClass)
|
|
{
|
|
return _loadedPlugins.FirstOrDefault(x => x.PluginType == moduleClass);
|
|
}
|
|
|
|
private PluginContext? FindPluginById(int id)
|
|
{
|
|
return _loadedPlugins.FirstOrDefault(x => x.PluginId == id);
|
|
}
|
|
|
|
private PluginContext? FindPluginByModuleName(string name)
|
|
{
|
|
return _loadedPlugins.FirstOrDefault(x => x.Name == name);
|
|
}
|
|
|
|
private PluginContext? FindPluginByModulePath(string path)
|
|
{
|
|
return _loadedPlugins.FirstOrDefault(x => x.PluginPath == path);
|
|
}
|
|
|
|
private PluginContext? FindPluginByIdOrName(string query)
|
|
{
|
|
|
|
PluginContext? plugin = null;
|
|
if (Int32.TryParse(query, out var pluginNumber))
|
|
{
|
|
plugin = FindPluginById(pluginNumber);
|
|
if (plugin != null) return plugin;
|
|
}
|
|
|
|
plugin = FindPluginByModuleName(query);
|
|
|
|
return plugin;
|
|
}
|
|
|
|
[RequiresPermissions("@css/generic")]
|
|
[CommandHelper(whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
private void OnCSSCommand(CCSPlayerController? caller, CommandInfo info)
|
|
{
|
|
var currentVersion = Api.GetVersion();
|
|
|
|
info.ReplyToCommand(" CounterStrikeSharp was created and is maintained by Michael \"roflmuffin\" Wilson.\n" +
|
|
" Counter-Strike Sharp uses code borrowed from SourceMod, Source.Python, FiveM, Saul Rennison and CS2Fixes.\n" +
|
|
" See ACKNOWLEDGEMENTS.md for more information.\n" +
|
|
" Current API Version: " + currentVersion, true);
|
|
return;
|
|
}
|
|
|
|
[RequiresPermissions("@css/generic")]
|
|
[CommandHelper(minArgs: 1,
|
|
usage: "[option]\n" +
|
|
" list - List all plugins currently loaded.\n" +
|
|
" start / load - Loads a plugin not currently loaded.\n" +
|
|
" stop / unload - Unloads a plugin currently loaded.\n" +
|
|
" restart / reload - Reloads a plugin currently loaded.",
|
|
whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
private void OnCSSPluginCommand(CCSPlayerController? caller, CommandInfo info)
|
|
{
|
|
switch (info.GetArg(1))
|
|
{
|
|
case "list":
|
|
{
|
|
info.ReplyToCommand($" List of all plugins currently loaded by CounterStrikeSharp: {_loadedPlugins.Count} plugins loaded.", true);
|
|
|
|
foreach (var plugin in _loadedPlugins)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.AppendFormat(" [#{0}]: \"{1}\" ({2})", plugin.PluginId, plugin.Name, plugin.Version);
|
|
if (!string.IsNullOrEmpty(plugin.Author)) sb.AppendFormat(" by {0}", plugin.Author);
|
|
if (!string.IsNullOrEmpty(plugin.Description))
|
|
{
|
|
sb.Append("\n");
|
|
sb.Append(" ");
|
|
sb.Append(plugin.Description);
|
|
}
|
|
info.ReplyToCommand(sb.ToString(), true);
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
case "start":
|
|
case "load":
|
|
{
|
|
if (info.ArgCount < 2)
|
|
{
|
|
info.ReplyToCommand("Valid usage: css_plugins start/load [relative plugin path || absolute plugin path] (e.g \"TestPlugin\", \"plugins/TestPlugin/TestPlugin.dll\")\n", true);
|
|
break;
|
|
}
|
|
|
|
// If our arugment doesn't end in ".dll" - try and construct a path similar to PluginName/PluginName.dll.
|
|
// We'll assume we have a full path if we have ".dll".
|
|
var path = info.GetArg(2);
|
|
if (!path.EndsWith(".dll"))
|
|
{
|
|
path = Path.Combine(rootDir.FullName, $"plugins/{path}/{path}.dll");
|
|
}
|
|
else
|
|
{
|
|
path = Path.Combine(rootDir.FullName, path);
|
|
}
|
|
|
|
try
|
|
{
|
|
LoadPlugin(path);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine($"Failed to load plugin {path} with error {e}");
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case "stop":
|
|
case "unload":
|
|
{
|
|
if (info.ArgCount < 2)
|
|
{
|
|
info.ReplyToCommand("Valid usage: css_plugins stop/unload [plugin name || #plugin id] (e.g \"TestPlugin\", \"1\")\n", true);
|
|
break;
|
|
}
|
|
|
|
var pluginIdentifier = info.GetArg(2);
|
|
PluginContext? plugin = FindPluginByIdOrName(pluginIdentifier);
|
|
if (plugin == null)
|
|
{
|
|
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\")", true);
|
|
break;
|
|
}
|
|
plugin.Unload();
|
|
_loadedPlugins.Remove(plugin);
|
|
break;
|
|
}
|
|
|
|
case "restart":
|
|
case "reload":
|
|
{
|
|
if (info.ArgCount < 2)
|
|
{
|
|
info.ReplyToCommand("Valid usage: css_plugins restart/reload [plugin name || #plugin id] (e.g \"TestPlugin\", \"#1\")\n", true);
|
|
break;
|
|
}
|
|
|
|
var pluginIdentifier = info.GetArg(2);
|
|
var plugin = FindPluginByIdOrName(pluginIdentifier);
|
|
|
|
if (plugin == null)
|
|
{
|
|
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\")", true);
|
|
break;
|
|
}
|
|
plugin.Unload(true);
|
|
plugin.Load(true);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
info.ReplyToCommand("Valid usage: css_plugins [option]\n" +
|
|
" list - List all plugins currently loaded.\n" +
|
|
" start / load - Loads a plugin not currently loaded.\n" +
|
|
" stop / unload - Unloads a plugin currently loaded.\n" +
|
|
" restart / reload - Reloads a plugin currently loaded."
|
|
, true);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
private void RegisterPluginCommands()
|
|
{
|
|
CommandUtils.AddStandaloneCommand("css", "Counter-Strike Sharp options.", OnCSSCommand);
|
|
CommandUtils.AddStandaloneCommand("css_plugins", "Counter-Strike Sharp plugin options.", OnCSSPluginCommand);
|
|
}
|
|
|
|
}
|
|
} |