diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs
index c4f9cf35..2b9466ca 100755
--- a/TShockAPI/ConfigFile.cs
+++ b/TShockAPI/ConfigFile.cs
@@ -295,6 +295,10 @@ namespace TShockAPI
[Description("Disable a player if this number of projectiles is created within 1 second.")]
public int ProjectileThreshold = 50;
+ /// ProjectileThreshold - Disables a player if this number of projectiles is created within 1 second.
+ [Description("Disable a player if this number of projectiles is created within 1 second.")]
+ public int HealOtherThreshold = 50;
+
/// ProjIgnoreShrapnel - Whether or not to ignore shrapnel from crystal bullets for the projectile threshold count.
[Description("Ignore shrapnel from crystal bullets for projectile threshold.")]
public bool ProjIgnoreShrapnel = true;
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 92a8b7f6..0f7781f3 100755
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -1261,7 +1261,8 @@ namespace TShockAPI
{ PacketTypes.PlaceItemFrame, HandlePlaceItemFrame },
{ PacketTypes.SyncExtraValue, HandleSyncExtraValue },
{ PacketTypes.LoadNetModule, HandleLoadNetModule },
- { PacketTypes.ToggleParty, HandleToggleParty }
+ { PacketTypes.ToggleParty, HandleToggleParty },
+ { PacketTypes.PlayerHealOther, HandleHealOther }
};
}
@@ -1283,6 +1284,43 @@ namespace TShockAPI
return false;
}
+ private static bool HandleHealOther(GetDataHandlerArgs args)
+ {
+ byte plr = args.Data.ReadInt8();
+ short amount = args.Data.ReadInt16();
+
+ if (amount <= 0 || Main.player[plr] == null || !Main.player[plr].active)
+ {
+ return true;
+ }
+
+ if (amount > TShock.Config.MaxDamage * 0.2)
+ {
+ args.Player.Disable("HealOtherPlayer max amount cheat attempt!", DisableFlags.WriteToLogAndConsole);
+ return true;
+ }
+
+ if (args.TPlayer.whoAmI != plr && (args.TPlayer.team == 0 || args.TPlayer.team != Main.player[plr].team))
+ {
+ args.Player.Disable("HealOtherPlayer cheat attempt!", DisableFlags.WriteToLogAndConsole);
+ return true;
+ }
+
+ if (args.Player.HealOtherThreshold > TShock.Config.HealOtherThreshold)
+ {
+ args.Player.Disable("Reached HealOtherPlayer threshold.", DisableFlags.WriteToLogAndConsole);
+ return true;
+ }
+
+ if (TShock.CheckIgnores(args.Player) || (DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000)
+ {
+ return true;
+ }
+
+ args.Player.HealOtherThreshold++;
+ return false;
+ }
+
private static bool HandlePlayerSlot(GetDataHandlerArgs args)
{
byte plr = args.Data.ReadInt8();
diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs
index 95feb980..d8a5537a 100755
--- a/TShockAPI/TSPlayer.cs
+++ b/TShockAPI/TSPlayer.cs
@@ -93,7 +93,12 @@ namespace TShockAPI
/// The number of projectiles created by the player in the last second.
///
public int ProjectileThreshold { get; set; }
-
+
+ ///
+ /// The number of HealOtherPlayer packets sent by the player in the last second.
+ ///
+ public int HealOtherThreshold { get; set; }
+
///
/// A timer to keep track of whether or not the player has recently thrown an explosive
///
diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs
index 1bbb7052..046f274c 100755
--- a/TShockAPI/TShock.cs
+++ b/TShockAPI/TShock.cs
@@ -1030,6 +1030,15 @@ namespace TShockAPI
player.PaintThreshold = 0;
}
+ if (player.HealOtherThreshold > TShock.Config.HealOtherThreshold)
+ {
+ player.Disable("Reached HealOtherPlayer threshold", flags);
+ }
+ if (player.HealOtherThreshold > 0)
+ {
+ player.HealOtherThreshold = 0;
+ }
+
if (player.RespawnTimer > 0 && --player.RespawnTimer == 0 && player.Difficulty != 2)
{
player.Spawn();
@@ -1458,7 +1467,7 @@ namespace TShockAPI
/// The CommandEventArgs object
private void ServerHooks_OnCommand(CommandEventArgs args)
{
- if (args.Handled)
+ if (args.Handled || string.IsNullOrWhiteSpace(args.Command))
return;
// Damn you ThreadStatic and Redigit