Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 72 additions & 8 deletions TShockAPI/Bouncer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ internal Bouncer()
GetDataHandlers.KillMe += OnKillMe;
GetDataHandlers.FishOutNPC += OnFishOutNPC;
GetDataHandlers.FoodPlatterTryPlacing += OnFoodPlatterTryPlacing;
GetDataHandlers.DisplayJarTryPlacing += OnDisplayJarTryPlacing;
OTAPI.Hooks.Chest.QuickStack += OnQuickStack;


Expand Down Expand Up @@ -649,6 +650,15 @@ internal void OnTileEdit(object sender, GetDataHandlers.TileEditEventArgs args)
}
}

if (tile.type == TileID.DeadCellsDisplayJar)
{
var displayJar = TEDeadCellsDisplayJar.Find(tileX - tile.frameX % 18 / 18, tileY - tile.frameY % 32 / 18);
if (displayJar != -1)
{
NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, displayJar, 0, 1);
}
}

GetRollbackRectSize(tileX, tileY, out byte width, out byte length, out int offsetY);
args.Player.SendTileRect((short)(tileX - width), (short)(tileY + offsetY), (byte)(width * 2), (byte)(length + 1));
args.Handled = true;
Expand Down Expand Up @@ -751,13 +761,15 @@ internal void OnTileEdit(object sender, GetDataHandlers.TileEditEventArgs args)
// Item frames can be modified without pickaxe tile.
// also add an exception for snake coils, they can be removed when the player places a new one or after x amount of time
// If the tile is part of the breakable when placing set, it might be getting broken by a placement.
else if (tile.type != TileID.ItemFrame && tile.type != TileID.MysticSnakeRope
&& !ItemID.Sets.Explosives[selectedItem.type]
&& !TileID.Sets.BreakableWhenPlacing[tile.type]
&& !Main.tileAxe[tile.type] && !Main.tileHammer[tile.type] && tile.wall == 0
&& selectedItem.pick == 0 && selectedItem.type != ItemID.GravediggerShovel
&& args.Player.TPlayer.mount.Type != MountID.Drill
&& args.Player.TPlayer.mount.Type != MountID.DiggingMoleMinecart)
else if (tile.type != TileID.ItemFrame &&
tile.type != TileID.DeadCellsDisplayJar &&
tile.type != TileID.MysticSnakeRope &&
!ItemID.Sets.Explosives[selectedItem.type] &&
!TileID.Sets.BreakableWhenPlacing[tile.type] &&
!Main.tileAxe[tile.type] && !Main.tileHammer[tile.type] && tile.wall == 0 &&
selectedItem.pick == 0 && selectedItem.type != ItemID.GravediggerShovel &&
args.Player.TPlayer.mount.Type != MountID.Drill &&
args.Player.TPlayer.mount.Type != MountID.DiggingMoleMinecart)
{
if (args.Player.TPlayer.ownedProjectileCounts[ProjectileID.PalworldDigtoise] > 0)
{
Expand Down Expand Up @@ -3004,7 +3016,7 @@ internal void OnFoodPlatterTryPlacing(object sender, GetDataHandlers.FoodPlatter
return;
}

if (!args.Player.IsInRange(args.TileX, args.TileY, range: 13)) // To my knowledge, max legit tile reach with accessories.
if (!args.Player.IsInRange(args.TileX, args.TileY))
{
TShock.Log.ConsoleDebug(GetString("Bouncer / OnFoodPlatterTryPlacing rejected range checks from {0}", args.Player.Name));
args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1);
Expand All @@ -3013,6 +3025,58 @@ internal void OnFoodPlatterTryPlacing(object sender, GetDataHandlers.FoodPlatter
}
}

/// <summary>
/// Called when a player is trying to place an item into a display jar.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
internal void OnDisplayJarTryPlacing(object sender, GetDataHandlers.DisplayJarTryPlacingEventArgs args)
{
if (!TShock.Utils.TilePlacementValid(args.TileX, args.TileY))
{
TShock.Log.ConsoleDebug(GetString("Bouncer / OnDisplayJarTryPlacing rejected tile placement valid from {0}", args.Player.Name));
args.Handled = true;
return;
}

if ((args.Player.SelectedItem.type != args.ItemID && args.Player.ItemInHand.type != args.ItemID))
{
TShock.Log.ConsoleDebug(GetString("Bouncer / OnDisplayJarTryPlacing rejected item not placed by hand from {0}", args.Player.Name));
args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}
if (args.Player.IsBeingDisabled())
{
TShock.Log.ConsoleDebug(GetString("Bouncer / OnDisplayJarTryPlacing rejected disabled from {0}", args.Player.Name));
Item item = new Item();
item.netDefaults(args.ItemID);
args.Player.GiveItemCheck(args.ItemID, item.Name, args.Stack, args.Prefix);
args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}

if (!args.Player.HasBuildPermission(args.TileX, args.TileY))
{
TShock.Log.ConsoleDebug(GetString("Bouncer / OnDisplayJarTryPlacing rejected permissions from {0}", args.Player.Name));
Item item = new Item();
item.netDefaults(args.ItemID);
args.Player.GiveItemCheck(args.ItemID, item.Name, args.Stack, args.Prefix);
args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}

if (!args.Player.IsInRange(args.TileX, args.TileY))
{
TShock.Log.ConsoleDebug(GetString("Bouncer / OnDisplayJarTryPlacing rejected range checks from {0}", args.Player.Name));
args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}
}

/// <summary>
/// Called when a player is trying to put an item into chest through Quick Stack.
/// </summary>
Expand Down
64 changes: 63 additions & 1 deletion TShockAPI/GetDataHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ public static void InitGetDataHandler()
{ PacketTypes.FoodPlatterTryPlacing, HandleFoodPlatterTryPlacing },
{ PacketTypes.SyncCavernMonsterType, HandleSyncCavernMonsterType },
{ PacketTypes.SyncLoadout, HandleSyncLoadout },
{ PacketTypes.TeamChangeFromUI, HandlePlayerTeam } // Same packet as PlayerTeam
{ PacketTypes.TeamChangeFromUI, HandlePlayerTeam }, // Same packet as PlayerTeam
{ PacketTypes.TEDeadCellsDisplayJar, HandleDisplayJar }
};
}

