diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2602044a..f4bc853d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,9 +34,6 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* Removed REST `/v3/server/restart/` route and `/server/restart/` route. (@hakusaro)
* The "auth system" is now referred to as the initial setup system (what it actually is). This is better verbiage for basically all situations. Who really wants to turn off the "authentication system?" In addition, the system now makes it more clear what the point of it is, rather than that it grants permissions. (@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.
-
@@ -68,6 +65,10 @@ Putting this stuff down here so things don't conflict as often.
* `GetDataHandlers.KillMe` now sends a `TSPlayer` and a `PlayerDeathReason`. (@hakusaro)
* Added `GetDataHandlers.ProjectileKill` hook. (@hakusaro)
* Removed `TShock.CheckProjectilePermission` and replaced it with `TSPlayer.HasProjectilePermission` and `TSPlayer.LacksProjectilePermission` respectively. (@hakusaro)
+* Added `TSPlayer` object to `GetDataHandlers.LiquidSetEventArgs`. (@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.
## TShock 4.3.24
* Updated OpenTerraria API to 1.3.5.3 (@DeathCradle)
diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs
index 2710fbd4..31b31173 100644
--- a/TShockAPI/Bouncer.cs
+++ b/TShockAPI/Bouncer.cs
@@ -42,6 +42,7 @@ namespace TShockAPI
{
// Setup hooks
+ GetDataHandlers.LiquidSet.Register(OnLiquidSet);
GetDataHandlers.ProjectileKill.Register(OnProjectileKill);
GetDataHandlers.PlayerUpdate.Register(OnPlayerUpdate);
GetDataHandlers.KillMe.Register(OnKillMe);
@@ -52,6 +53,146 @@ namespace TShockAPI
GetDataHandlers.TileEdit.Register(OnTileEdit);
}
+ /// Handles Bouncer's liquid set anti-cheat.
+ /// The object that triggered the event.
+ /// The packet arguments that the event has.
+ internal void OnLiquidSet(object sender, GetDataHandlers.LiquidSetEventArgs args)
+ {
+ int tileX = args.TileX;
+ int tileY = args.TileY;
+ byte amount = args.Amount;
+ byte type = args.Type;
+
+ if (!TShock.Utils.TilePlacementValid(tileX, tileY) || (args.Player.Dead && TShock.Config.PreventDeadModification))
+ {
+ args.Handled = true;
+ return;
+ }
+
+ if (TShock.CheckIgnores(args.Player))
+ {
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (args.Player.TileLiquidThreshold >= TShock.Config.TileLiquidThreshold)
+ {
+ args.Player.Disable("Reached TileLiquid threshold.", DisableFlags.WriteToLogAndConsole);
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (!args.Player.HasPermission(Permissions.ignoreliquidsetdetection))
+ {
+ args.Player.TileLiquidThreshold++;
+ }
+
+ // Liquid anti-cheat
+ // Arguably the banned buckets bit should be in the item bans system
+ if (amount != 0)
+ {
+ int bucket = -1;
+ if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.EmptyBucket)
+ {
+ bucket = 0;
+ }
+ else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.WaterBucket)
+ {
+ bucket = 1;
+ }
+ else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.LavaBucket)
+ {
+ bucket = 2;
+ }
+ else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.HoneyBucket)
+ {
+ bucket = 3;
+ }
+ else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.BottomlessBucket ||
+ args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.SuperAbsorbantSponge)
+ {
+ bucket = 4;
+ }
+
+ if (type == 1 && !(bucket == 2 || bucket == 0))
+ {
+ args.Player.SendErrorMessage("You do not have permission to perform this action.");
+ args.Player.Disable("Spreading lava without holding a lava bucket", DisableFlags.WriteToLogAndConsole);
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (type == 1 && TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player))
+ {
+ args.Player.SendErrorMessage("You do not have permission to perform this action.");
+ args.Player.Disable("Using banned lava bucket without permissions", DisableFlags.WriteToLogAndConsole);
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (type == 0 && !(bucket == 1 || bucket == 0 || bucket == 4))
+ {
+ args.Player.SendErrorMessage("You do not have permission to perform this action.");
+ args.Player.Disable("Spreading water without holding a water bucket", DisableFlags.WriteToLogAndConsole);
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (type == 0 && TShock.Itembans.ItemIsBanned("Water Bucket", args.Player))
+ {
+ args.Player.SendErrorMessage("You do not have permission to perform this action.");
+ args.Player.Disable("Using banned water bucket without permissions", DisableFlags.WriteToLogAndConsole);
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (type == 2 && !(bucket == 3 || bucket == 0))
+ {
+ args.Player.SendErrorMessage("You do not have permission to perform this action.");
+ args.Player.Disable("Spreading honey without holding a honey bucket", DisableFlags.WriteToLogAndConsole);
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (type == 2 && TShock.Itembans.ItemIsBanned("Honey Bucket", args.Player))
+ {
+ args.Player.SendErrorMessage("You do not have permission to perform this action.");
+ args.Player.Disable("Using banned honey bucket without permissions", DisableFlags.WriteToLogAndConsole);
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+ }
+
+ if (TShock.CheckTilePermission(args.Player, tileX, tileY))
+ {
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if (TShock.CheckRangePermission(args.Player, tileX, tileY, 16))
+ {
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+
+ if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000)
+ {
+ args.Player.SendTileSquare(tileX, tileY, 1);
+ args.Handled = true;
+ return;
+ }
+ }
+
/// Handles ProjectileKill events for throttling & out of bounds projectiles.
/// The object that triggered the event.
/// The packet arguments that the event has.
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 205bf0b7..7dca2509 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -795,6 +795,8 @@ namespace TShockAPI
///
public class LiquidSetEventArgs : HandledEventArgs
{
+ /// The TSPlayer that triggered the event.
+ public TSPlayer Player { get; set; }
///
/// X location of the tile
///
@@ -817,13 +819,14 @@ namespace TShockAPI
///
public static HandlerList LiquidSet;
- private static bool OnLiquidSet(int tilex, int tiley, byte amount, byte type)
+ private static bool OnLiquidSet(TSPlayer player, int tilex, int tiley, byte amount, byte type)
{
if (LiquidSet == null)
return false;
var args = new LiquidSetEventArgs
{
+ Player = player,
TileX = tilex,
TileY = tiley,
Amount = amount,
@@ -2325,121 +2328,9 @@ namespace TShockAPI
byte amount = args.Data.ReadInt8();
byte type = args.Data.ReadInt8();
- if (OnLiquidSet(tileX, tileY, amount, type))
+ if (OnLiquidSet(args.Player, tileX, tileY, amount, type))
return true;
- if (!TShock.Utils.TilePlacementValid(tileX, tileY) || (args.Player.Dead && TShock.Config.PreventDeadModification))
- return true;
-
- if (TShock.CheckIgnores(args.Player))
- {
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (args.Player.TileLiquidThreshold >= TShock.Config.TileLiquidThreshold)
- {
- args.Player.Disable("Reached TileLiquid threshold.", DisableFlags.WriteToLogAndConsole);
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (!args.Player.HasPermission(Permissions.ignoreliquidsetdetection))
- {
- args.Player.TileLiquidThreshold++;
- }
- if (amount != 0)
- {
- int bucket = -1;
- if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 205)
- {
- bucket = 0;
- }
- else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 206)
- {
- bucket = 1;
- }
- else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 207)
- {
- bucket = 2;
- }
- else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 1128)
- {
- bucket = 3;
- }
- else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 3031 ||
- args.TPlayer.inventory[args.TPlayer.selectedItem].type == 3032)
- {
- bucket = 4;
- }
-
- if (type == 1 && !(bucket == 2 || bucket == 0))
- {
- args.Player.SendErrorMessage("You do not have permission to perform this action.");
- args.Player.Disable("Spreading lava without holding a lava bucket", DisableFlags.WriteToLogAndConsole);
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (type == 1 && TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player))
- {
- args.Player.SendErrorMessage("You do not have permission to perform this action.");
- args.Player.Disable("Using banned lava bucket without permissions", DisableFlags.WriteToLogAndConsole);
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (type == 0 && !(bucket == 1 || bucket == 0 || bucket == 4))
- {
- args.Player.SendErrorMessage("You do not have permission to perform this action.");
- args.Player.Disable("Spreading water without holding a water bucket", DisableFlags.WriteToLogAndConsole);
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (type == 0 && TShock.Itembans.ItemIsBanned("Water Bucket", args.Player))
- {
- args.Player.SendErrorMessage("You do not have permission to perform this action.");
- args.Player.Disable("Using banned water bucket without permissions", DisableFlags.WriteToLogAndConsole);
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (type == 2 && !(bucket == 3 || bucket == 0))
- {
- args.Player.SendErrorMessage("You do not have permission to perform this action.");
- args.Player.Disable("Spreading honey without holding a honey bucket", DisableFlags.WriteToLogAndConsole);
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (type == 2 && TShock.Itembans.ItemIsBanned("Honey Bucket", args.Player))
- {
- args.Player.SendErrorMessage("You do not have permission to perform this action.");
- args.Player.Disable("Using banned honey bucket without permissions", DisableFlags.WriteToLogAndConsole);
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
- }
-
- if (TShock.CheckTilePermission(args.Player, tileX, tileY))
- {
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if (TShock.CheckRangePermission(args.Player, tileX, tileY, 16))
- {
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
- if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000)
- {
- args.Player.SendTileSquare(tileX, tileY, 1);
- return true;
- }
-
return false;
}