initial
This commit is contained in:
30
LightPerms.TorchCommands/Commands.cs
Normal file
30
LightPerms.TorchCommands/Commands.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Text;
|
||||
using Torch.API.Managers;
|
||||
using Torch.Commands;
|
||||
using Torch.Mod;
|
||||
using Torch.Mod.Messages;
|
||||
namespace LightPerms.TorchCommands;
|
||||
|
||||
[Category("lp")]
|
||||
public class Commands : CommandModule
|
||||
{
|
||||
[Command("get commands", "Get all command permissions")]
|
||||
public void GetCommands()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (Context.Player is null)
|
||||
sb.AppendLine("Available commands:");
|
||||
|
||||
foreach (var commandNode in Context.Torch.CurrentSession.Managers.GetManager<CommandManager>().Commands.WalkTree()
|
||||
.Where(b => b.IsCommand))
|
||||
{
|
||||
sb.Append(" ".PadRight(4)).AppendLine(commandNode.Command.GetPermissionString());
|
||||
}
|
||||
|
||||
if (Context.Player is null)
|
||||
Context.Respond(sb.ToString());
|
||||
else
|
||||
ModCommunication.SendMessageTo(new DialogMessage("Light Perms", "Available commands:", sb.ToString()), Context.Player.SteamUserId);
|
||||
}
|
||||
}
|
10
LightPerms.TorchCommands/Extensions.cs
Normal file
10
LightPerms.TorchCommands/Extensions.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using Torch.Commands;
|
||||
namespace LightPerms.TorchCommands;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static string GetPermissionString(this Command command)
|
||||
{
|
||||
return $"command.{string.Join(".", command.Path.Select(b => b.ToLowerInvariant()))}";
|
||||
}
|
||||
}
|
3
LightPerms.TorchCommands/FodyWeavers.xml
Normal file
3
LightPerms.TorchCommands/FodyWeavers.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<PropertyChanged />
|
||||
</Weavers>
|
91
LightPerms.TorchCommands/LightPerms.TorchCommands.csproj
Normal file
91
LightPerms.TorchCommands/LightPerms.TorchCommands.csproj
Normal file
@@ -0,0 +1,91 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<LangVersion>10</LangVersion>
|
||||
<UseWpf>true</UseWpf>
|
||||
<TorchDir>$(SolutionDir)TorchBinaries\</TorchDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c">
|
||||
<HintPath>$(TorchDir)NLog.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\Sandbox.Common.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Sandbox.Game, Version=0.1.1.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\Sandbox.Game.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Sandbox.Graphics, Version=0.1.1.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\Sandbox.Graphics.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="Torch">
|
||||
<HintPath>$(TorchDir)Torch.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Torch.API">
|
||||
<HintPath>$(TorchDir)Torch.API.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Torch.Server">
|
||||
<HintPath>$(TorchDir)Torch.Server.exe</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\VRage.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\VRage.Game.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\VRage.Input.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\VRage.Library.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\VRage.Math.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Network, Version=1.0.53.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>$(TorchDir)DedicatedServer64\VRage.Network.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LightPerms\LightPerms.csproj" Private="false" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="manifest.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyToTorch" AfterTargets="Build">
|
||||
<ZipDirectory DestinationFile="$(TorchDir)Plugins\$(AssemblyName).zip" SourceDirectory="$(TargetDir)" Overwrite="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
157
LightPerms.TorchCommands/PermissionPatch.cs
Normal file
157
LightPerms.TorchCommands/PermissionPatch.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using Sandbox.Game.Multiplayer;
|
||||
using Sandbox.Game.World;
|
||||
using Torch.API;
|
||||
using Torch.API.Managers;
|
||||
using Torch.Commands;
|
||||
using Torch.Managers;
|
||||
using Torch.Managers.PatchManager;
|
||||
using Torch.Managers.PatchManager.MSIL;
|
||||
using Torch.Mod;
|
||||
using Torch.Mod.Messages;
|
||||
using Torch.Utils;
|
||||
namespace LightPerms.TorchCommands;
|
||||
|
||||
[PatchShim]
|
||||
public static class PermissionPatch
|
||||
{
|
||||
[ReflectedMethodInfo(typeof(CommandManager), nameof(CommandManager.HasPermission))]
|
||||
private static readonly MethodInfo HasPermissionMethod = null!;
|
||||
|
||||
[ReflectedMethodInfo(typeof(Torch.Commands.TorchCommands), nameof(Torch.Commands.TorchCommands.Help))]
|
||||
private static readonly MethodInfo HelpMethod = null!;
|
||||
|
||||
[ReflectedMethodInfo(typeof(Torch.Commands.TorchCommands), nameof(Torch.Commands.TorchCommands.LongHelp))]
|
||||
private static readonly MethodInfo LongHelpMethod = null!;
|
||||
|
||||
[ReflectedMethodInfo(typeof(PermissionPatch), nameof(Prefix))]
|
||||
private static readonly MethodInfo PrefixMethod = null!;
|
||||
|
||||
[ReflectedMethodInfo(typeof(PermissionPatch), nameof(PrefixHelp))]
|
||||
private static readonly MethodInfo PrefixHelpMethod = null!;
|
||||
|
||||
[ReflectedMethodInfo(typeof(PermissionPatch), nameof(PrefixLongHelp))]
|
||||
private static readonly MethodInfo PrefixLongHelpMethod = null!;
|
||||
|
||||
[ReflectedMethodInfo(typeof(PermissionPatch), nameof(Transpiler))]
|
||||
private static readonly MethodInfo TranspilerMethod = null!;
|
||||
|
||||
[ReflectedGetter(Name = "Torch")]
|
||||
private static readonly Func<Manager, ITorchBase> TorchGetter = null!;
|
||||
|
||||
public static void Patch(PatchContext context)
|
||||
{
|
||||
context.GetPattern(HasPermissionMethod).Prefixes.Add(PrefixMethod);
|
||||
context.GetPattern(typeof(CommandManager).GetMethod(nameof(CommandManager.HandleCommand),
|
||||
new []{typeof(string), typeof(ulong), typeof(bool).MakeByRefType(), typeof(bool)})).Transpilers.Add(TranspilerMethod);
|
||||
|
||||
context.GetPattern(HelpMethod).Prefixes.Add(PrefixHelpMethod);
|
||||
context.GetPattern(LongHelpMethod).Prefixes.Add(PrefixLongHelpMethod);
|
||||
}
|
||||
|
||||
private static bool PrefixHelp(CommandModule __instance)
|
||||
{
|
||||
var commandManager = __instance.Context.Torch.CurrentSession.Managers.GetManager<CommandManager>();
|
||||
commandManager.Commands.GetNode(__instance.Context.Args, out var node);
|
||||
|
||||
if (node is null)
|
||||
{
|
||||
__instance.Context.Respond(
|
||||
$"Command not found. Use the {commandManager.Prefix}longhelp command for a full list of commands.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var command = node.Command;
|
||||
var children = node.Subcommands.Where(e => __instance.Context.Player == null ||
|
||||
!e.Value.IsCommand ||
|
||||
!commandManager.HasPermission(__instance.Context.Player.SteamUserId, e.Value.Command))
|
||||
.Select(x => x.Key);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (command is not null)
|
||||
{
|
||||
if (__instance.Context.Player is not null && !commandManager.HasPermission(__instance.Context.Player.SteamUserId, command))
|
||||
{
|
||||
__instance.Context.Respond("You are not authorized to use this command.");
|
||||
return false;
|
||||
}
|
||||
|
||||
sb.AppendLine($"Syntax: {command.SyntaxHelp}");
|
||||
sb.Append(command.HelpText);
|
||||
}
|
||||
|
||||
if (node.Subcommands.Count > 0)
|
||||
sb.Append($"\nSubcommands: {string.Join(", ", children)}");
|
||||
|
||||
__instance.Context.Respond(sb.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool PrefixLongHelp(CommandModule __instance)
|
||||
{
|
||||
var commandManager = __instance.Context.Torch.CurrentSession.Managers.GetManager<CommandManager>();
|
||||
commandManager.Commands.GetNode(__instance.Context.Args, out var node);
|
||||
|
||||
if (node != null)
|
||||
{
|
||||
var command = node.Command;
|
||||
var children = node.Subcommands.Where(e => __instance.Context.Player == null ||
|
||||
!e.Value.IsCommand ||
|
||||
!commandManager.HasPermission(__instance.Context.Player.SteamUserId, e.Value.Command));
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (command != null && (__instance.Context.Player is null || commandManager.HasPermission(__instance.Context.Player.SteamUserId, command)))
|
||||
{
|
||||
sb.AppendLine($"Syntax: {command.SyntaxHelp}");
|
||||
sb.Append(command.HelpText);
|
||||
}
|
||||
|
||||
if (node.Subcommands.Count > 0)
|
||||
sb.Append($"\nSubcommands: {string.Join(", ", children)}");
|
||||
|
||||
__instance.Context.Respond(sb.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var command in commandManager.Commands.WalkTree())
|
||||
{
|
||||
if (command.IsCommand && (__instance.Context.Player is null || commandManager.HasPermission(__instance.Context.Player.SteamUserId, command.Command)))
|
||||
sb.AppendLine($"{command.Command.SyntaxHelp}\n {command.Command.HelpText}");
|
||||
}
|
||||
|
||||
if (!__instance.Context.SentBySelf)
|
||||
{
|
||||
var m = new DialogMessage("Torch Help", "Available commands:", sb.ToString());
|
||||
ModCommunication.SendMessageTo(m, __instance.Context.Player!.SteamUserId);
|
||||
}
|
||||
else
|
||||
__instance.Context.Respond($"Available commands: {sb}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool Prefix(Manager __instance, ulong steamId, Command command, ref bool __result)
|
||||
{
|
||||
__result = steamId == Sync.MyId ||
|
||||
MySession.Static.IsUserAdmin(steamId) ||
|
||||
TorchGetter(__instance).Managers.GetManager<IPermissionsManager>().HasPermission(steamId, command.GetPermissionString());
|
||||
return false;
|
||||
}
|
||||
|
||||
private static IEnumerable<MsilInstruction> Transpiler(IEnumerable<MsilInstruction> ins)
|
||||
{
|
||||
foreach (var instruction in ins)
|
||||
{
|
||||
if (instruction.OpCode == OpCodes.Ldstr &&
|
||||
instruction.Operand is MsilOperandInline.MsilOperandString {Value: "You need to be a {0} or higher to use that command."})
|
||||
yield return instruction.InlineValue("You don't have permission to use that command.");
|
||||
else
|
||||
yield return instruction;
|
||||
}
|
||||
}
|
||||
}
|
12
LightPerms.TorchCommands/Plugin.cs
Normal file
12
LightPerms.TorchCommands/Plugin.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.IO;
|
||||
using System.Windows.Controls;
|
||||
using Torch;
|
||||
using Torch.API;
|
||||
using Torch.API.Plugins;
|
||||
using Torch.Views;
|
||||
|
||||
namespace LightPerms.TorchCommands;
|
||||
|
||||
public class Plugin : TorchPluginBase
|
||||
{
|
||||
}
|
11
LightPerms.TorchCommands/README.md
Normal file
11
LightPerms.TorchCommands/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Add-on for [LightPerms](https://torchapi.com/plugins/view/?guid=5c3f35b3-ac9d-486f-8559-f931536c6700) plugin to have better control over commands permissions.
|
||||
|
||||
### Usage
|
||||
|
||||
All existing torch commands are indexed as `command.something`, spaces are replaced by `.`
|
||||
|
||||
`!help` and `!longhelp` commands are modified to reflect permission requirements.
|
||||
|
||||
For example if you want give to players ability to use `!fixship` command, you need to invoke this command `!lp add perm player command.fixship`
|
||||
|
||||
Wildcards are also supported, for example command to give to admins ability to use all lp commands (you need to create group before using that command) `!lp add perm admin command.lp.*`
|
12
LightPerms.TorchCommands/manifest.xml
Normal file
12
LightPerms.TorchCommands/manifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<PluginManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<Name>LightPerms.TorchCommands</Name>
|
||||
<Guid>0cf57780-f235-4240-99cd-ebd7463e673a</Guid>
|
||||
<Version>v1.0.0</Version>
|
||||
<Dependencies>
|
||||
<PluginDependency>
|
||||
<Plugin>5c3f35b3-ac9d-486f-8559-f931536c6700</Plugin>
|
||||
<MinVersion>v1.0.1</MinVersion>
|
||||
</PluginDependency>
|
||||
</Dependencies>
|
||||
</PluginManifest>
|
20
LightPerms.TorchCommands/setup.bat
Normal file
20
LightPerms.TorchCommands/setup.bat
Normal file
@@ -0,0 +1,20 @@
|
||||
:: This script creates a symlink to the game binaries to account for different installation directories on different systems.
|
||||
|
||||
@echo off
|
||||
|
||||
set /p path="Please enter the folder location of your Torch.Server.exe: "
|
||||
cd %~dp0
|
||||
rmdir TorchBinaries > nul 2>&1
|
||||
mklink /J ..\TorchBinaries "%path%"
|
||||
if errorlevel 1 goto Error
|
||||
echo Done!
|
||||
|
||||
echo You can now open the plugin without issue.
|
||||
goto EndFinal
|
||||
|
||||
:Error
|
||||
echo An error occured creating the symlink.
|
||||
goto EndFinal
|
||||
|
||||
:EndFinal
|
||||
pause
|
Reference in New Issue
Block a user