diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 469b6ee9..efe21554 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -44,6 +44,27 @@ namespace TShockAPI internal Handlers.LandGolfBallInCupHandler LandGolfBallInCupHandler { get; private set; } internal Handlers.SyncTilePickingHandler SyncTilePickingHandler { get; private set; } + /// + /// A class that represents the limits for a particular buff when a client applies it with PlayerAddBuff. + /// + internal class BuffLimit + { + /// + /// How many ticks at the maximum a player can apply this to another player for. + /// + public int MaxTicks { get; set; } + /// + /// Can this buff be added without the receiver being hostile (PvP) + /// + public bool CanBeAddedWithoutHostile { get; set; } + /// + /// Can this buff only be applied to the sender? + /// + public bool CanOnlyBeAppliedToSender { get; set; } + } + + internal static BuffLimit[] PlayerAddBuffWhitelist; + /// /// Represents a place style corrector. /// @@ -231,6 +252,172 @@ namespace TShockAPI return actualItemPlaceStyle; } }); + + #region PlayerAddBuff Whitelist + + PlayerAddBuffWhitelist = new BuffLimit[Main.maxBuffTypes]; + PlayerAddBuffWhitelist[BuffID.Poisoned] = new BuffLimit + { + MaxTicks = 60 * 60 + }; + PlayerAddBuffWhitelist[BuffID.OnFire] = new BuffLimit + { + MaxTicks = 60 * 20 + }; + PlayerAddBuffWhitelist[BuffID.Confused] = new BuffLimit + { + MaxTicks = 60 * 4 + }; + PlayerAddBuffWhitelist[BuffID.CursedInferno] = new BuffLimit + { + MaxTicks = 60 * 7 + }; + PlayerAddBuffWhitelist[BuffID.Wet] = new BuffLimit + { + MaxTicks = 60 * 30, + // The Water Gun can be shot at other players and inflict Wet while not in PvP + CanBeAddedWithoutHostile = true + }; + PlayerAddBuffWhitelist[BuffID.Ichor] = new BuffLimit + { + MaxTicks = 60 * 20 + }; + PlayerAddBuffWhitelist[BuffID.Venom] = new BuffLimit + { + MaxTicks = 60 * 30 + }; + PlayerAddBuffWhitelist[BuffID.GelBalloonBuff] = new BuffLimit + { + MaxTicks = 60 * 30, + // The Sparkle Slime Balloon inflicts this while not in PvP + CanBeAddedWithoutHostile = true + }; + PlayerAddBuffWhitelist[BuffID.Frostburn] = new BuffLimit + { + MaxTicks = 60 * 8 + }; + PlayerAddBuffWhitelist[BuffID.Campfire] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.Sunflower] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.WaterCandle] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.BeetleEndurance1] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.BeetleEndurance2] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.BeetleEndurance3] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.BeetleMight1] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.BeetleMight2] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.BeetleMight3] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true, + }; + PlayerAddBuffWhitelist[BuffID.SolarShield1] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = false, + }; + PlayerAddBuffWhitelist[BuffID.SolarShield2] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = false, + }; + PlayerAddBuffWhitelist[BuffID.SolarShield3] = new BuffLimit + { + MaxTicks = 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = false, + }; + PlayerAddBuffWhitelist[BuffID.MonsterBanner] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; + PlayerAddBuffWhitelist[BuffID.HeartLamp] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; + PlayerAddBuffWhitelist[BuffID.PeaceCandle] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; + PlayerAddBuffWhitelist[BuffID.StarInBottle] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; + PlayerAddBuffWhitelist[BuffID.CatBast] = new BuffLimit + { + MaxTicks = 2, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; + PlayerAddBuffWhitelist[BuffID.OnFire3] = new BuffLimit + { + MaxTicks = 60 * 5, + CanBeAddedWithoutHostile = false, + CanOnlyBeAppliedToSender = false + }; + PlayerAddBuffWhitelist[BuffID.HeartyMeal] = new BuffLimit + { + MaxTicks = 60 * 7, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; + PlayerAddBuffWhitelist[BuffID.Frostburn2] = new BuffLimit + { + MaxTicks = 60 * 7, + CanBeAddedWithoutHostile = false, + CanOnlyBeAppliedToSender = false + }; + + #endregion Whitelist } internal void OnGetSection(object sender, GetDataHandlers.GetSectionEventArgs args) @@ -1640,9 +1827,24 @@ namespace TShockAPI int type = args.Type; int time = args.Time; + if (id >= Main.maxPlayers) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected player cap from {0}", args.Player.Name); + args.Handled = true; + return; + } + if (TShock.Players[id] == null) { - TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected null check"); + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected null check from {0}", args.Player.Name); + args.Handled = true; + return; + } + + if (type >= Main.maxBuffTypes) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected invalid buff type {0}", args.Player.Name); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); args.Handled = true; return; } @@ -1650,31 +1852,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected disabled from {0}", args.Player.Name); - args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); - args.Handled = true; - return; - } - - if (id >= Main.maxPlayers) - { - TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected player cap from {0}", args.Player.Name); - args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); - args.Handled = true; - return; - } - - if (!TShock.Players[id].TPlayer.hostile || !Main.pvpBuff[type]) - { - TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected hostile/pvp from {0}", args.Player.Name); - args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); - args.Handled = true; - return; - } - - if (!args.Player.IsInRange(TShock.Players[id].TileX, TShock.Players[id].TileY, 50)) - { - TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected range check from {0}", args.Player.Name); - args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); args.Handled = true; return; } @@ -1682,15 +1860,51 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected throttled from {0}", args.Player.Name); - args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); args.Handled = true; return; } - if (WhitelistBuffMaxTime[type] > 0 && time <= WhitelistBuffMaxTime[type]) + var targetPlayer = TShock.Players[id]; + var buffLimit = PlayerAddBuffWhitelist[type]; + + if (!args.Player.IsInRange(targetPlayer.TileX, targetPlayer.TileY, 50)) { - TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected buff time whitelists from {0}", args.Player.Name); - args.Handled = false; + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected range check from {0}", args.Player.Name); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + args.Handled = true; + return; + } + + if (buffLimit == null) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected non-whitelisted buff {0}", args.Player.Name); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + args.Handled = true; + return; + } + + if (buffLimit.CanOnlyBeAppliedToSender && id != args.Player.Index) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected applied to non-sender from {0}", args.Player.Name); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + args.Handled = true; + return; + } + + if (!buffLimit.CanBeAddedWithoutHostile && !targetPlayer.TPlayer.hostile) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected hostile/pvp from {0}", args.Player.Name); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + args.Handled = true; + return; + } + + if (time <= 0 || time > buffLimit.MaxTicks) + { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected time too long from {0}", args.Player.Name); + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + args.Handled = true; return; } } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 0770eda0..e1d34934 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -79,20 +79,8 @@ namespace TShockAPI { private static Dictionary GetDataHandlerDelegates; - public static int[] WhitelistBuffMaxTime; - public static void InitGetDataHandler() { - #region Blacklists - - WhitelistBuffMaxTime = new int[Main.maxBuffTypes]; - WhitelistBuffMaxTime[20] = 600; - WhitelistBuffMaxTime[0x18] = 1200; - WhitelistBuffMaxTime[0x1f] = 120; - WhitelistBuffMaxTime[0x27] = 420; - - #endregion Blacklists - GetDataHandlerDelegates = new Dictionary { { PacketTypes.PlayerInfo, HandlePlayerInfo },