<commit_before>package com.elmakers.mine.bukkit.utility;

import java.lang.ref.WeakReference;

import com.elmakers.mine.bukkit.block.MaterialAndData;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;

import com.elmakers.mine.bukkit.api.magic.Mage;

public class Target implements Comparable<Target>
{
    public static boolean DEBUG_TARGETING = false;

    protected int    maxDistanceSquared = 128 * 128;
    protected int    minDistanceSquared = 0;
    protected double maxAngle           = 0.3;
    protected boolean useHitbox         = false;
    protected double hitboxPadding      = 0;

    protected float distanceWeight = 1;
    protected float fovWeight = 4;
    protected int npcWeight = -1;
    protected int playerWeight = 4;
    protected int livingEntityWeight = 3;
    protected int mageWeight = 5;

    protected double closeDistanceSquared = 1;
    protected double closeAngle = Math.PI / 2;

    private Location source;
    private Location location;
    private MaterialAndData locationMaterial;
    private WeakReference<Entity>   _entity;
    private Mage	 mage;
    private boolean  reverseDistance = false;

    private double   distanceSquared    = 100000;
    private double   angle              = 10000;
    private int      score              = 0;

    private Object	 extraData	 = null;

    public Target(Location sourceLocation)
    {
        this.source = sourceLocation;
    }

    public void setBlock(Block block)
    {
        if (block != null) {
            this.location = block.getLocation();
            this.location.add(0.5, 0.5, 0.5);
        }
    }

