diff --git a/CHANGELOG.md b/CHANGELOG.md
index 45456eb2..790b6e71 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* Cleaned up a check in Bouner OnTileEdit where it checks for using the respective item when placing a tile to make it clearer. This change also fixed the issue in a previous commit where valid replace action was caught. Moved the check for max tile/wall types to the beginning of the method. (@Patrikkk)
* Improved clarity for insufficient permission related error messages. (@moisterrific)
* Remove redundant Boulder placement check that prevented placing chests on them, as it is no longer possible to place a chest on a boulder, so nothing crashes the server. "1.2.3: Boulders with Chests on them no longer crash the game if the boulder is hit." (@kevzhao2, @Patrikkk)
+* Adding 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)
## TShock 4.4.0 (Pre-release 11)
* New permission `tshock.tp.pylon` to enable teleporting via Teleportation Pylons (@QuiCM)
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 4a1c90fd..a98385e4 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -152,6 +152,7 @@ namespace TShockAPI
{ PacketTypes.PlayerHurtV2, HandlePlayerDamageV2 },
{ PacketTypes.PlayerDeathV2, HandlePlayerKillMeV2 },
{ PacketTypes.Emoji, HandleEmoji },
+ { PacketTypes.TileEntityDisplayDollItemSync, HandleTileEntityDisplayDollItemSync },
{ PacketTypes.SyncTilePicking, HandleSyncTilePicking },
{ PacketTypes.SyncRevengeMarker, HandleSyncRevengeMarker },
{ PacketTypes.LandGolfBallInCup, HandleLandGolfBallInCup },
@@ -1945,7 +1946,60 @@ namespace TShockAPI
Emoji.Invoke(null, args);
return args.Handled;
}
-
+
+ /// For use in a TileEntityDisplayDollItemSync event.
+ ///
+ public class DisplayDollItemSyncEventArgs : GetDataHandledEventArgs
+ {
+ ///
+ /// The player index in the packet who modifies the DisplayDoll item slot.
+ ///
+ public byte PlayerIndex { get; set; }
+ ///
+ /// The ID of the TileEntity that is being modified.
+ ///
+ public int TileEntityID { get; set; }
+ ///
+ /// The slot of the DisplayDoll that is being modified.
+ ///
+ public int Slot { get; set; }
+ ///
+ /// Wether or not the slot that is being modified is a Dye slot.
+ ///
+ public bool IsDye { get; set; }
+ ///
+ /// The current item that is present in the slot before the modification.
+ ///
+ public Item OldItem { get; set; }
+ ///
+ /// The item that is about to replace the OldItem in the slot that is being modified.
+ ///
+ public Item NewItem { get; set; }
+ }
+ ///
+ /// Called when a player modifies a DisplayDoll (Mannequin) item slot.
+ ///
+ public static HandlerList DisplayDollItemSync = new HandlerList();
+ private static bool OnDisplayDollItemSync(TSPlayer player, MemoryStream data, byte playerIndex, int tileEntityID, int slot, bool isDye, Item oldItem, Item newItem)
+ {
+ if (DisplayDollItemSync == null)
+ return false;
+
+ var args = new DisplayDollItemSyncEventArgs
+ {
+ Player = player,
+ Data = data,
+ PlayerIndex = playerIndex,
+ TileEntityID = tileEntityID,
+ Slot = slot,
+ IsDye = isDye,
+ OldItem = oldItem,
+ NewItem = newItem
+ };
+ DisplayDollItemSync.Invoke(null, args);
+ return args.Handled;
+ }
+
///
/// For use in a LandBallInCup event.
///
@@ -3703,6 +3757,49 @@ namespace TShockAPI
return false;
}
+ private static bool HandleTileEntityDisplayDollItemSync(GetDataHandlerArgs args)
+ {
+ byte playerIndex = args.Data.ReadInt8();
+ int tileEntityID = args.Data.ReadInt32();
+ int slot = args.Data.ReadByte();
+ bool isDye = false;
+ if (slot >= 8)
+ {
+ isDye = true;
+ slot -= 8;
+ }
+
+ Item newItem = new Item();
+ Item oldItem = new Item();
+
+ if (!TileEntity.ByID.TryGetValue(tileEntityID, out TileEntity tileEntity))
+ return false;
+
+ TEDisplayDoll displayDoll = tileEntity as TEDisplayDoll;
+ if (displayDoll != null)
+ {
+ oldItem = displayDoll._items[slot];
+ if (isDye)
+ oldItem = displayDoll._dyes[slot];
+
+ ushort itemType = args.Data.ReadUInt16();
+ ushort stack = args.Data.ReadUInt16();
+ int prefix = args.Data.ReadByte();
+
+ newItem.SetDefaults(itemType);
+ newItem.stack = stack;
+ newItem.Prefix(prefix);
+
+ if (oldItem.type == 0 && newItem.type == 0)
+ return false;
+ }
+
+ if (OnDisplayDollItemSync(args.Player, args.Data, playerIndex, tileEntityID, slot, isDye, oldItem, newItem))
+ return true;
+
+ return false;
+ }
+
private static bool HandleSyncTilePicking(GetDataHandlerArgs args)
{
byte playerIndex = args.Data.ReadInt8();