diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c321eac..02cdc3b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,7 +13,10 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* `-worldselectpath` is identical to the old `-worldpath`. If you specify `-worldselectpath` and `-world` without specifying an absolute path the server will crash for sure.
* Thank you again to @fjfnaranjo for supplying a [detailed feature request](https://github.com/Pryaxis/TShock/issues/1914) explaining precisely why this option should be available. Without this, we would have had no context as to why this feature was useful or important. Thank you, @fjfnaranjo!
* This change was implemented by (@QuiCM, @hakusaro).
-* Fix kick on hardcore death / kick on mediumcore death / ban on either from taking action against journey mode players. (@hakusaro)
+* Fixed kick on hardcore death / kick on mediumcore death / ban on either from taking action against journey mode players. (@hakusaro)
+* Attempted to fix the problem with the magic mirror spawn problems. You should be able to remove your spawn point in SSC by right clicking on a bed now. (@hakusaro, @AxeelAnder)
+* Added HandleFoodPlatterTryPlacing event, which is called whenever a player places a food in a plate. Add antihack to bouncer, to prevent removing food from plates if the region is protected; To prevent placement if they are not in range; To prevent placement if the item is not placed from player hand. (@Patrikkk)
+* Fixed an offset error in NetTile that impacted `SendTileSquare`. It was being read as a `byte` and not a `ushort`. (@QuiCM)
## TShock 4.4.0 (Pre-release 8)
* Update for OTAPI 2.0.0.36 and Terraria 1.4.0.4. (@hakusaro, @Patrikkk, @DeathCradle)
diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs
index cc8feef8..eab61a0d 100644
--- a/TShockAPI/Bouncer.cs
+++ b/TShockAPI/Bouncer.cs
@@ -67,6 +67,7 @@ namespace TShockAPI
GetDataHandlers.MassWireOperation += OnMassWireOperation;
GetDataHandlers.PlayerDamage += OnPlayerDamage;
GetDataHandlers.KillMe += OnKillMe;
+ GetDataHandlers.FoodPlatterTryPlacing += OnFoodPlatterTryPlacing;
}
internal void OnGetSection(object sender, GetDataHandlers.GetSectionEventArgs args)
@@ -2076,6 +2077,54 @@ namespace TShockAPI
}
}
+ ///
+ /// Called when a player is trying to place an item into a food plate.
+ ///
+ ///
+ ///
+ internal void OnFoodPlatterTryPlacing(object sender, GetDataHandlers.FoodPlatterTryPlacingEventArgs args)
+ {
+ if (args.Player.ItemInHand.type != args.ItemID)
+ {
+ TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected item not placed by hand from {0}", args.Player.Name);
+ args.Player.SendTileSquare(args.TileX, args.TileY, 1);
+ args.Handled = true;
+ return;
+ }
+ if (args.Player.IsBeingDisabled())
+ {
+ TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing 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.SendTileSquare(args.TileX, args.TileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (!args.Player.HasBuildPermission(args.TileX, args.TileY))
+ {
+ TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing 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.SendTileSquare(args.TileX, args.TileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (!args.Player.IsInRange(args.TileX, args.TileY))
+ {
+ TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected range checks 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.SendTileSquare(args.TileX, args.TileY, 1);
+ args.Handled = true;
+ return;
+ }
+ }
+
internal void OnSecondUpdate()
{
Task.Run(() =>
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 3c94dedb..a84d1713 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -150,7 +150,8 @@ namespace TShockAPI
{ PacketTypes.ToggleParty, HandleToggleParty },
{ PacketTypes.CrystalInvasionStart, HandleOldOnesArmy },
{ PacketTypes.PlayerHurtV2, HandlePlayerDamageV2 },
- { PacketTypes.PlayerDeathV2, HandlePlayerKillMeV2 }
+ { PacketTypes.PlayerDeathV2, HandlePlayerKillMeV2 },
+ { PacketTypes.FoodPlatterTryPlacing, HandleFoodPlatterTryPlacing }
};
}
@@ -1863,6 +1864,52 @@ namespace TShockAPI
return args.Handled;
}
+ public class FoodPlatterTryPlacingEventArgs : GetDataHandledEventArgs
+ {
+ ///
+ /// The X tile position of the placement action.
+ ///
+ public short TileX { get; set; }
+ ///
+ /// The Y tile position of the placement action.
+ ///
+ public short TileY { get; set; }
+ ///
+ /// The Item ID that is being placed in the plate.
+ ///
+ public short ItemID { get; set; }
+ ///
+ /// The prefix of the item that is being placed in the plate.
+ ///
+ public byte Prefix { get; set; }
+ ///
+ /// The stack of the item that is being placed in the plate.
+ ///
+ public short Stack { get; set; }
+ }
+ ///
+ /// Called when a player is placing an item in a food plate.
+ ///
+ public static HandlerList FoodPlatterTryPlacing = new HandlerList();
+ private static bool OnFoodPlatterTryPlacing(TSPlayer player, MemoryStream data, short tileX, short tileY, short itemID, byte prefix, short stack)
+ {
+ if (FoodPlatterTryPlacing == null)
+ return false;
+
+ var args = new FoodPlatterTryPlacingEventArgs
+ {
+ Player = player,
+ Data = data,
+ TileX = tileX,
+ TileY = tileY,
+ ItemID = itemID,
+ Prefix = prefix,
+ Stack = stack,
+ };
+ FoodPlatterTryPlacing.Invoke(null, args);
+ return args.Handled;
+ }
+
#endregion
private static bool HandlePlayerInfo(GetDataHandlerArgs args)
@@ -2118,7 +2165,7 @@ namespace TShockAPI
TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawn force teleport 'vanilla spawn' {0}", args.Player.Name);
}
- if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0) && (args.TPlayer.SpawnX > 0) && ((args.TPlayer.SpawnX != args.Player.sX) && (args.TPlayer.SpawnY != args.Player.sY)))
+ else if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0) && (args.TPlayer.SpawnX > 0) && ((args.TPlayer.SpawnX != args.Player.sX) && (args.TPlayer.SpawnY != args.Player.sY)))
{
args.Player.sX = args.TPlayer.SpawnX;
@@ -2269,6 +2316,14 @@ namespace TShockAPI
{
var player = args.Player;
var size = args.Data.ReadInt16();
+
+ var changeType = TileChangeType.None;
+ bool hasChangeType = ((size & 0x7FFF) & 0x8000) != 0;
+ if (hasChangeType)
+ {
+ changeType = (TileChangeType)args.Data.ReadInt8();
+ }
+
var tileX = args.Data.ReadInt16();
var tileY = args.Data.ReadInt16();
var data = args.Data;
@@ -3559,7 +3614,19 @@ namespace TShockAPI
return false;
}
+ private static bool HandleFoodPlatterTryPlacing(GetDataHandlerArgs args)
+ {
+ short tileX = args.Data.ReadInt16();
+ short tileY = args.Data.ReadInt16();
+ short itemID = args.Data.ReadInt16();
+ byte prefix = args.Data.ReadInt8();
+ short stack = args.Data.ReadInt16();
+ if (OnFoodPlatterTryPlacing(args.Player, args.Data, tileX, tileY, itemID, prefix, stack))
+ return true;
+
+ return false;
+ }
public enum EditAction
{
diff --git a/TShockAPI/Net/NetTile.cs b/TShockAPI/Net/NetTile.cs
index 76d8e943..62896c10 100644
--- a/TShockAPI/Net/NetTile.cs
+++ b/TShockAPI/Net/NetTile.cs
@@ -30,7 +30,7 @@ namespace TShockAPI.Net
public short FrameX { get; set; }
public short FrameY { get; set; }
public bool Lighted { get; set; }
- public byte Wall { get; set; }
+ public ushort Wall { get; set; }
public byte Liquid { get; set; }
public byte LiquidType { get; set; }
public bool Wire { get; set; }
@@ -175,7 +175,7 @@ namespace TShockAPI.Net
}
if (HasWall)
- stream.WriteInt8(Wall);
+ stream.WriteInt16((short)Wall);;
if (HasLiquid)
{
@@ -218,7 +218,7 @@ namespace TShockAPI.Net
if (flags[2])
{
- Wall = stream.ReadInt8();
+ Wall = stream.ReadUInt16();
}
if (flags[3])
diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs
index 3d7deaae..1a204594 100644
--- a/TShockAPI/TSPlayer.cs
+++ b/TShockAPI/TSPlayer.cs
@@ -685,7 +685,7 @@ namespace TShockAPI
/// True if they can paint.
public bool HasPaintPermission(int x, int y)
{
- return HasBuildPermission(x, y) || HasPermission(Permissions.canpaint);
+ return HasBuildPermission(x, y) && HasPermission(Permissions.canpaint);
}
/// Checks if a player can place ice, and if they can, tracks ice placements and removals.
diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj
index c941ea0a..f6a2d81c 100644
--- a/TShockAPI/TShockAPI.csproj
+++ b/TShockAPI/TShockAPI.csproj
@@ -221,4 +221,4 @@
-->
-
+
\ No newline at end of file