Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added SendingCommand event to Player #163

Merged
merged 35 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3f43ad0
Added Event
Oct 31, 2024
22ed05e
adk how but i broke this while adding comments..........
Oct 31, 2024
4b31444
Added Some Features, and changed event name.
Nov 1, 2024
5e2c6b8
Merge branch 'dev' into sendingcommandevent
louis1706 Nov 1, 2024
bd02944
Merge branch 'dev' into sendingcommandevent
louis1706 Nov 9, 2024
f0c4526
Update SendingValidRACommand.cs
Mar1ki Nov 9, 2024
66481e6
Update SendingValidRACommand.cs
Mar1ki Nov 9, 2024
6ae0df1
Update Player.cs
Mar1ki Nov 9, 2024
0f8015c
Update SendingValidRACommandEventArgs.cs
Mar1ki Nov 17, 2024
bf778e0
Merge branch 'dev' into sendingcommandevent
louis1706 Nov 18, 2024
5e91382
Update docs
Misaka-ZeroTwo Nov 23, 2024
a1f3748
Update Player.cs
Mar1ki Nov 23, 2024
5a7d7f0
Update Player.cs
Mar1ki Nov 23, 2024
157de05
Trying to change header from my mobile phone
Mar1ki Nov 23, 2024
31af951
Update SendingValidRACommandEventArgs.cs
Mar1ki Nov 23, 2024
7f44855
Update SendingValidRACommand.cs
Mar1ki Nov 23, 2024
a453045
Update Player.cs
Mar1ki Nov 23, 2024
dc16d67
Merge branch 'dev' into sendingcommandevent
louis1706 Dec 26, 2024
705d3f6
Added support to client command and using Plugin api enumn
Jan 4, 2025
06a15c0
build errors🥶
Mar1ki Jan 4, 2025
e5d45bb
Merge branch 'dev' into sendingcommandevent
Mar1ki Jan 4, 2025
e9e3e40
Update Exiled.Events.csproj
Mar1ki Jan 7, 2025
72ee126
Merge branch 'dev' into sendingcommandevent
louis1706 Jan 13, 2025
13af934
Added SendedValidCommand event
Jan 14, 2025
8ee3a97
Some Spelling Issues fixed(maybe i lost smth)
Jan 14, 2025
ec500db
oh
Jan 14, 2025
f165406
Renamed first patch.
Mar1ki Jan 14, 2025
282aaa9
Renamed second patch
Mar1ki Jan 14, 2025
87be843
Update SendingValidGameConsoleCommand.cs
Mar1ki Jan 14, 2025
2d5c600
Update SendingValidRACommand.cs
Mar1ki Jan 14, 2025
3acfc1f
Update SendingValidGameConsoleCommand.cs
Mar1ki Jan 15, 2025
ccd6764
Update SendingValidRACommand.cs
Mar1ki Jan 15, 2025
d48c0b5
bla
Jan 15, 2025
416920a
Merge branch 'dev' into sendingcommandevent
Mar1ki Jan 15, 2025
8ffa2ff
Update EXILED/Exiled.Events/EventArgs/Player/SendingValidCommandEvent…
Mar1ki Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// -----------------------------------------------------------------------
// <copyright file="SendingValidCommandEventArgs.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.EventArgs.Player
{
using CommandSystem;
using Exiled.API.Features;
using Exiled.API.Features.Pickups;
using Exiled.Events.EventArgs.Interfaces;
using PluginAPI.Enums;
using RemoteAdmin;

/// <summary>
/// Contains all information before a player sends the command.
/// </summary>
public class SendingValidCommandEventArgs : IPlayerEvent, IDeniableEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="SendingValidCommandEventArgs" /> class.
/// </summary>
/// <param name="player">
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="command">
/// <inheritdoc cref="Command" />
/// </param>
/// <param name="commandType">
/// <inheritdoc cref="Type" />
/// </param>
/// <param name="query">
/// <inheritdoc cref="Query" />
/// </param>
/// <param name="response">
/// <inheritdoc cref="Response" />
/// </param>
public SendingValidCommandEventArgs(Player player, ICommand command, CommandType commandType, string query, string response)
{
Player = player;
Command = command;
Type = commandType;
Query = query;
Response = response;
}

/// <summary>
/// Gets or sets a value indicating whether the player can send the command.
/// </summary>
public bool IsAllowed { get; set; } = true;

/// <summary>
/// Gets or sets the response of the command. If this value is null, the response will stay unchanged.
/// </summary>
public string Response { get; set; }

/// <summary>
/// Gets the player who is sending the command.
/// </summary>
public Player Player { get; }

/// <summary>
/// Gets the command query.
/// </summary>
public string Query { get; }

/// <summary>
/// Gets the command type.
/// </summary>
public CommandType Type { get; }

/// <summary>
/// Gets the command interface.
/// </summary>
public ICommand Command { get; }
}
}
83 changes: 83 additions & 0 deletions EXILED/Exiled.Events/EventArgs/Player/SentValidCommandEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// -----------------------------------------------------------------------
// <copyright file="SentValidCommandEventArgs.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.EventArgs.Player
{
using CommandSystem;
using Exiled.API.Features;
using Exiled.API.Features.Pickups;
using Exiled.Events.EventArgs.Interfaces;
using PluginAPI.Enums;
using RemoteAdmin;

/// <summary>
/// Contains all information after a player sends the command.
/// </summary>
public class SentValidCommandEventArgs : IPlayerEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="SentValidCommandEventArgs" /> class.
/// </summary>
/// <param name="player">
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="command">
/// <inheritdoc cref="Command" />
/// </param>
/// <param name="commandType">
/// <inheritdoc cref="Type" />
/// </param>
/// <param name="query">
/// <inheritdoc cref="Query" />
/// </param>
/// <param name="response">
/// <inheritdoc cref="Response" />
/// </param>
/// <param name="result">
/// <inheritdoc cref="Result" />
/// </param>
public SentValidCommandEventArgs(Player player, ICommand command, CommandType commandType, string query, string response, bool result)
{
Player = player;
Command = command;
Type = commandType;
Query = query;
Response = response;
Result = result;
}

/// <summary>
/// Gets a value indicating whether the command succeeded.
/// </summary>
public bool Result { get; }

/// <summary>
/// Gets the response of the command.
/// </summary>
public string Response { get; }

/// <summary>
/// Gets the player who is sending the command.
/// </summary>
public Player Player { get; }

/// <summary>
/// Gets the command query.
/// </summary>
public string Query { get; }

/// <summary>
/// Gets the command type.
/// </summary>
public CommandType Type { get; }

/// <summary>
/// Gets the command interface.
/// </summary>
public ICommand Command { get; }
}
}
22 changes: 22 additions & 0 deletions EXILED/Exiled.Events/Handlers/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,16 @@ public class Player
/// </summary>
public static Event<ChangingNicknameEventArgs> ChangingNickname { get; set; } = new();

