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

Open
wants to merge 35 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
70 changes: 70 additions & 0 deletions EXILED/Exiled.Events/EventArgs/Player/SendingCommandEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// -----------------------------------------------------------------------
// <copyright file="SendingCommandEventArgs.cs" company="Exiled Team">
// Copyright (c) Exiled 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 RemoteAdmin;

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

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

/// <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 interface.
/// </summary>
public ICommand Command { get; }
}
}
11 changes: 11 additions & 0 deletions EXILED/Exiled.Events/Handlers/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,11 @@ public class Player
/// </summary>
public static Event<ChangingNicknameEventArgs> ChangingNickname { get; set; } = new();

/// <summary>
/// Invoked before a <see cref="API.Features.Player"/> sended command.
Mar1ki marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
public static Event<SendingCommandEventArgs> SendingCommand { get; set; } = new();

/// <summary>
/// Called before reserved slot is resolved for a <see cref="API.Features.Player"/>.
/// </summary>
Expand Down Expand Up @@ -1164,6 +1169,12 @@ 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"/>'s sended command.
Mar1ki marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
/// <param name="ev">The <see cref="SendingCommandEventArgs"/> instance.</param>
public static void OnSendingCommand(SendingCommandEventArgs ev) => SendingCommand.InvokeSafely(ev);

/// <summary>
/// Called before pre-authenticating a <see cref="API.Features.Player"/>.
/// </summary>
Expand Down
125 changes: 125 additions & 0 deletions EXILED/Exiled.Events/Patches/Events/Player/SendingCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// -----------------------------------------------------------------------
// <copyright file="SendingCommand.cs" company="Exiled Team">
// Copyright (c) Exiled 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="CommandProcessor.ProcessQuery(string, CommandSender)" />.
/// Adds the <see cref="Handlers.Player.SendingCommand" /> event.
/// </summary>
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.SendingCommand))]
[HarmonyPatch(typeof(CommandProcessor), nameof(CommandProcessor.ProcessQuery))]
internal static class SendingCommand
{
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].labels.Add(ret);

LocalBuilder ev = generator.DeclareLocal(typeof(SendingCommandEventArgs));
int offset = 2;
int index = newInstructions.FindIndex(instruction => instruction.Calls(Method(typeof(CommandHandler), nameof(CommandHandler.TryGetCommand)))) + offset;

Label contlabel = generator.DefineLabel();
newInstructions[index].WithLabels(contlabel);

int sendreplyidx = newInstructions.FindIndex(instructions => instructions.Calls(Method(typeof(string), nameof(string.IsNullOrEmpty)))) + offset;

Label sendreply = generator.DefineLabel();
newInstructions[sendreplyidx].WithLabels(sendreply);

newInstructions.InsertRange(
index,
new CodeInstruction[]
{
// sender
new (OpCodes.Ldarg_1),

// Player.get(sender)
new (OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new Type[] { typeof(CommandSender) })),

// command
new (OpCodes.Ldloc_1),

// query
new (OpCodes.Ldarg_0),

// response
new (OpCodes.Ldloc_S, 6),

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

// OnSendingCommad(ev)
new (OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnSendingCommand))),

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

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

// response = ev.Response
new (OpCodes.Ldloc_S, ev.LocalIndex),
new (OpCodes.Callvirt, PropertyGetter(typeof (SendingCommandEventArgs), nameof(SendingCommandEventArgs.Response))),
new (OpCodes.Stloc_S, 6),

// goto sendreply
new (OpCodes.Br, sendreply),
});
offset = -4;
index = newInstructions.FindIndex(instruction => instruction.Calls(Method(typeof(string), nameof(string.ToUpperInvariant)))) + offset;
Label skip = generator.DefineLabel();
newInstructions[index].WithLabels(skip);
newInstructions.InsertRange(
index,
new CodeInstruction[]
{
// if ev.Response.IsNullOrEmpty skip
new (OpCodes.Ldloc_S, ev.LocalIndex),
new (OpCodes.Callvirt, PropertyGetter(typeof (SendingCommandEventArgs), nameof(SendingCommandEventArgs.Response))),
new (OpCodes.Call, Method(typeof(string), nameof(string.IsNullOrEmpty))),
new (OpCodes.Brtrue_S, skip),

// response = ev.Response
new (OpCodes.Ldloc_S, ev.LocalIndex),
new (OpCodes.Callvirt, PropertyGetter(typeof (SendingCommandEventArgs), nameof(SendingCommandEventArgs.Response))),
new (OpCodes.Stloc_S, 6),
});

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

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