diff --git a/CHANGELOG.md b/CHANGELOG.md
index 010e16e7..7359fbfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* Added `GetDataHandlers.HealOtherPlayer` hook. (@hakusaro)
* Added `GetDataHandlers.PlaceObject` hook. (@hakusaro)
* `GetDataHandlers.KillMe` now sends a `TSPlayer` and a `PlayerDeathReason`. (@hakusaro)
+* Added `GetDataHandlers.ProjectileKill` hook. (@hakusaro)
## TShock 4.3.24
* Updated OpenTerraria API to 1.3.5.3 (@DeathCradle)
diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs
index e99233a9..87ea3c72 100644
--- a/TShockAPI/Bouncer.cs
+++ b/TShockAPI/Bouncer.cs
@@ -42,6 +42,7 @@ namespace TShockAPI
{
// Setup hooks
+ GetDataHandlers.ProjectileKill.Register(OnProjectileKill);
GetDataHandlers.PlayerUpdate.Register(OnPlayerUpdate);
GetDataHandlers.KillMe.Register(OnKillMe);
GetDataHandlers.NewProjectile.Register(OnNewProjectile);
@@ -51,6 +52,33 @@ namespace TShockAPI
GetDataHandlers.TileEdit.Register(OnTileEdit);
}
+ /// Handles ProjectileKill events for throttling & out of bounds projectiles.
+ /// The object that triggered the event.
+ /// The packet arguments that the event has.
+ internal void OnProjectileKill(object sender, GetDataHandlers.ProjectileKillEventArgs args)
+ {
+ if (args.ProjectileIndex > Main.maxProjectiles || args.ProjectileIndex < 0)
+ {
+ // TODO: Should this be /true/ to stop the server from processing it?
+ args.Handled = false;
+ return;
+ }
+
+ if (TShock.CheckIgnores(args.Player))
+ {
+ args.Player.RemoveProjectile(args.ProjectileIdentity, args.ProjectileOwner);
+ args.Handled = true;
+ return;
+ }
+
+ if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000)
+ {
+ args.Player.RemoveProjectile(args.ProjectileIdentity, args.ProjectileOwner);
+ args.Handled = true;
+ return;
+ }
+ }
+
/// Handles disabling enforcement & minor anti-exploit stuff
/// The object that triggered the event.
/// The packet arguments that the event has.
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 888bce64..3eb03926 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -384,6 +384,45 @@ namespace TShockAPI
return args.Handled;
}
+ /// The arguments to the ProjectileKill packet.
+ public class ProjectileKillEventArgs : HandledEventArgs
+ {
+ /// The TSPlayer that fired the event.
+ public TSPlayer Player;
+ /// The projectile's identity...?
+ public int ProjectileIdentity;
+ /// The the player index of the projectile's owner (Main.players).
+ public byte ProjectileOwner;
+ /// The index of the projectile in Main.projectile.
+ public int ProjectileIndex;
+ }
+
+ /// The event fired when a projectile kill packet is received.
+ public static HandlerList ProjectileKill;
+
+ /// Fires the ProjectileKill event.
+ /// The TSPlayer that caused the event.
+ /// The projectile identity (from the packet).
+ /// The projectile's owner (from the packet).
+ /// The projectile's index (from Main.projectiles).
+ /// bool
+ private static bool OnProjectileKill(TSPlayer player, int identity, byte owner, int index)
+ {
+ if (ProjectileKill == null)
+ return false;
+
+ var args = new ProjectileKillEventArgs
+ {
+ Player = player,
+ ProjectileIdentity = identity,
+ ProjectileOwner = owner,
+ ProjectileIndex = index,
+ };
+
+ ProjectileKill.Invoke(null, args);
+ return args.Handled;
+ }
+
///
/// For use in a KillMe event
///
@@ -2213,19 +2252,14 @@ namespace TShockAPI
owner = (byte)args.Player.Index;
var index = TShock.Utils.SearchProjectile(ident, owner);
- if (index > Main.maxProjectiles || index < 0)
+ if (OnProjectileKill(args.Player, ident, owner, index))
{
- return false;
+ return true;
}
var type = Main.projectile[index].type;
- if (TShock.CheckIgnores(args.Player))
- {
- args.Player.RemoveProjectile(ident, owner);
- return true;
- }
-
+ // TODO: This needs to be moved somewhere else.
if (TShock.CheckProjectilePermission(args.Player, index, type) && type != 102 && type != 100 && !TShock.Config.IgnoreProjKill)
{
args.Player.Disable("Does not have projectile permission to kill projectile.", DisableFlags.WriteToLogAndConsole);
@@ -2233,12 +2267,6 @@ namespace TShockAPI
return true;
}
- if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000)
- {
- args.Player.RemoveProjectile(ident, owner);
- return true;
- }
-
args.Player.LastKilledProjectile = type;
return false;