/// <summary>
/// Invoked before a <see cref="API.Features.Player"/> sends valid command.
/// </summary>
public static Event<SendingValidCommandEventArgs> SendingValidCommand { get; set; } = new();

/// <summary>
/// Invoked after a <see cref="API.Features.Player"/> sends valid command.
/// </summary>
public static Event<SentValidCommandEventArgs> SentValidCommand { get; set; } = new();

/// <summary>
/// Invoked before a player's emotion changed.
/// </summary>
Expand Down Expand Up @@ -1198,6 +1208,18 @@ public static void OnItemRemoved(ReferenceHub referenceHub, InventorySystem.Item
/// <param name="ev">The <see cref="ChangingNicknameEventArgs"/> instance.</param>
public static void OnChangingNickname(ChangingNicknameEventArgs ev) => ChangingNickname.InvokeSafely(ev);

/// <summary>
/// Called before a <see cref="Player"/> sends valid command.
/// </summary>
/// <param name="ev">The <see cref="SendingValidCommandEventArgs"/> instance.</param>
public static void OnSendingValidCommand(SendingValidCommandEventArgs ev) => SendingValidCommand.InvokeSafely(ev);

/// <summary>
/// Called after a <see cref="Player"/> sends valid command.
/// </summary>
/// <param name="ev">The <see cref="SentValidCommandEventArgs"/> instance.</param>
public static void OnSentValidCommand(SentValidCommandEventArgs ev) => SentValidCommand.InvokeSafely(ev);

/// <summary>
/// Called before a <see cref="API.Features.Player"/>'s rotates the revolver.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// -----------------------------------------------------------------------
// <copyright file="SendingValidGameConsoleCommand.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.Patches.Events.Player
{
using System;
using System.Collections.Generic;
using System.Reflection.Emit;

using API.Features;
using API.Features.Pools;
using CommandSystem;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Player;

using HarmonyLib;

using RemoteAdmin;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches <see cref="QueryProcessor.ProcessGameConsoleQuery(string)" />.
/// Adds the <see cref="Handlers.Player.SendingValidCommand" /> and
/// the <see cref="Handlers.Player.SentValidCommand" /> events.
/// </summary>
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.SendingValidCommand))]
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.SentValidCommand))]
[HarmonyPatch(typeof(QueryProcessor), nameof(QueryProcessor.ProcessGameConsoleQuery))]
internal static class SendingValidGameConsoleCommand
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label ret = generator.DefineLabel();
newInstructions[newInstructions.Count - 1].WithLabels(ret);

