diff --git a/CHANGELOG.md b/CHANGELOG.md
index a56d0083d..c930f1f0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,6 +42,9 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* `/who` - Changed the display format of the online players when the `-i` flag is used. From `PlayerName (ID: 0, ID: 0)` to `PlayerName (Index: 0, Account ID: 0)` for clarification. (@Patrikkk)
* Added DisplayDollItemSync event. An event that is called when a player modifies the slot of a DisplayDoll (Mannequin). This event provides information about the current item in the displaydoll, as well as the item that the player is about to set. (@Patrikkk)
* Added DisplayDollItemSyncHandler, which checks for building permissions of the player at the position of the DisplayDoll. (If they do not have permissions, it means they are hacking as they could not even open the doll in the first place.) (@Patrikkk)
+* Added RequestTileEntity packet handling. (@Patrikkk)
+ * Implemented the OnRequestTileEntityInteraction even hook in GetDataHandler. (@Patrikkk)
+ * Created RequestTileEntityInteractionHandler which checks for building permissions when the player is attempting to open a display doll (Mannequin) or a Hat Rack. This now prevents players from opening a Mannequin or a Hat Rack if they have no building permissions at the position of these tile entities. As of 1.4.0.5, these are the only two items that use this packet. (@Patrikkk)
## TShock 4.4.0 (Pre-release 11)
* Added new permission `tshock.tp.pylon` to enable teleporting via Teleportation Pylons (@QuiCM)
diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs
index dcc499605..9b5e79c54 100644
--- a/TShockAPI/Bouncer.cs
+++ b/TShockAPI/Bouncer.cs
@@ -40,6 +40,7 @@ internal sealed class Bouncer
internal Handlers.NetModules.NetModulePacketHandler NetModuleHandler { get; set; }
internal Handlers.EmojiHandler EmojiHandler { get; set; }
internal Handlers.DisplayDollItemSyncHandler DisplayDollItemSyncHandler { get; set; }
+ internal Handlers.RequestTileEntityInteractionHandler RequestTileEntityInteractionHandler { get; set; }
internal Handlers.LandGolfBallInCupHandler LandGolfBallInCupHandler { get; set; }
internal Handlers.SyncTilePickingHandler SyncTilePickingHandler { get; set; }
@@ -53,11 +54,14 @@ internal Bouncer()
NetModuleHandler = new Handlers.NetModules.NetModulePacketHandler();
GetDataHandlers.ReadNetModule += NetModuleHandler.OnReceive;
+ EmojiHandler = new Handlers.EmojiHandler();
+ GetDataHandlers.Emoji += EmojiHandler.OnReceive;
+
DisplayDollItemSyncHandler = new Handlers.DisplayDollItemSyncHandler();
GetDataHandlers.DisplayDollItemSync += DisplayDollItemSyncHandler.OnReceive;
- EmojiHandler = new Handlers.EmojiHandler();
- GetDataHandlers.Emoji += EmojiHandler.OnReceive;
+ RequestTileEntityInteractionHandler = new Handlers.RequestTileEntityInteractionHandler();
+ GetDataHandlers.RequestTileEntityInteraction += RequestTileEntityInteractionHandler.OnReceive;
LandGolfBallInCupHandler = new Handlers.LandGolfBallInCupHandler();
GetDataHandlers.LandGolfBallInCup += LandGolfBallInCupHandler.OnReceive;
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index ace294d61..788b63ab1 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -153,6 +153,7 @@ public static void InitGetDataHandler()
{ PacketTypes.PlayerDeathV2, HandlePlayerKillMeV2 },
{ PacketTypes.Emoji, HandleEmoji },
{ PacketTypes.TileEntityDisplayDollItemSync, HandleTileEntityDisplayDollItemSync },
+ { PacketTypes.RequestTileEntityInteraction, HandleRequestTileEntityInteraction },
{ PacketTypes.SyncTilePicking, HandleSyncTilePicking },
{ PacketTypes.SyncRevengeMarker, HandleSyncRevengeMarker },
{ PacketTypes.LandGolfBallInCup, HandleLandGolfBallInCup },
@@ -1871,49 +1872,6 @@ private static bool OnKillMe(TSPlayer player, MemoryStream data, byte plr, byte
return args.Handled;
}
- ///
- /// For use in a SyncTilePicking event.
- ///
- public class SyncTilePickingEventArgs : GetDataHandledEventArgs
- {
- ///
- /// The player index in the packet, who sends the tile picking data.
- ///
- public byte PlayerIndex { get; set; }
- ///
- /// The X world position of the tile that is being picked.
- ///
- public short TileX { get; set; }
- ///
- /// The Y world position of the tile that is being picked.
- ///
- public short TileY { get; set; }
- ///
- /// The damage that is being dealt on the tile.
- ///
- public byte TileDamage { get; set; }
- }
- ///
- /// Called when a player hits and damages a tile.
- ///
- public static HandlerList SyncTilePicking = new HandlerList();
- private static bool OnSyncTilePicking(TSPlayer player, MemoryStream data, byte playerIndex, short tileX, short tileY, byte tileDamage)
- {
- if (SyncTilePicking == null)
- return false;
-
- var args = new SyncTilePickingEventArgs
- {
- PlayerIndex = playerIndex,
- TileX = tileX,
- TileY = tileY,
- TileDamage = tileDamage
- };
- SyncTilePicking.Invoke(null, args);
- return args.Handled;
- }
-
-
/// For use in an Emoji event.
///
public class EmojiEventArgs : GetDataHandledEventArgs
@@ -2005,6 +1963,81 @@ private static bool OnDisplayDollItemSync(TSPlayer player, MemoryStream data, by
return args.Handled;
}
+ /// For use in an OnRequestTileEntityInteraction event.
+ ///
+ public class RequestTileEntityInteractionEventArgs : GetDataHandledEventArgs
+ {
+ ///
+ /// The TileEntity object that the player is requesting interaction with.
+ ///
+ public TileEntity TileEntity { get; set; }
+ ///
+ /// The player index in the packet who requests interaction with the TileEntity.
+ ///
+ public byte PlayerIndex { get; set; }
+ }
+ ///
+ /// Called when a player requests interaction with a TileEntity.
+ ///
+ public static HandlerList RequestTileEntityInteraction = new HandlerList();
+ private static bool OnRequestTileEntityInteraction(TSPlayer player, MemoryStream data, TileEntity tileEntity, byte playerIndex)
+ {
+ if (RequestTileEntityInteraction == null)
+ return false;
+
+ var args = new RequestTileEntityInteractionEventArgs
+ {
+ Player = player,
+ Data = data,
+ PlayerIndex = playerIndex,
+ TileEntity = tileEntity
+ };
+ RequestTileEntityInteraction.Invoke(null, args);
+ return args.Handled;
+ }
+
+ ///
+ /// For use in a SyncTilePicking event.
+ ///
+ public class SyncTilePickingEventArgs : GetDataHandledEventArgs
+ {
+ ///
+ /// The player index in the packet, who sends the tile picking data.
+ ///
+ public byte PlayerIndex { get; set; }
+ ///
+ /// The X world position of the tile that is being picked.
+ ///
+ public short TileX { get; set; }
+ ///
+ /// The Y world position of the tile that is being picked.
+ ///
+ public short TileY { get; set; }
+ ///
+ /// The damage that is being dealt on the tile.
+ ///
+ public byte TileDamage { get; set; }
+ }
+ ///
+ /// Called when a player hits and damages a tile.
+ ///
+ public static HandlerList SyncTilePicking = new HandlerList();
+ private static bool OnSyncTilePicking(TSPlayer player, MemoryStream data, byte playerIndex, short tileX, short tileY, byte tileDamage)
+ {
+ if (SyncTilePicking == null)
+ return false;
+
+ var args = new SyncTilePickingEventArgs
+ {
+ PlayerIndex = playerIndex,
+ TileX = tileX,
+ TileY = tileY,
+ TileDamage = tileDamage
+ };
+ SyncTilePicking.Invoke(null, args);
+ return args.Handled;
+ }
+
///
/// For use in a LandBallInCup event.
///
@@ -3804,6 +3837,20 @@ private static bool HandleTileEntityDisplayDollItemSync(GetDataHandlerArgs args)
return false;
}
+ private static bool HandleRequestTileEntityInteraction(GetDataHandlerArgs args)
+ {
+ int tileEntityID = args.Data.ReadInt32();
+ byte playerIndex = args.Data.ReadInt8();
+
+ if (!TileEntity.ByID.TryGetValue(tileEntityID, out TileEntity tileEntity))
+ return false;
+
+ if (OnRequestTileEntityInteraction(args.Player, args.Data, tileEntity, playerIndex))
+ return true;
+
+ return false;
+ }
+
private static bool HandleSyncTilePicking(GetDataHandlerArgs args)
{
byte playerIndex = args.Data.ReadInt8();
diff --git a/TShockAPI/Handlers/RequestTileEntityInteractionHandler.cs b/TShockAPI/Handlers/RequestTileEntityInteractionHandler.cs
new file mode 100644
index 000000000..b2505307b
--- /dev/null
+++ b/TShockAPI/Handlers/RequestTileEntityInteractionHandler.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Terraria;
+using Terraria.DataStructures;
+using Terraria.GameContent.Tile_Entities;
+using static TShockAPI.GetDataHandlers;
+
+namespace TShockAPI.Handlers
+{
+ ///
+ ///
+ ///
+ public class RequestTileEntityInteractionHandler : IPacketHandler
+ {
+ public void OnReceive(object sender, RequestTileEntityInteractionEventArgs args)
+ {
+ if (args.TileEntity is TEHatRack && !args.Player.HasBuildPermissionForTileObject(args.TileEntity.Position.X, args.TileEntity.Position.Y, TEHatRack.entityTileWidth, TEHatRack.entityTileHeight, false))
+ {
+ args.Player.SendErrorMessage("You do not have permission to modify a Hat Rack in a protected area!");
+ args.Handled = true;
+ return;
+ }
+ else if (args.TileEntity is TEDisplayDoll && !args.Player.HasBuildPermissionForTileObject(args.TileEntity.Position.X, args.TileEntity.Position.Y, TEDisplayDoll.entityTileWidth, TEDisplayDoll.entityTileHeight, false))
+ {
+ args.Player.SendErrorMessage("You do not have permission to modify a Mannequin in a protected area!");
+ args.Handled = true;
+ return;
+ }
+ else if (!args.Player.HasBuildPermission(args.TileEntity.Position.X, args.TileEntity.Position.Y, false))
+ {
+ args.Player.SendErrorMessage("You do not have permission to modify a TileEntity in a protected area!");
+ TShock.Log.ConsoleDebug($"RequestTileEntityInteractionHandler: Rejected packet due to lack of building permissions! - From {args.Player.Name} | Position X:{args.TileEntity.Position.X} Y:{args.TileEntity.Position.Y}, TileEntity type: {args.TileEntity.type}, Tile type: {Main.tile[args.TileEntity.Position.X, args.TileEntity.Position.Y].type}");
+ args.Handled = true;
+ return;
+ }
+ }
+ }
+}
diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj
index 3afe3d0d6..0b072be8b 100644
--- a/TShockAPI/TShockAPI.csproj
+++ b/TShockAPI/TShockAPI.csproj
@@ -100,6 +100,7 @@
+