From 71a480af6b388cfbb1e985f90233ce71ccb73810 Mon Sep 17 00:00:00 2001 From: James Puleo Date: Thu, 10 Nov 2022 20:14:11 -0500 Subject: [PATCH 1/3] Whitelist Shadow Candle and BoC for `PlayerAddBuff` --- TShockAPI/Bouncer.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 8d3d7636..3e73f9ba 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -416,6 +416,18 @@ namespace TShockAPI CanBeAddedWithoutHostile = false, CanOnlyBeAppliedToSender = false }; + PlayerAddBuffWhitelist[BuffID.ShadowCandle] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; + PlayerAddBuffWhitelist[BuffID.BrainOfConfusionBuff] = new BuffLimit + { + MaxTicks = 240, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; #endregion Whitelist } From 51de32387ab3654696775500a33de1c9cc46a58f Mon Sep 17 00:00:00 2001 From: James Puleo Date: Thu, 10 Nov 2022 20:16:59 -0500 Subject: [PATCH 2/3] Improve rejection message and code duplication in `OnPlayerBuff` There is now a local function `Reject` that will handle logging, rejecting, and (optionally) re-syncing upon a rejected packet. Alongside this, the debug message has been improved to include the sender index, buff type, receiver index, and the time in ticks (and the existing reason for rejection.) --- TShockAPI/Bouncer.cs | 77 ++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 3e73f9ba..76ffc3cd 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -1879,41 +1879,57 @@ namespace TShockAPI int type = args.Type; int time = args.Time; + void Reject(bool shouldResync = true) + { + args.Handled = true; + + if (shouldResync) + args.Player.SendData(PacketTypes.PlayerBuff, number: id); + } + if (id >= Main.maxPlayers) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected player cap from {0}", args.Player.Name)); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: target ID out of bounds", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(false); return; } if (TShock.Players[id] == null) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected null check from {0}", args.Player.Name)); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: target is null", args.Player.Name, + args.Player.Index, type, id, time)); + Reject(false); return; } if (type >= Terraria.ID.BuffID.Count) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected invalid buff type {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: invalid buff type", args.Player.Name, + args.Player.Index, type, id, time)); + Reject(false); return; } if (args.Player.IsBeingDisabled()) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected disabled from {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: sender is being disabled", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(); return; } if (args.Player.IsBouncerThrottled()) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected throttled from {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: sender is being throttled", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(); + return; } @@ -1922,41 +1938,46 @@ namespace TShockAPI if (!args.Player.IsInRange(targetPlayer.TileX, targetPlayer.TileY, 50)) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected range check from {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: sender is not in range of target", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(); return; } if (buffLimit == null) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected non-whitelisted buff {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: buff is not whitelisted", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(); return; } if (buffLimit.CanOnlyBeAppliedToSender && id != args.Player.Index) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected applied to non-sender from {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: buff cannot be applied to non-senders", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(); return; } if (!buffLimit.CanBeAddedWithoutHostile && !targetPlayer.TPlayer.hostile) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected hostile/pvp from {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: buff cannot be applied without pvp", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(); return; } if (time <= 0 || time > buffLimit.MaxTicks) { - TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerBuff rejected time too long from {0}", args.Player.Name)); - args.Player.SendData(PacketTypes.PlayerBuff, "", id); - args.Handled = true; + TShock.Log.ConsoleDebug(GetString( + "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: buff cannot be applied for that long", + args.Player.Name, args.Player.Index, type, id, time)); + Reject(); return; } } From 5cc1275496443e42140b8595bcdb5ce8f9deb7b9 Mon Sep 17 00:00:00 2001 From: James Puleo Date: Thu, 10 Nov 2022 20:22:41 -0500 Subject: [PATCH 3/3] Update `docs/changelog.md` --- docs/changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index bef17eca..35e8c596 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -79,6 +79,9 @@ Use past tense when adding new entries; sign your name off when you add or chang ## Upcoming changes * Updated the Utils.FindByIdOrName to follow same logic. Now fuzzy match fallback to `StartsWith` and then `Contains`. (@sgkoishi) +* Added `ShadowCandle` and `BrainOfConfusionBuff` (BoC dodge buff) to the `PlayerAddBuffWhitelist` (@drunderscore) +* Improved rejection message and code duplication in `OnPlayerBuff` (@drunderscore) + * This will make it so Bouncer rejections regarding `PlayerAddBuff` will now always include the sender index, buff type, receiver index, and time in ticks, allowing much faster triage of buff whitelist issues. ## TShock 5.1.3 * Added support for Terraria 1.4.4.9 via OTAPI 3.1.20. (@SignatureBeef)