    public Target(Location sourceLocation, Block block)
    {
        this.source = sourceLocation;
        this.locationMaterial = new MaterialAndData(block);
        this.setBlock(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Block block, boolean hitbox, double hitboxPadding)
    {
        this.source = sourceLocation;
        this.locationMaterial = new MaterialAndData(block);
        this.useHitbox = hitbox;
        this.hitboxPadding = hitboxPadding;
        this.setBlock(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Block block, int range)
    {
        this(sourceLocation, block, range, 0.3, false);
    }

    public Target(Location sourceLocation, Block block, int range, double angle)
    {
        this(sourceLocation, block, range, angle, false);
    }

    public Target(Location sourceLocation, Block block, int range, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this.setBlock(block);
        this.locationMaterial = new MaterialAndData(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Block block, int minRange, int maxRange, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = maxRange * maxRange;
        this.minDistanceSquared = minRange * minRange;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this.setBlock(block);
        this.locationMaterial = new MaterialAndData(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range)
    {
        this.maxDistanceSquared = range * range;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, boolean hitbox, double hitboxPadding)
    {
        this.maxDistanceSquared = range * range;
        this.source = sourceLocation;
        this.useHitbox = hitbox;
        this.hitboxPadding = hitboxPadding;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle)
    {
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle, double closeRange, double closeAngle,
                  float distanceWeight, float fovWeight, int mageWeight, int npcWeight, int playerWeight, int livingEntityWeight)
    {
        this.closeDistanceSquared = closeRange * closeRange;
        this.closeAngle = closeAngle;
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        this.distanceWeight = distanceWeight;
        this.fovWeight = fovWeight;
        this.mageWeight = mageWeight;
        this.npcWeight = npcWeight;
        this.playerWeight = playerWeight;
        this.livingEntityWeight = livingEntityWeight;

        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle, double closeRange, double closeAngle)
    {
        this.closeDistanceSquared = closeRange * closeRange;
        this.closeAngle = closeAngle;
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int minRange, int maxRange, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = maxRange * maxRange;
        this.minDistanceSquared = minRange * minRange;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Mage mage, int minRange, int maxRange, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = maxRange * maxRange;
        this.minDistanceSquared = minRange * minRange;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this.mage = mage;
        if (mage != null) {
            this._entity = new WeakReference<Entity>(mage.getLivingEntity());
        }
        if (mage != null) this.location = mage.getEyeLocation();
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity)
    {
        this.maxDistanceSquared = 0;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
    }

    public Target(Location sourceLocation, Entity entity, Block block)
    {
        this.maxDistanceSquared = 0;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (block != null) {
            this.setBlock(block);
        } else if (entity != null) {
            this.location = CompatibilityUtils.getEyeLocation(entity);
        }
    }

    public int getScore()
    {
        return score;
    }

    protected void calculateScore()
    {
        score = 0;
        if (source == null) return;

        Vector sourceDirection = source.getDirection();
        Vector sourceLocation = new Vector(source.getX(), source.getY(), source.getZ());

        Location targetLocation = getLocation();
        if (targetLocation == null) return;

        Vector targetLoc = new Vector(targetLocation.getX(), targetLocation.getY(), targetLocation.getZ());
        Vector targetDirection = new Vector(targetLoc.getX() - sourceLocation.getX(), targetLoc.getY() - sourceLocation.getY(), targetLoc.getZ() - sourceLocation.getZ());
        distanceSquared = targetDirection.lengthSquared();

        if (maxDistanceSquared > 0 && distanceSquared > maxDistanceSquared) return;
        if (distanceSquared < minDistanceSquared) return;

        Entity entity = getEntity();
        if (useHitbox)
        {
            double checkDistance = Math.max(maxDistanceSquared, 2);
            Vector endPoint = sourceLocation.clone().add(sourceDirection.multiply(checkDistance));
            Vector startPoint = sourceLocation.clone().add(sourceDirection.multiply(-1));
            BoundingBox hitbox = null;
            if (entity != null)
            {
                hitbox = CompatibilityUtils.getHitbox(entity);
            }
            if (hitbox == null)
            {
                // We make this a little smaller to ensure the coordinates stay inside the block
                hitbox =  new BoundingBox(targetLoc, -0.499, 0.499, -0.499, 0.499, -0.499, 0.499);
                if (DEBUG_TARGETING)
                {
                    if (entity != null) {
                        org.bukkit.Bukkit.getLogger().info(" failed to get hitbox for " + entity.getType() + " : " + targetLoc);
                    } else {
                        org.bukkit.Bukkit.getLogger().info(" got hitbox for block " + getBlock() + " : " + hitbox);
                    }
                }
            }
            if (hitboxPadding > 0)
            {<commit_msg>Fix spells hitting targets behind you<commit_after>package com.elmakers.mine.bukkit.utility;

import java.lang.ref.WeakReference;

import com.elmakers.mine.bukkit.block.MaterialAndData;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;

import com.elmakers.mine.bukkit.api.magic.Mage;

public class Target implements Comparable<Target>
{
    public static boolean DEBUG_TARGETING = false;

    protected int    maxDistanceSquared = 128 * 128;
    protected int    minDistanceSquared = 0;
    protected double maxAngle           = 0.3;
    protected boolean useHitbox         = false;
    protected double hitboxPadding      = 0;

    protected float distanceWeight = 1;
    protected float fovWeight = 4;
    protected int npcWeight = -1;
    protected int playerWeight = 4;
    protected int livingEntityWeight = 3;
    protected int mageWeight = 5;

    protected double closeDistanceSquared = 1;
    protected double closeAngle = Math.PI / 2;

    private Location source;
    private Location location;
    private MaterialAndData locationMaterial;
    private WeakReference<Entity>   _entity;
    private Mage	 mage;
    private boolean  reverseDistance = false;

    private double   distanceSquared    = 100000;
    private double   angle              = 10000;
    private int      score              = 0;

    private Object	 extraData	 = null;

    public Target(Location sourceLocation)
    {
        this.source = sourceLocation;
    }

    public void setBlock(Block block)
    {
        if (block != null) {
            this.location = block.getLocation();
            this.location.add(0.5, 0.5, 0.5);
        }
    }

    public Target(Location sourceLocation, Block block)
    {
        this.source = sourceLocation;
        this.locationMaterial = new MaterialAndData(block);
        this.setBlock(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Block block, boolean hitbox, double hitboxPadding)
    {
        this.source = sourceLocation;
        this.locationMaterial = new MaterialAndData(block);
        this.useHitbox = hitbox;
        this.hitboxPadding = hitboxPadding;
        this.setBlock(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Block block, int range)
    {
        this(sourceLocation, block, range, 0.3, false);
    }

    public Target(Location sourceLocation, Block block, int range, double angle)
    {
        this(sourceLocation, block, range, angle, false);
    }

    public Target(Location sourceLocation, Block block, int range, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this.setBlock(block);
        this.locationMaterial = new MaterialAndData(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Block block, int minRange, int maxRange, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = maxRange * maxRange;
        this.minDistanceSquared = minRange * minRange;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this.setBlock(block);
        this.locationMaterial = new MaterialAndData(block);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range)
    {
        this.maxDistanceSquared = range * range;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, boolean hitbox, double hitboxPadding)
    {
        this.maxDistanceSquared = range * range;
        this.source = sourceLocation;
        this.useHitbox = hitbox;
        this.hitboxPadding = hitboxPadding;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle)
    {
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle, double closeRange, double closeAngle,
                  float distanceWeight, float fovWeight, int mageWeight, int npcWeight, int playerWeight, int livingEntityWeight)
    {
        this.closeDistanceSquared = closeRange * closeRange;
        this.closeAngle = closeAngle;
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        this.distanceWeight = distanceWeight;
        this.fovWeight = fovWeight;
        this.mageWeight = mageWeight;
        this.npcWeight = npcWeight;
        this.playerWeight = playerWeight;
        this.livingEntityWeight = livingEntityWeight;

        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle, double closeRange, double closeAngle)
    {
        this.closeDistanceSquared = closeRange * closeRange;
        this.closeAngle = closeAngle;
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int range, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = range * range;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity, int minRange, int maxRange, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = maxRange * maxRange;
        this.minDistanceSquared = minRange * minRange;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
        calculateScore();
    }

    public Target(Location sourceLocation, Mage mage, int minRange, int maxRange, double angle, boolean reverseDistance)
    {
        this.maxDistanceSquared = maxRange * maxRange;
        this.minDistanceSquared = minRange * minRange;
        this.maxAngle = angle;
        this.reverseDistance = reverseDistance;
        this.source = sourceLocation;
        this.mage = mage;
        if (mage != null) {
            this._entity = new WeakReference<Entity>(mage.getLivingEntity());
        }
        if (mage != null) this.location = mage.getEyeLocation();
        calculateScore();
    }

    public Target(Location sourceLocation, Entity entity)
    {
        this.maxDistanceSquared = 0;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (entity != null) this.location = CompatibilityUtils.getEyeLocation(entity);
    }

    public Target(Location sourceLocation, Entity entity, Block block)
    {
        this.maxDistanceSquared = 0;
        this.source = sourceLocation;
        this._entity = new WeakReference<Entity>(entity);
        if (block != null) {
            this.setBlock(block);
        } else if (entity != null) {
            this.location = CompatibilityUtils.getEyeLocation(entity);
        }
    }

    public int getScore()
    {
        return score;
    }

    protected void calculateScore()
    {
        score = 0;
        if (source == null) return;

        Vector sourceDirection = source.getDirection();
        Vector sourceLocation = new Vector(source.getX(), source.getY(), source.getZ());

        Location targetLocation = getLocation();
        if (targetLocation == null) return;

        Vector targetLoc = new Vector(targetLocation.getX(), targetLocation.getY(), targetLocation.getZ());
        Vector targetDirection = new Vector(targetLoc.getX() - sourceLocation.getX(), targetLoc.getY() - sourceLocation.getY(), targetLoc.getZ() - sourceLocation.getZ());
        distanceSquared = targetDirection.lengthSquared();

        if (maxDistanceSquared > 0 && distanceSquared > maxDistanceSquared) return;
        if (distanceSquared < minDistanceSquared) return;

        Entity entity = getEntity();
        if (useHitbox)
        {
            double checkDistance = Math.max(maxDistanceSquared, 2);
            Vector endPoint = sourceLocation.clone().add(sourceDirection.clone().multiply(checkDistance));
            // Back up just a wee bit
            Vector startPoint = sourceLocation.clone().add(sourceDirection.multiply(-0.1));
            BoundingBox hitbox = null;
            if (entity != null)
            {
                hitbox = CompatibilityUtils.getHitbox(entity);
            }
            if (hitbox == null)
            {
                // We make this a little smaller to ensure the coordinates stay inside the block
                hitbox =  new BoundingBox(targetLoc, -0.499, 0.499, -0.499, 0.499, -0.499, 0.499);
                if (DEBUG_TARGETING)
                {
                    if (entity != null) {
                        org.bukkit.Bukkit.getLogger().info(" failed to get hitbox for " + entity.getType() + " : " + targetLoc);
                    } else {
                        org.bukkit.Bukkit.getLogger().info(" got hitbox for block " + getBlock() + " : " + hitbox);
                    }
                }
            }
            if (hitboxPadding > 0)
            {
{'fraction_non_alphanumeric': 0.09141063445258252, 'fraction_numerical': 0.00661086274136783, 'mean_word_length': 2.552458185504308, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5626479', 'n_tokens_mistral': 5749, 'n_tokens_neox': 5429, 'n_words': 1393}