Expand Down Expand Up @@ -2498,6 +2499,52 @@ private static bool OnFoodPlatterTryPlacing(TSPlayer player, MemoryStream data,
return args.Handled;
}

public class DisplayJarTryPlacingEventArgs : GetDataHandledEventArgs
{
/// <summary>
/// The X tile position of the placement action.
/// </summary>
public ushort TileX { get; set; }
/// <summary>
/// The Y tile position of the placement action.
/// </summary>
public ushort TileY { get; set; }
/// <summary>
/// The Item ID that is being placed in the display jar.
/// </summary>
public short ItemID { get; set; }
/// <summary>
/// The prefix of the item that is being placed in the display jar.
/// </summary>
public byte Prefix { get; set; }
/// <summary>
/// The stack of the item that is being placed in the display jar.
/// </summary>
public short Stack { get; set; }
}
/// <summary>
/// Called when a player is placing an item in a display jar.
/// </summary>
public static HandlerList<DisplayJarTryPlacingEventArgs> DisplayJarTryPlacing = new HandlerList<DisplayJarTryPlacingEventArgs>();
private static bool OnDisplayJarTryPlacing(TSPlayer player, MemoryStream data, ushort tileX, ushort tileY, short itemID, byte prefix, short stack)
{
if (DisplayJarTryPlacing == null)
return false;

var args = new DisplayJarTryPlacingEventArgs
{
Player = player,
Data = data,
TileX = tileX,
TileY = tileY,
ItemID = itemID,
Prefix = prefix,
Stack = stack,
};
DisplayJarTryPlacing.Invoke(null, args);
return args.Handled;
}

/// <summary>
/// Used when a net module is loaded
/// </summary>
Expand Down Expand Up @@ -4805,6 +4852,21 @@ Tuple<int, int> GetDyeSlotsForLoadoutIndex(int index)
return false;
}

private static bool HandleDisplayJar(GetDataHandlerArgs args)
{
ushort tileX = args.Data.ReadUInt16();
ushort tileY = args.Data.ReadUInt16();
short itemID = args.Data.ReadInt16();
byte prefix = args.Data.ReadInt8();
short stack = args.Data.ReadInt16();

if (OnDisplayJarTryPlacing(args.Player, args.Data, tileX, tileY, itemID, prefix, stack))
return true;

return false;
}


public enum DoorAction
{
OpenDoor = 0,
Expand Down
19 changes: 19 additions & 0 deletions TShockAPI/Handlers/SendTileRectHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,24 @@ public static TileRectMatch Removal(int width, int height, ushort tileType)
/// <returns><see langword="true"/>, if the rect matches this operation and the changes have been applied, otherwise <see langword="false"/>.</returns>
public MatchResult Matches(TSPlayer player, TileRect rect)
{
// DeadCellsDisplayJar is a 1x2 rect, but the client sends a 2x2 tile rect; only the first column is relevant.
if (TileType == TileID.DeadCellsDisplayJar)
{
if (rect.Width != 2)
{
return MatchResult.NotMatched;
}

var newTiles = new NetTile[1, rect.Height];

for (var y = 0; y < rect.Height; y++)
{
newTiles[0, y] = rect[0, y];
}

rect = new TileRect(newTiles, rect.X, rect.Y, 1, rect.Height);
}

if (rect.Width != Width || rect.Height != Height)
{
return MatchResult.NotMatched;
Expand Down Expand Up @@ -378,6 +396,7 @@ private MatchResult MatchRemoval(TSPlayer player, TileRect rect)
TileRectMatch.Placement(1, 1, TileID.LogicSensor, 18, 108, 18, 18),
TileRectMatch.Placement(1, 1, TileID.KiteAnchor, 72, 0, 18, 18),
TileRectMatch.Placement(1, 1, TileID.CritterAnchor, 72, 72, 18, 18),
TileRectMatch.Placement(1, 2, TileID.DeadCellsDisplayJar, 36, 18, 18, 18),

TileRectMatch.StateChangeY(3, 2, TileID.Campfire, 54, 18),
TileRectMatch.StateChangeY(4, 3, TileID.Cannon, 468, 18),
Expand Down
Loading