From 229c6c7784a0eaf07094156a387ca0eb03aa7085 Mon Sep 17 00:00:00 2001
From: Rysik5318 <72207886+Rysik5318@users.noreply.github.com>
Date: Sat, 7 Dec 2024 19:43:20 +0400
Subject: [PATCH] Added Emotion Events and Player.Emotion (#257)
* SigmoEmotionPatchAdd
* Oops
* Oops
* Fucking Exiled Dev CI / build
* Update Player.cs
* Update EXILED/Exiled.Events/Handlers/Player.cs
Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com>
* Update EXILED/Exiled.Events/Handlers/Player.cs
* Sigmoemotionadd (#11)
* Say hi to transpilers
* Update Emotion.cs
* Allows setting emotion
* missing dup
---------
Co-authored-by: Misaka-ZeroTwo <45165615+Misaka-ZeroTwo@users.noreply.github.com>
Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com>
Co-authored-by: VALERA771 <72030575+VALERA771@users.noreply.github.com>
---
EXILED/Exiled.API/Features/Player.cs | 10 +++
.../Player/ChangedEmotionEventArgs.cs | 38 ++++++++
.../Player/ChangingEmotionEventArgs.cs | 50 +++++++++++
EXILED/Exiled.Events/Handlers/Player.cs | 22 +++++
.../Patches/Events/Player/Emotion.cs | 87 +++++++++++++++++++
5 files changed, 207 insertions(+)
create mode 100644 EXILED/Exiled.Events/EventArgs/Player/ChangedEmotionEventArgs.cs
create mode 100644 EXILED/Exiled.Events/EventArgs/Player/ChangingEmotionEventArgs.cs
create mode 100644 EXILED/Exiled.Events/Patches/Events/Player/Emotion.cs
diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs
index 788493ca9..3251d1b34 100644
--- a/EXILED/Exiled.API/Features/Player.cs
+++ b/EXILED/Exiled.API/Features/Player.cs
@@ -47,6 +47,7 @@ namespace Exiled.API.Features
using Mirror.LiteNetLib4Mirror;
using PlayerRoles;
using PlayerRoles.FirstPersonControl;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
using PlayerRoles.RoleAssign;
using PlayerRoles.Spectating;
using PlayerRoles.Voice;
@@ -732,6 +733,15 @@ public bool IsBypassModeEnabled
set => ReferenceHub.serverRoles.BypassMode = value;
}
+ ///
+ /// Gets or sets the player's emotion.
+ ///
+ public EmotionPresetType Emotion
+ {
+ get => EmotionSync.GetEmotionPreset(ReferenceHub);
+ set => EmotionSync.ServerSetEmotionPreset(ReferenceHub, value);
+ }
+
///
/// Gets or sets a value indicating whether the player is muted.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangedEmotionEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangedEmotionEventArgs.cs
new file mode 100644
index 000000000..cd5e3447a
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangedEmotionEventArgs.cs
@@ -0,0 +1,38 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Player
+{
+ using Exiled.API.Features;
+ using Exiled.Events.EventArgs.Interfaces;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
+
+ ///
+ /// Contains all the information after the player's emotion.
+ ///
+ public class ChangedEmotionEventArgs : IPlayerEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public ChangedEmotionEventArgs(ReferenceHub hub, EmotionPresetType emotionPresetType)
+ {
+ Player = Player.Get(hub);
+ EmotionPresetType = emotionPresetType;
+ }
+
+ ///
+ /// Gets the player's emotion.
+ ///
+ public EmotionPresetType EmotionPresetType { get; }
+
+ ///
+ public Player Player { get; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangingEmotionEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangingEmotionEventArgs.cs
new file mode 100644
index 000000000..759f1fa9e
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangingEmotionEventArgs.cs
@@ -0,0 +1,50 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Player
+{
+ using Exiled.API.Features;
+ using Exiled.Events.EventArgs.Interfaces;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
+
+ ///
+ /// Contains all the information before the player's emotion changes.
+ ///
+ public class ChangingEmotionEventArgs : IDeniableEvent, IPlayerEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ChangingEmotionEventArgs(ReferenceHub hub, EmotionPresetType newEmotionPresetType, EmotionPresetType oldEmotionPresetType, bool isAllowed = true)
+ {
+ Player = Player.Get(hub);
+ NewEmotionPresetType = newEmotionPresetType;
+ OldEmotionPresetType = oldEmotionPresetType;
+ IsAllowed = isAllowed;
+ }
+
+ ///
+ public bool IsAllowed { get; set; }
+
+ ///
+ /// Gets the old player's emotion.
+ ///
+ public EmotionPresetType OldEmotionPresetType { get; }
+
+ ///
+ /// Gets or sets the new player's emotion.
+ ///
+ public EmotionPresetType NewEmotionPresetType { get; set; }
+
+ ///
+ public Player Player { get; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Handlers/Player.cs b/EXILED/Exiled.Events/Handlers/Player.cs
index 581b10014..af69cf807 100644
--- a/EXILED/Exiled.Events/Handlers/Player.cs
+++ b/EXILED/Exiled.Events/Handlers/Player.cs
@@ -549,6 +549,28 @@ public class Player
///
public static Event ChangingNickname { get; set; } = new();
+ ///
+ /// Invoked before a player's emotion changed.
+ ///
+ public static Event ChangingEmotion { get; set; } = new();
+
+ ///
+ /// Invoked after a player's emotion changed.
+ ///
+ public static Event ChangedEmotion { get; set; } = new();
+
+ ///
+ /// Called before a player's emotion changed.
+ ///
+ /// The instance.
+ public static void OnChangingEmotion(ChangingEmotionEventArgs ev) => ChangingEmotion.InvokeSafely(ev);
+
+ ///
+ /// Called after a player's emotion changed.
+ ///
+ /// The instance.
+ public static void OnChangedEmotion(ChangedEmotionEventArgs ev) => ChangedEmotion.InvokeSafely(ev);
+
///
/// Called before reserved slot is resolved for a .
///
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Emotion.cs b/EXILED/Exiled.Events/Patches/Events/Player/Emotion.cs
new file mode 100644
index 000000000..a7d447569
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Player/Emotion.cs
@@ -0,0 +1,87 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Player
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Player;
+ using HarmonyLib;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches .
+ /// Adds the event and
+ /// event.
+ ///
+ [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ChangingEmotion))]
+ [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ChangedEmotion))]
+ [HarmonyPatch(typeof(EmotionSync), nameof(EmotionSync.ServerSetEmotionPreset))]
+ internal static class Emotion
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label ret = generator.DefineLabel();
+ LocalBuilder ev = generator.DeclareLocal(typeof(ChangingEmotionEventArgs));
+
+ int index = newInstructions.FindIndex(x => x.opcode == OpCodes.Ldsfld);
+
+ newInstructions.InsertRange(index, new CodeInstruction[]
+ {
+ // ChangingEmotionEventArgs ev = new(hub, preset, EmotionSync.GetEmotionPreset(hub), true);
+ new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(newInstructions[index]),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Call, Method(typeof(EmotionSync), nameof(EmotionSync.GetEmotionPreset))),
+ new(OpCodes.Ldc_I4_1),
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangingEmotionEventArgs))[0]),
+ new(OpCodes.Dup),
+ new(OpCodes.Dup),
+ new(OpCodes.Stloc_S, ev),
+
+ // Handlers.Player.OnChangingEmotion(ev);
+ new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnChangingEmotion))),
+
+ // if (!ev.IsAllowed)
+ // return;
+ new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingEmotionEventArgs), nameof(ChangingEmotionEventArgs.IsAllowed))),
+ new(OpCodes.Brfalse, ret),
+
+ // preset = ev.EmotionPresetTypeNew
+ new(OpCodes.Ldloc_S, ev),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingEmotionEventArgs), nameof(ChangingEmotionEventArgs.NewEmotionPresetType))),
+ new(OpCodes.Starg_S, 1),
+ });
+
+ newInstructions.InsertRange(newInstructions.Count - 1, new CodeInstruction[]
+ {
+ // ChangedEmotionEventArgs ev = new(hub, EmotionSync.GetEmotionPreset(hub));
+ new CodeInstruction(OpCodes.Ldarg_0),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Call, Method(typeof(EmotionSync), nameof(EmotionSync.GetEmotionPreset))),
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangedEmotionEventArgs))[0]),
+
+ // Handlers.Player.OnChangedEmotion(ev);
+ new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnChangedEmotion))),
+ });
+
+ newInstructions[newInstructions.Count - 1].labels.Add(ret);
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}