Skip to content

Commit

Permalink
work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
VALERA771 committed Aug 12, 2024
1 parent 8132e16 commit c3160f7
Showing 1 changed file with 130 additions and 47 deletions.
177 changes: 130 additions & 47 deletions EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
// </copyright>
// -----------------------------------------------------------------------

using System.IO;
using Exiled.Events.Patches.Generic;

namespace Exiled.Events.Patches.Events.Server
{
#pragma warning disable SA1402
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;

using Exiled.API.Features;
using Exiled.API.Features.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Server;
using Exiled.Events.Patches.Generic;
using HarmonyLib;
using RemoteAdmin;

Expand All @@ -28,9 +28,9 @@ namespace Exiled.Events.Patches.Events.Server
/// Patches <see cref="CommandProcessor.ProcessQuery"/> and <see cref="QueryProcessor.ProcessGameConsoleQuery"/>
/// to add <see cref="Handlers.Server.ExecutingCommand"/> and <see cref="Handlers.Server.ExecutedCommand"/> events.
/// </summary>
[HarmonyPatch]
[EventPatch(typeof(Handlers.Server), nameof(Handlers.Server.OnExecutingCommand))]
[EventPatch(typeof(Handlers.Server), nameof(Handlers.Server.OnExecutedCommand))]
[HarmonyPatch(typeof(CommandProcessor), nameof(CommandProcessor.ProcessQuery))]
// [EventPatch(typeof(Handlers.Server), nameof(Handlers.Server.ExecutingCommand))]

Check failure on line 32 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 32 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 32 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 32 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 32 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

// [EventPatch(typeof(Handlers.Server), nameof(Handlers.Server.ExecutedCommand))]
internal class ExecuteCommand
{
/// <summary>
Expand Down Expand Up @@ -83,13 +83,10 @@ public static void LogCommand(string query, CommandSender sender)
}
}

[HarmonyPatch(typeof(CommandProcessor), nameof(CommandProcessor.ProcessQuery))]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

int index = newInstructions.FindIndex(x => x.operand is FieldInfo fieldInfo && fieldInfo == Field(typeof(CommandProcessor), nameof(CommandProcessor.RemoteAdminCommandHandler)));

LocalBuilder ev = generator.DeclareLocal(typeof(ExecutingCommandEventArgs));

Label returnLabel = generator.DefineLabel();
Expand Down Expand Up @@ -119,48 +116,44 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel),
});

newInstructions.InsertRange(index, new[]
int index = newInstructions.FindIndex(x => x.Is(OpCodes.Ldsfld, Field(typeof(CommandProcessor), nameof(CommandProcessor.RemoteAdminCommandHandler))));

newInstructions.InsertRange(index, new CodeInstruction[]
{
// Player.Get(sender);
new CodeInstruction(OpCodes.Ldarg_1).MoveLabelsFrom(newInstructions[index]),
new(OpCodes.Ldarg_1),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(CommandSender) })),

// null
new(OpCodes.Ldnull),

// strArray.Segment(1);
new(OpCodes.Ldloc_0),
new(OpCodes.Call, Method(typeof(ExecuteCommand), nameof(Convert))),

// true
new(OpCodes.Ldc_I4_1),

// ExecutingCommandEventArgs ev = new(Player, null, ArraySegment<string>, true);
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ExecutingCommandEventArgs))[0]),
new(OpCodes.Stloc_S, ev.LocalIndex),
});

index = newInstructions.FindIndex(x => x.opcode == OpCodes.Ldloc_1);
index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Ldloc_1);

newInstructions.InsertRange(index, new CodeInstruction[]
{
new(OpCodes.Ldloc_1),
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Ldloc_1),
new(OpCodes.Callvirt, PropertySetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.Command))),

new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Ldloc_S, ev.LocalIndex),

// Handlers.Server.OnExecutingCommand(ev);
new(OpCodes.Call, Method(typeof(Handlers.Server), nameof(Handlers.Server.OnExecutingCommand))),

// if (ev.IsAllowed)
// goto retLabel
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.IsAllowed))),
new(OpCodes.Brfalse_S, returnLabel),
});

index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Ldloc_0);
int offset = -3;
index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Ldelem_Ref) + offset;

newInstructions[index].labels.Add(continueLabel);

newInstructions.InsertRange(index, new[]
{
Expand All @@ -176,28 +169,26 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new(OpCodes.Ldloc_0),
new(OpCodes.Ldc_I4_0),
new(OpCodes.Ldelem_Ref),
new(OpCodes.Call, Method(typeof(string), nameof(string.ToUpperInvariant))),
new(OpCodes.Callvirt, Method(typeof(string), nameof(string.ToUpperInvariant))),
new(OpCodes.Ldstr, "#Command execution was aborted by a plugin."),
new(OpCodes.Call, Method(typeof(string), nameof(string.Concat), new[] { typeof(string), typeof(string) })),
new(OpCodes.Ldc_I4_0),
new(OpCodes.Ldc_I4_1),
new(OpCodes.Ldstr, string.Empty),
new(OpCodes.Call, Method(typeof(CommandSender), nameof(CommandSender.RaReply))),
new(OpCodes.Callvirt, Method(typeof(CommandSender), nameof(CommandSender.RaReply))),

new(OpCodes.Ldstr, "Command execution was aborted by a plugin."),
new(OpCodes.Ret),

new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel),
});

