package net.simpvp.Misc;

import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;

/**
 * Modifies damage source data in various ways
 * to prevent it from being used to track players positions
 *
 * @author cats
 */
public class DamageSource implements Listener {

    private final int maxDistanceSq;

    public DamageSource(int maxDistance) {
        this.maxDistanceSq = maxDistance * maxDistance;
    }

    /**
     * This handler removes the TNT explosion source
     * By doing this, we prevent the tnt knockback from an improper damage source
     */
    @EventHandler
    public void onExplosionPrimed(ExplosionPrimeEvent event) {
        if (event.getEntityType() == EntityType.PRIMED_TNT) {
            final TNTPrimed tnt = (TNTPrimed) event.getEntity();

            tnt.setSource(null);
        }
    }

    /**
     * Reset the velocity 1 tick after the player takes damage
     *
     * Possible todo: maybe make this run async to avoid tps lag playing a factor
     * I don't think it does because bukkit scheduler, but who knows
     */
    @EventHandler
    public void onDamage(EntityDamageByEntityEvent event) {
        if (event.getCause() == EntityDamageEvent.DamageCause.PROJECTILE) {
            // This SHOULD always be a successful cast
            final Projectile projectile = (Projectile) event.getDamager();

            if (projectile.getShooter() instanceof Player) {
                final Player shooter = (Player) projectile.getShooter();


                // I'm wincing but it shouldn't be too much math
                if (projectile.getLocation().distanceSquared(shooter.getLocation()) > this.maxDistanceSq) {
                    new BukkitRunnable() {
                        @Override
                        public void run() {
                            event.getEntity().setVelocity(new Vector(0, event.getEntity().getVelocity().getY(), 0));

                        }
                        // The velocity should be sent all at once, so we don't send 2 conflicting ones
                        // Just 1 all at once
                    }.runTaskLater(Misc.instance, 1L);
                }
            }
        }
    }
}

@@ -19,16 +19,44 @@
 .Misc;%0A%0A
+import org.bukkit.Location;%0A
 import o
@@ -75,16 +75,16 @@
 tity.*;%0A
-
 import o
@@ -1066,24 +1066,168 @@
 tEntity();%0A%0A
+            if (tnt.getSource() instanceof Player) %7B%0A                if (checkDist(tnt.getLocation(), tnt.getSource().getLocation())) %7B%0A        
             
@@ -1247,16 +1247,48 @@
 (null);%0A
+                %7D%0A            %7D%0A
         
@@ -1814,24 +1814,78 @@
 Damager();%0A%0A
+            final Entity entity = event.getEntity();%0A%0A
             
@@ -2084,32 +2084,42 @@
              if 
+(checkDist
 (projectile.getL
@@ -2131,25 +2131,10 @@
 on()
-.distanceSquared(
+, 
 shoo
@@ -2155,29 +2155,8 @@
 n())
- %3E this.maxDistanceSq
 ) %7B%0A
@@ -2305,32 +2305,21 @@
        e
-vent.getE
 ntity
-()
 .setVelo
@@ -2338,32 +2338,21 @@
 tor(0, e
-vent.getE
 ntity
-()
 .getVelo
@@ -2627,32 +2627,32 @@
 %7D%0A            %7D%0A
-
         %7D%0A    %7D%0A
@@ -2650,11 +2650,269 @@
  %7D%0A    %7D
+%0A%0A    /**%0A     * Should not be capable of throwing an %7B@link IllegalArgumentException%7D%0A     */%0A    private boolean checkDist(Location to, Location from) %7B%0A        return to.getWorld() != from.getWorld() %7C%7C to.distanceSquared(from) %3E this.maxDistanceSq;%0A    %7D
 %0A%7D%0A

Fix exception!