Label setproperresp = generator.DefineLabel();

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

int offset = 2;
int index = newInstructions.FindIndex(instruction => instruction.Calls(Method(typeof(ClientCommandHandler), nameof(ClientCommandHandler.TryGetCommand)))) + offset;
Label contlabel = generator.DefineLabel();

offset = -6;
int sendreplyidx = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ldstr && (string)instruction.operand == "magenta") + offset;
Label sendreply = generator.DefineLabel();
newInstructions[sendreplyidx].WithLabels(sendreply);

newInstructions[index].WithLabels(contlabel);

newInstructions.InsertRange(
index,
new CodeInstruction[]
{
// this
new CodeInstruction(OpCodes.Ldarg_0),

// this._hub
new CodeInstruction(OpCodes.Ldfld, Field(typeof(QueryProcessor), nameof(QueryProcessor._hub))),

// Player.Get(Hub)
new CodeInstruction(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new Type[] { typeof(ReferenceHub) })),

// command
new (OpCodes.Ldloc_S, 1),

// commandtype client
new CodeInstruction(OpCodes.Ldc_I4_2),

// query
new CodeInstruction(OpCodes.Ldarg_1),

// response
new CodeInstruction(OpCodes.Ldloc_S, 3),

// new SendingValidCommandEventArgs
new CodeInstruction(OpCodes.Newobj, GetDeclaredConstructors(typeof(SendingValidCommandEventArgs))[0]),
new CodeInstruction(OpCodes.Dup),
new CodeInstruction(OpCodes.Stloc_S, ev.LocalIndex),

// OnSendingValidCommad(ev)
new CodeInstruction(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnSendingValidCommand))),

// if ev.IsAllowed cont
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),
new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(SendingValidCommandEventArgs), nameof(SendingValidCommandEventArgs.IsAllowed))),
new CodeInstruction(OpCodes.Brtrue_S, contlabel),

// if ev.Response.IsNullOrEmpty rets
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),
new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof (SendingValidCommandEventArgs), nameof(SendingValidCommandEventArgs.Response))),
new CodeInstruction(OpCodes.Call, Method(typeof(string), nameof(string.IsNullOrEmpty))),
new CodeInstruction(OpCodes.Brtrue_S, setproperresp),

// response = ev.Response
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),
new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof (SendingValidCommandEventArgs), nameof(SendingValidCommandEventArgs.Response))),
new CodeInstruction(OpCodes.Stloc_S, 3),

// goto sendreply
new CodeInstruction(OpCodes.Br, sendreply),

// response = "The Command Execution Was Prevented By Plugin."
new CodeInstruction(OpCodes.Ldstr, "The Command Execution Was Prevented By Plugin.").WithLabels(setproperresp),
new CodeInstruction(OpCodes.Stloc_S, 3),
new CodeInstruction(OpCodes.Br, sendreply),
});

offset = -3;
index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ldstr && (string)instruction.operand == "magenta") + offset;
Label skip = generator.DefineLabel();
newInstructions[index].WithLabels(skip);
newInstructions.InsertRange(
index,
new CodeInstruction[]
{
// if ev.Response.IsNullOrEmpty skip
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),
new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof (SendingValidCommandEventArgs), nameof(SendingValidCommandEventArgs.Response))),
new CodeInstruction(OpCodes.Call, Method(typeof(string), nameof(string.IsNullOrEmpty))),
new CodeInstruction(OpCodes.Brtrue_S, skip),

// response = ev.Response
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),
new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof (SendingValidCommandEventArgs), nameof(SendingValidCommandEventArgs.Response))),
new CodeInstruction(OpCodes.Stloc_S, 3),
});
offset = 0;
index = newInstructions.FindIndex(instrction => instrction.Calls(Method(typeof(GameConsoleTransmission), nameof(GameConsoleTransmission.SendToClient)))) + offset;
newInstructions.InsertRange(
index,
new CodeInstruction[]
{
// this
new CodeInstruction(OpCodes.Ldarg_0),

// this._hub
new CodeInstruction(OpCodes.Ldfld, Field(typeof(QueryProcessor), nameof(QueryProcessor._hub))),

// Player.Get(Hub)
new CodeInstruction(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new Type[] { typeof(ReferenceHub) })),

// command
new CodeInstruction(OpCodes.Ldloc_1),

// commandtype CLIENT
new CodeInstruction(OpCodes.Ldc_I4_2),

// query
new CodeInstruction(OpCodes.Ldarg_1),

// response
new CodeInstruction(OpCodes.Ldloc_S, 3),

// result
new (OpCodes.Ldloc_S, 2),

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

// OnSentValidCommand(ev)
new (OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnSentValidCommand))),
});

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

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