diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b0c0914..10a852f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
## Upcoming Changes
* New permission `tshock.tp.pylon` to enable teleporting via Teleportation Pylons (@QuiCM)
* New permission `tshock.journey.research` to enable sharing research via item sacrifice (@QuiCM)
+* Add Emoji event to GetDataHandler. This packet is received when a player tries to display an emote.
+ * Adding EmojiHandler to handle an exploit. Adding `tshock.sendemoji` permission and checks. Added this permission to guest group by default.
## TShock 4.4.0 (Pre-release 10)
* Fix all rope coils. (@Olink)
diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs
index 8bf5a11a..b9bb2e05 100644
--- a/TShockAPI/Bouncer.cs
+++ b/TShockAPI/Bouncer.cs
@@ -38,6 +38,7 @@ namespace TShockAPI
{
internal Handlers.SendTileSquareHandler STSHandler { get; set; }
internal Handlers.NetModules.NetModulePacketHandler NetModuleHandler { get; set; }
+ internal Handlers.EmojiHandler EmojiHandler { get; set; }
/// Constructor call initializes Bouncer and related functionality.
/// A new Bouncer.
@@ -49,6 +50,9 @@ namespace TShockAPI
NetModuleHandler = new Handlers.NetModules.NetModulePacketHandler();
GetDataHandlers.ReadNetModule += NetModuleHandler.OnReceive;
+ EmojiHandler = new Handlers.EmojiHandler();
+ GetDataHandlers.Emoji += EmojiHandler.OnReceiveEmoji;
+
// Setup hooks
GetDataHandlers.GetSection += OnGetSection;
GetDataHandlers.PlayerUpdate += OnPlayerUpdate;
diff --git a/TShockAPI/DB/GroupManager.cs b/TShockAPI/DB/GroupManager.cs
index 584ad374..3cff37a1 100644
--- a/TShockAPI/DB/GroupManager.cs
+++ b/TShockAPI/DB/GroupManager.cs
@@ -65,7 +65,8 @@ namespace TShockAPI.DB
Permissions.canpartychat,
Permissions.cantalkinthird,
Permissions.canchat,
- Permissions.synclocalarea));
+ Permissions.synclocalarea,
+ Permissions.sendemoji));
AddDefaultGroup("default", "guest",
string.Join(",",
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index a6c08a50..dee152b5 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -151,6 +151,7 @@ namespace TShockAPI
{ PacketTypes.CrystalInvasionStart, HandleOldOnesArmy },
{ PacketTypes.PlayerHurtV2, HandlePlayerDamageV2 },
{ PacketTypes.PlayerDeathV2, HandlePlayerKillMeV2 },
+ { PacketTypes.Emoji, HandleEmoji },
{ PacketTypes.FishOutNPC, HandleFishOutNPC },
{ PacketTypes.FoodPlatterTryPlacing, HandleFoodPlatterTryPlacing },
{ PacketTypes.SyncRevengeMarker, HandleSyncRevengeMarker }
@@ -1866,6 +1867,40 @@ namespace TShockAPI
return args.Handled;
}
+ ///
+ /// For use in an Emoji event.
+ ///
+ public class EmojiEventArgs : GetDataHandledEventArgs
+ {
+ ///
+ /// The player index in the packet, who sends the emoji.
+ ///
+ public byte PlayerIndex { get; set; }
+ ///
+ /// The ID of the emoji, that is being received.
+ ///
+ public byte EmojiID { get; set; }
+ }
+ ///
+ /// Called when a player sends an emoji.
+ ///
+ public static HandlerList Emoji = new HandlerList();
+ private static bool OnEmoji(TSPlayer player, MemoryStream data, byte playerIndex, byte emojiID)
+ {
+ if (Emoji == null)
+ return false;
+
+ var args = new EmojiEventArgs
+ {
+ Player = player,
+ Data = data,
+ PlayerIndex = playerIndex,
+ EmojiID = emojiID
+ };
+ Emoji.Invoke(null, args);
+ return args.Handled;
+ }
+
///
/// For use in a FishOutNPC event.
///
@@ -3556,6 +3591,17 @@ namespace TShockAPI
return false;
}
+ private static bool HandleEmoji(GetDataHandlerArgs args)
+ {
+ byte playerIndex = args.Data.ReadInt8();
+ byte emojiID = args.Data.ReadInt8();
+
+ if (OnEmoji(args.Player, args.Data, playerIndex, emojiID))
+ return true;
+
+ return false;
+ }
+
private static bool HandleFishOutNPC(GetDataHandlerArgs args)
{
ushort tileX = args.Data.ReadUInt16();
diff --git a/TShockAPI/Handlers/EmojiHandler.cs b/TShockAPI/Handlers/EmojiHandler.cs
new file mode 100644
index 00000000..b21cd53e
--- /dev/null
+++ b/TShockAPI/Handlers/EmojiHandler.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TShockAPI.Handlers
+{
+ ///
+ /// Handles emoji packets and checks for validity and permissions
+ ///
+ public class EmojiHandler
+ {
+ public void OnReceiveEmoji(object sender, GetDataHandlers.EmojiEventArgs args)
+ {
+ if (args.PlayerIndex != args.Player.Index)
+ {
+ TShock.Log.ConsoleError($"EmojiHandler: Emoji packet rejected for ID spoofing. Expected {args.Player.Index}, received {args.PlayerIndex} from {args.Player.Name}.");
+ args.Handled = true;
+ return;
+ }
+
+ if (!args.Player.HasPermission(Permissions.sendemoji))
+ {
+ args.Player.SendErrorMessage("You do not have permission to send emotes!");
+ args.Handled = true;
+ return;
+ }
+ }
+ }
+}
diff --git a/TShockAPI/Permissions.cs b/TShockAPI/Permissions.cs
index 3b401004..643882f8 100644
--- a/TShockAPI/Permissions.cs
+++ b/TShockAPI/Permissions.cs
@@ -474,6 +474,9 @@ namespace TShockAPI
[Description("Player can resync themselves with server state.")]
public static readonly string synclocalarea = "tshock.synclocalarea";
+
+ [Description("Player can send emotes.")]
+ public static readonly string sendemoji = "tshock.sendemoji";
#endregion
///
/// Lists all commands associated with a given permission
diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj
index bc26b96d..fef6f380 100644
--- a/TShockAPI/TShockAPI.csproj
+++ b/TShockAPI/TShockAPI.csproj
@@ -97,6 +97,7 @@
+