Package net.citizensnpcs.resources.npclib

Source Code of net.citizensnpcs.resources.npclib.PathNPC

package net.citizensnpcs.resources.npclib;

import net.citizensnpcs.Plugins;
import net.citizensnpcs.Settings;
import net.citizensnpcs.resources.npclib.NPCAnimator.Animation;
import net.citizensnpcs.resources.npclib.creatures.CreatureNPC;
import net.citizensnpcs.utils.PacketUtils;
import net.minecraft.server.v1_6_R3.Entity;
import net.minecraft.server.v1_6_R3.EntityHuman;
import net.minecraft.server.v1_6_R3.EntityPlayer;
import net.minecraft.server.v1_6_R3.GenericAttributes;
import net.minecraft.server.v1_6_R3.MathHelper;
import net.minecraft.server.v1_6_R3.MinecraftServer;
import net.minecraft.server.v1_6_R3.Packet5EntityEquipment;
import net.minecraft.server.v1_6_R3.PathEntity;
import net.minecraft.server.v1_6_R3.PlayerInteractManager;
import net.minecraft.server.v1_6_R3.Vec3D;
import net.minecraft.server.v1_6_R3.World;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_6_R3.entity.CraftLivingEntity;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;

import com.sk89q.worldguard.protection.flags.DefaultFlag;

//TODO: FIX UP THIS WHOLE CLASS
public class PathNPC extends EntityPlayer {
    protected final NPCAnimator animations = new NPCAnimator(this);
    private int attackTimes = 0;
    private int attackTimesLimit = -1;
    private AutoPathfinder autoPathfinder;
    protected boolean autoPathToTarget = true;
    private Location dest;
    private boolean hasAttacked = false;
    public HumanNPC npc;
    private PathEntity path;
    protected float pathingRange = 16;
    private int pathTickLimit = -1;
    private int pathTicks = 0;
    private final net.minecraft.server.v1_6_R3.ItemStack[] previousEquipment = { null, null, null, null, null };
    private int prevX, prevY, prevZ;
    protected boolean randomPather = false;
    private int stationaryTickLimit = -1;
    private int stationaryTicks = 0;
    protected boolean targetAggro = false;
    protected Entity targetEntity;

    public PathNPC(MinecraftServer minecraftserver, World world, String s, PlayerInteractManager iteminworldmanager) {
        this(minecraftserver, world, s, iteminworldmanager, new MinecraftAutoPathfinder());
    }

    public PathNPC(MinecraftServer minecraftserver, World world, String s, PlayerInteractManager iteminworldmanager,
            AutoPathfinder autoPathfinder) {
        super(minecraftserver, world, s, iteminworldmanager);
        this.autoPathfinder = autoPathfinder;
    }

    private void attackEntity(Entity entity) {
        this.attackTicks = 20; // Possibly causes attack spam (maybe higher?).
        if (isHoldingBow() && distance(entity) >= Settings.getDouble("MinArrowRange")) {
            NPCManager.faceEntity(this.npc, entity.getBukkitEntity());

            // make inaccuracies.
            boolean up = this.random.nextBoolean();
            this.yaw += this.random.nextInt(5) * (up ? 1 : -1);

            up = this.random.nextBoolean();
            this.pitch += this.random.nextInt(5) * (up ? 1 : -1);

            this.getBukkitEntity().launchProjectile(Arrow.class);
        } else {
            this.performAction(Animation.SWING_ARM);
            LivingEntity other = (LivingEntity) entity.getBukkitEntity();
            other.damage(this.getAttributeInstance(GenericAttributes.e).getValue());
        }
        hasAttacked = true;

        if (this.attackTimesLimit == -1)
            return;
        ++this.attackTimes;
        if (this.attackTimes >= this.attackTimesLimit) {
            cancelTarget();
        }
    }

    public void cancelPath() {
        this.path = null;
        this.dest = null;
        this.pathTicks = this.stationaryTicks = 0;
        this.pathTickLimit = this.stationaryTickLimit = -1;
        this.pathingRange = 16;
    }

    public void cancelTarget() {
        this.targetEntity = null;
        this.targetAggro = false;
        this.attackTimes = 0;
        this.attackTimesLimit = -1;
        cancelPath();
    }

