diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7286ea27..5149a73e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -60,6 +60,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* Added `TSPlayer.CheckIgnores()` and removed `TShock.CheckIgnores(TSPlayer)`. (@hakusaro)
* Hooks inside TShock can now be registered with their `Register` method and can be prioritized according to the TShock HandlerList system. (@hakusaro)
* Fix message requiring login not using the command specifier set in the config file. (@hakusaro)
+* Fix stack hack detection being inconsistent between two different check points. Moved `TShock.HackedInventory` to `TSPlayer.HasHackedItemStacks`. Added `GetDataHandlers.GetDataHandledEventArgs` which is where most hooks will inherit from in the future. (@hakusaro)
## TShock 4.3.25
* Fixed a critical exploit in the Terraria protocol that could cause massive unpreventable world corruption as well as a number of other problems. Thanks to @bartico6 for reporting. Fixed by the efforts of @QuiCM, @hakusaro, and tips in the right directioon from @bartico6.
diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs
index 8e81d802..b0b6a427 100644
--- a/TShockAPI/Bouncer.cs
+++ b/TShockAPI/Bouncer.cs
@@ -42,6 +42,7 @@ namespace TShockAPI
{
// Setup hooks
+ GetDataHandlers.GetSection += OnGetSection;
GetDataHandlers.PlaceItemFrame += OnPlaceItemFrame;
GetDataHandlers.GemLockToggle += OnGemLockToggle;
GetDataHandlers.PlaceTileEntity += OnPlaceTileEntity;
@@ -64,6 +65,28 @@ namespace TShockAPI
GetDataHandlers.TileEdit += OnTileEdit;
}
+ internal void OnGetSection(object sender, GetDataHandlers.GetSectionEventArgs args)
+ {
+ if (args.Player.RequestedSection)
+ {
+ args.Handled = true;
+ return;
+ }
+ args.Player.RequestedSection = true;
+
+ if (String.IsNullOrEmpty(args.Player.Name))
+ {
+ TShock.Utils.ForceKick(args.Player, "Blank name.", true);
+ args.Handled = true;
+ return;
+ }
+
+ if (!args.Player.HasPermission(Permissions.ignorestackhackdetection))
+ {
+ args.Player.IsDisabledForStackDetection = args.Player.HasHackedItemStacks(true);
+ }
+ }
+
/// Fired when an item frame is placed for anti-cheat detection.
/// The object that triggered the event.
/// The packet arguments that the event has.
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 9162acd2..83bcb26d 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -58,6 +58,19 @@ namespace TShockAPI
}
}
+ ///
+ /// A custom HandledEventArgs that contains TShock's TSPlayer for the triggering uesr and the Terraria MP data stream.
+ /// Differentiated by GetDataHandlerArgs because it can be handled and responds to being handled.
+ ///
+ public class GetDataHandledEventArgs : HandledEventArgs
+ {
+ /// The TSPlayer that triggered the event.
+ public TSPlayer Player { get; set; }
+
+ /// The raw MP packet data associated with the event.
+ public MemoryStream Data { get; set; }
+ }
+
public static class GetDataHandlers
{
private static Dictionary GetDataHandlerDelegates;
@@ -1903,21 +1916,46 @@ namespace TShockAPI
return true;
}
+ /// The arguments to a GetSection packet.
+ public class GetSectionEventArgs : GetDataHandledEventArgs
+ {
+ /// The X position requested. Or -1 for spawn.
+ public int X { get; set; }
+
+ /// The Y position requested. Or -1 for spawn.
+ public int Y { get; set; }
+ }
+
+ /// The hook for a GetSection event.
+ public static HandlerList GetSection = new HandlerList();
+
+ /// Fires a GetSection event.
+ /// The TSPlayer that caused the GetSection.
+ /// The raw MP protocol data.
+ /// The x coordinate requested or -1 for spawn.
+ /// The y coordinate requested or -1 for spawn.
+ /// bool
+ private static bool OnGetSection(TSPlayer player, MemoryStream data, int x, int y)
+ {
+ if (GetSection == null)
+ return false;
+
+ var args = new GetSectionEventArgs
+ {
+ Player = player,
+ Data = data,
+ X = x,
+ Y = y,
+ };
+
+ GetSection.Invoke(null, args);
+ return args.Handled;
+ }
+
private static bool HandleGetSection(GetDataHandlerArgs args)
{
- if (args.Player.RequestedSection)
+ if (OnGetSection(args.Player, args.Data, args.Data.ReadInt32(), args.Data.ReadInt32()))
return true;
- args.Player.RequestedSection = true;
- if (String.IsNullOrEmpty(args.Player.Name))
- {
- TShock.Utils.ForceKick(args.Player, "Blank name.", true);
- return true;
- }
-
- if (!args.Player.HasPermission(Permissions.ignorestackhackdetection))
- {
- args.Player.IsDisabledForStackDetection = args.Player.HasHackedItemStacks(true);
- }
if (TShock.Utils.ActivePlayers() + 1 > TShock.Config.MaxSlots &&
!args.Player.HasPermission(Permissions.reservedslot))