From 69f232b12a5aa4cc6e0b6621bb155f2f744eff14 Mon Sep 17 00:00:00 2001 From: Patrikkk Date: Fri, 19 Jun 2020 14:07:39 +0200 Subject: [PATCH] Adding DisplayDollItemSync event. An event that is called when a player modifies the slot of a DisplayDoll (Mannequin). I was trying to think from a developer friendly perspective here. Instead of passing seperate variables for type/stack/prefix, thought I pass an Item object. As well as, instead of having devs who work with this hook figure out and implement how to get the Item of the DisplayDoll, I just provide it in the hook. I can imagine this being used for creative purposes in plugins. --- CHANGELOG.md | 1 + TShockAPI/GetDataHandlers.cs | 99 +++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) 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();