    PathEntity createPathEntity(int x, int y, int z) {
        return this.world.a(this, x, y, z, pathingRange, true, false, false, true);
    }

    private double distance(Entity entity) {
        return entity.getBukkitEntity().getLocation().distance(this.getBukkitEntity().getLocation());
    }

    protected EntityHuman getClosestPlayer(double range) {
        EntityHuman entityhuman = this.world.findNearbyPlayer(this, range);
        return entityhuman != null && isInSight(entityhuman) ? entityhuman : null;
    }

    private Vec3D getPathVector() {
        Vec3D vec3d = path.a(this);
        double length = (this.width * 2.0F);
        while (vec3d != null && vec3d.d(this.locX, vec3d.d, this.locZ) < length * length) {
            this.path.a(); // Increment path index.
            // Is path finished?
            if (this.path.b()) {
                Vec3D.a.release(vec3d);
                vec3d = null;
                cancelPath();
            } else {
                vec3d = this.path.a(this);
            }
        }
        return vec3d;
    }

    public int getStationaryTicks() {
        return this.stationaryTicks;
    }

    private float getYawDifference(double diffZ, double diffX) {
        float vectorYaw = (float) (Math.atan2(diffZ, diffX) * 180.0D / Math.PI) - 90.0F;
        float diffYaw = vectorYaw - this.yaw;

        this.bf = (float) this.getAttributeInstance(GenericAttributes.d).getValue();
        while (diffYaw >= 180.0F) {
            diffYaw -= 360.0F;
        }
        if (diffYaw > 30.0F) {
            diffYaw = 30.0F;
        }
        if (diffYaw < -30.0F) {
            diffYaw = -30.0F;
        }
        return diffYaw;
    }

    private void handleMove(Vec3D vector) {
        int yHeight = MathHelper.floor(this.boundingBox.b + 0.5D);
        boolean inWater = this.getBukkitEntity().getRemainingAir() < 20;
        boolean onFire = this.getBukkitEntity().getFireTicks() > 0;
        if (vector != null) {
            double diffX = vector.c - this.locX;
            double diffZ = vector.e - this.locZ;
            double diffY = vector.d - yHeight;
            float diffYaw = getYawDifference(diffZ, diffX);

            this.yaw += diffYaw;
            this.aP = this.yaw;
            this.aQ = this.yaw;
            if (diffY > 0.0D) {
                jump();
            }
            // TODO: adjust pitch.
            // Walk.
            this.e(this.be, this.bf);
        }
        if (this.positionChanged && !this.pathFinished()) {
            jump();
        }
        if (this.random.nextFloat() < 0.8F && (inWater || onFire)) {
            this.motY += 0.04D;
        }
        Vec3D.a.release(vector);
    }

    public boolean isAutoPathfinder() {
        return autoPathfinder != null;
    }

    private boolean isHoldingBow() {
        return getBukkitEntity().getItemInHand() != null && getBukkitEntity().getItemInHand().getType() == Material.BOW;
    }

    public boolean isInSight(Entity entity) {
        return this.o(entity);
    }

    private boolean isWithinAttackRange(Entity entity, double distance) {
        // Distance from EntityCreature.
        return this.attackTicks <= 0
                && ((isHoldingBow() && (distance > Settings.getDouble("MinArrowRange") && distance < Settings
                        .getDouble("MaxArrowRange"))) || (distance < 1.5F && entity.boundingBox.e > this.boundingBox.b && entity.boundingBox.b < this.boundingBox.e)
                        && isInSight(entity));
    }

    protected void jump() {
        if (this.onGround) {
            this.motY = 0.42D + JUMP_FACTOR;
            // Augment defaults to actually get over a block.
        }
    }

    public void moveTick() {
        if (this.dead) {
            if (this.targetEntity != null || this.path != null)
                cancelTarget();
            return;
        }
        updateEquipment();
        hasAttacked = false;
        if (randomPather) {
            takeRandomPath();
        }
        updateTarget();
        if (this.path != null || this.targetEntity != null) {
            updatePathingState();
        }
        if (this.path != null) {
            Vec3D vector = getPathVector();
            if (vector != null) {
                handleMove(vector);
            }
        }
        if (this.attackTicks > 0)
            --this.attackTicks;
        if (this.noDamageTicks > 0)
            --this.noDamageTicks; // Update entity
    }

    public boolean pathFinished() {
        return path == null;
    }