int offset = 1;
index = newInstructions.FindIndex(x => x.opcode == OpCodes.Stloc_S && x.operand is 6) + offset;
offset = 2;
index = newInstructions.FindIndex(x => x.Calls(Method(typeof(Misc), nameof(Misc.CloseAllRichTextTags)))) + offset;

newInstructions.InsertRange(index, new CodeInstruction[]
{
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Dup),
new(OpCodes.Dup),

new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.Player))),
new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.Command))),
Expand All @@ -218,18 +209,110 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi

private static ArraySegment<string> Convert(string[] strArray) => strArray.Segment(1);
}
}

/*IL_00f4: ldarg.1 // sender
IL_00f5: ldloc.0 // strArray
IL_00f6: ldc.i4.0
IL_00f7: ldelem.ref
IL_00f8: callvirt instance string [mscorlib]System.String::ToUpperInvariant()
IL_00fd: ldstr "#"
IL_0102: ldloc.s response
IL_0104: call string [mscorlib]System.String::Concat(string, string, string)
IL_0109: ldloc.s flag
IL_010b: ldc.i4.1
IL_010c: ldstr ""
IL_0111: callvirt instance void CommandSender::RaReply(string, bool, bool, string)
*/

[HarmonyPatch(typeof(QueryProcessor), nameof(QueryProcessor.ProcessGameConsoleQuery))]
internal class ExecuteCommandClientConsole

Check failure on line 214 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 214 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 214 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 214 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 214 in EXILED/Exiled.Events/Patches/Events/Server/ExecuteCommand.cs

View workflow job for this annotation

GitHub Actions / build

{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

LocalBuilder ev = generator.DeclareLocal(typeof(ExecutingCommandEventArgs));

Label continueLabel = generator.DefineLabel();
Label returnLabel = generator.DefineLabel();

int index = newInstructions.FindIndex(x => x.Is(OpCodes.Ldsfld, Field(typeof(QueryProcessor), nameof(QueryProcessor.DotCommandHandler))));

newInstructions.InsertRange(index, new CodeInstruction[]
{
new(OpCodes.Ldarg_0),
new(OpCodes.Ldfld, Field(typeof(QueryProcessor), nameof(QueryProcessor._hub))),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

new(OpCodes.Ldnull),

new(OpCodes.Ldloc_0),
new(OpCodes.Call, Method(typeof(ExecuteCommand), "Convert")),

new(OpCodes.Ldc_I4_1),

new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ExecutingCommandEventArgs))[0]),
new(OpCodes.Stloc_S, ev.LocalIndex),
});

index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Ldloc_1);

newInstructions.InsertRange(index, new CodeInstruction[]
{
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Ldloc_1),
new(OpCodes.Callvirt, PropertySetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.Command))),

new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Call, Method(typeof(Handlers.Server), nameof(Handlers.Server.OnExecutingCommand))),

new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.IsAllowed))),
new(OpCodes.Brfalse_S, returnLabel),
});

int offset = -4;
index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Ldelem_Ref) + offset;

newInstructions[index].labels.Add(continueLabel);

newInstructions.InsertRange(index, new[]
{
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex).MoveLabelsFrom(newInstructions[index]),
new(OpCodes.Dup),

new(OpCodes.Call, Method(typeof(Handlers.Server), nameof(Handlers.Server.OnExecutingCommand))),

new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.IsAllowed))),
new(OpCodes.Brtrue_S, continueLabel),

new CodeInstruction(OpCodes.Ldarg_0).WithLabels(returnLabel),
new(OpCodes.Ldfld, Field(typeof(QueryProcessor), nameof(QueryProcessor._hub))),
new(OpCodes.Ldfld, Field(typeof(ReferenceHub), nameof(ReferenceHub.gameConsoleTransmission))),
new(OpCodes.Ldstr, "Command execution was aborted by a plugin."),
new(OpCodes.Ldstr, "red"),
new(OpCodes.Callvirt, Method(typeof(GameConsoleTransmission), nameof(GameConsoleTransmission.SendToClient))),
new(OpCodes.Ret),
});

offset = 2;
index = newInstructions.FindIndex(x => x.Calls(Method(typeof(Misc), nameof(Misc.CloseAllRichTextTags)))) + offset;

newInstructions.InsertRange(index, new CodeInstruction[]
{
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Dup),
new(OpCodes.Dup),

new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.Player))),
new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.Command))),
new(OpCodes.Callvirt, PropertyGetter(typeof(ExecutingCommandEventArgs), nameof(ExecutingCommandEventArgs.Arguments))),

new(OpCodes.Ldloc_3),

new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ExecutedCommandEventArgs))[0]),

new(OpCodes.Call, Method(typeof(Handlers.Server), nameof(Handlers.Server.OnExecutedCommand))),
});

for (int z = 0; z < newInstructions.Count; z++)
yield return newInstructions[z];

ListPool<CodeInstruction>.Pool.Return(newInstructions);
}
}

/*internal class ExecuteCommandGameConsole
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
}
}*/
}

0 comments on commit c3160f7

Please sign in to comment.