diff --git a/CHANGELOG.md b/CHANGELOG.md
index e48fd0cc..226bcfe0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -80,6 +80,7 @@ Putting this stuff down here so things don't conflict as often.
* Added `GetDataHandlers.MassWireOperation` hook and related arguments. (@hakusaro)
* Added `GetDataHandlers.PlaceTileEntity` hook and related arguments. (@hakusaro)
* Added `TSPlayer` to `GetDataHandlers.GemLockToggle`. (@hakusaro)
+* Added `GetDataHandlers.PlaceItemFrame` hook and related arguments. (@hakusaro)
## TShock 4.3.25
* Fixed a critical exploit in the Terraria protocol that could cause massive unpreventable world corruption as well as a number of other problems. Thanks to @bartico6 for reporting. Fixed by the efforts of @QuiCM, @hakusaro, and tips in the right directioon from @bartico6.
diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs
index d29b94ae..ae522e19 100644
--- a/TShockAPI/Bouncer.cs
+++ b/TShockAPI/Bouncer.cs
@@ -29,6 +29,7 @@ using static TShockAPI.GetDataHandlers;
using TerrariaApi.Server;
using Terraria.ObjectData;
using Terraria.DataStructures;
+using Terraria.Localization;
namespace TShockAPI
{
@@ -41,6 +42,7 @@ namespace TShockAPI
{
// Setup hooks
+ GetDataHandlers.PlaceItemFrame.Register(OnPlaceItemFrame);
GetDataHandlers.GemLockToggle.Register(OnGemLockToggle);
GetDataHandlers.PlaceTileEntity.Register(OnPlaceTileEntity);
GetDataHandlers.PlayerAnimation.Register(OnPlayerAnimation);
@@ -62,6 +64,33 @@ namespace TShockAPI
GetDataHandlers.TileEdit.Register(OnTileEdit);
}
+ /// Fired when an item frame is placed for anti-cheat detection.
+ /// The object that triggered the event.
+ /// The packet arguments that the event has.
+ internal void OnPlaceItemFrame(object sender, GetDataHandlers.PlaceItemFrameEventArgs args)
+ {
+ if (TShock.CheckIgnores(args.Player))
+ {
+ NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, args.ItemFrame.ID, 0, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (TShock.CheckTilePermission(args.Player, args.X, args.Y))
+ {
+ NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, args.ItemFrame.ID, 0, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (TShock.CheckRangePermission(args.Player, args.X, args.Y))
+ {
+ NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, args.ItemFrame.ID, 0, 1);
+ args.Handled = true;
+ return;
+ }
+ }
+
/// Handles the anti-cheat components of gem lock toggles.
/// The object that triggered the event.
/// The packet arguments that the event has.
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 8e10eb98..82ef08c4 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -3075,6 +3075,54 @@ namespace TShockAPI
return false;
}
+ /// The arguments to the PlaceItemFrame event.
+ public class PlaceItemFrameEventArgs : HandledEventArgs
+ {
+ /// The TSPlayer that triggered the event.
+ public TSPlayer Player { get; set; }
+
+ /// The X coordinate of the item frame.
+ public short X { get; set; }
+
+ /// The Y coordinate of the item frame.
+ public short Y { get; set; }
+
+ /// The ItemID of the item frame.
+ public short ItemID { get; set; }
+
+ /// The prefix.
+ public byte Prefix { get; set; }
+
+ /// The stack.
+ public short Stack { get; set; }
+
+ /// The ItemFrame object associated with this event.
+ public TEItemFrame ItemFrame { get; set; }
+ }
+
+ /// Fired when an ItemFrame is placed.
+ public static HandlerList PlaceItemFrame;
+
+ private static bool OnPlaceItemFrame(TSPlayer player, short x, short y, short itemID, byte prefix, short stack, TEItemFrame itemFrame)
+ {
+ if (PlaceItemFrame == null)
+ return false;
+
+ var args = new PlaceItemFrameEventArgs
+ {
+ Player = player,
+ X = x,
+ Y = y,
+ ItemID = itemID,
+ Prefix = prefix,
+ Stack = stack,
+ ItemFrame = itemFrame,
+ };
+
+ PlaceItemFrame.Invoke(null, args);
+ return args.Handled;
+ }
+
///
/// For use with a ToggleGemLock event
///
@@ -3221,21 +3269,8 @@ namespace TShockAPI
var stack = args.Data.ReadInt16();
var itemFrame = (TEItemFrame)TileEntity.ByID[TEItemFrame.Find(x, y)];
- if (TShock.CheckIgnores(args.Player))
+ if (OnPlaceItemFrame(args.Player, x, y, itemID, prefix, stack, itemFrame))
{
- NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, itemFrame.ID, 0, 1);
- return true;
- }
-
- if (TShock.CheckTilePermission(args.Player, x, y))
- {
- NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, itemFrame.ID, 0, 1);
- return true;
- }
-
- if (TShock.CheckRangePermission(args.Player, x, y))
- {
- NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, itemFrame.ID, 0, 1);
return true;
}