    public void performAction(Animation action) {
        this.animations.performAnimation(action);
    }

    public void setAutoPathfinder(boolean toggle) {
        if (toggle) {
            autoPathfinder = MinecraftAutoPathfinder.INSTANCE;
        } else
            autoPathfinder = null;
    }

    public void setTarget(LivingEntity entity, boolean aggro, int maxTicks, int maxStationaryTicks, double range) {
        if (Plugins.worldGuardEnabled() && Settings.getBoolean("DenyBlockedPVPTargets") && entity instanceof Player) {
            if (!Plugins.worldGuard.getGlobalRegionManager().allows(DefaultFlag.PVP, entity.getLocation()))
                return;
        }
        this.targetEntity = ((CraftLivingEntity) entity).getHandle();
        this.targetAggro = aggro;
        this.pathTickLimit = maxTicks;
        this.pathingRange = (float) range;
        this.stationaryTickLimit = maxStationaryTicks;
    }

    public boolean startPath(Location loc, int maxTicks, int maxStationaryTicks, double range) {
        this.pathTickLimit = maxTicks;
        this.stationaryTickLimit = maxStationaryTicks;
        this.pathingRange = (float) range;

        if (loc != null) {
            this.path = createPathEntity(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
            this.dest = loc.clone();
        }
        return pathFinished();
    }

    private void takeRandomPath() {
        if (!hasAttacked && this.targetEntity != null && (this.path == null || this.random.nextInt(20) == 0)) {
            this.path = this.world.findPath(this, this.targetEntity, pathingRange, true, false, false, true);
            this.dest = this.targetEntity.getBukkitEntity().getLocation();
        } else if (!hasAttacked && this.path == null)
            autoPathfinder.find(this);
    }

    public void targetClosestPlayer(boolean aggro, double range) {
        this.targetEntity = this.getClosestPlayer(range);
        this.targetAggro = aggro;
    }

    public boolean toggleAutoPathfinder() {
        if (autoPathfinder == null) {
            autoPathfinder = MinecraftAutoPathfinder.INSTANCE;
            return true;
        }
        autoPathfinder = null;
        return false;
    }

    private void updateEquipment() {
        for (int i = 0; i < previousEquipment.length; i++) {
            net.minecraft.server.v1_6_R3.ItemStack previous = previousEquipment[i];
            net.minecraft.server.v1_6_R3.ItemStack current = getEquipment(i);
            if (previous != current) {
                PacketUtils.sendPacketNearby(getBukkitEntity().getLocation(), 64, new Packet5EntityEquipment(id, i,
                        current));
                previousEquipment[i] = current;
            }
        }
    }

    private void updatePathingState() {
        Location loc = this.bukkitEntity.getLocation();
        if (prevX == loc.getBlockX() && prevY == loc.getBlockY() && prevZ == loc.getBlockZ()) {
            ++stationaryTicks;
        } else {
            stationaryTicks = 0;
        }
        ++pathTicks;
        if ((pathTickLimit != -1 && pathTicks >= pathTickLimit)
                || (stationaryTickLimit != -1 && stationaryTicks >= stationaryTickLimit)) {
            if (dest != null && !(this instanceof CreatureNPC)) {
                this.getBukkitEntity().teleport(dest);
            }
            cancelPath();
        }
        prevX = loc.getBlockX();
        prevY = loc.getBlockY();
        prevZ = loc.getBlockZ();
    }

    private void updateTarget() {
        if (!this.hasAttacked && this.targetEntity != null && autoPathToTarget) {
            this.path = this.world.findPath(this, this.targetEntity, pathingRange, true, false, false, true);
            this.dest = this.targetEntity.getBukkitEntity().getLocation();
        }
        if (targetEntity == null)
            return;
        if (this.targetEntity.dead || !targetEntity.world.equals(this.world)) {
            cancelTarget();
            return;
        }
        NPCManager.faceEntity(this.npc, targetEntity.getBukkitEntity());
        if (!targetAggro)
            return;
        if (isWithinAttackRange(this.targetEntity, distance(this.targetEntity))) {
            this.attackEntity(this.targetEntity);
        }
    }

    private static final double JUMP_FACTOR = 0.07D;
}
TOP

Related Classes of net.citizensnpcs.resources.npclib.PathNPC

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.