package de.slikey.effectlib.util; import java.lang.ref.WeakReference; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.util.Vector; /** * Represents a Location that can move, possibly bound to an Entity. */ public class DynamicLocation { private final Location location; private final Location originalLocation; private final WeakReference<Entity> entity; private float yawOffset; private float pitchOffset; private Vector offset; private Vector relativeOffset; private Vector entityOffset; private boolean updateLocation = true; private boolean updateDirection = true; private Float yaw = null; private Float pitch = null; public DynamicLocation(Location location) { if (location != null) { this.location = location.clone(); } else { this.location = null; } this.originalLocation = location; this.entity = null; } public DynamicLocation(Entity entity) { if (entity != null) { this.entity = new WeakReference<Entity>(entity); this.location = getEntityLocation(entity); } else { this.entity = null; this.location = null; } this.originalLocation = location; } public DynamicLocation(Location location, Entity entity) { if (location != null) { this.location = location.clone(); } else if (entity != null) { this.location = getEntityLocation(entity); } else { this.location = null; } if (entity != null) { this.entity = new WeakReference<Entity>(entity); this.entityOffset = this.location.toVector().subtract(getEntityLocation(entity).toVector()); } else { this.entity = null; } this.originalLocation = this.location == null ? null : this.location.clone(); } public void addOffset(Vector offset) { if (this.offset == null) { this.offset = offset.clone(); } else { this.offset.add(offset); } this.updateOffsets(); } public void addRelativeOffset(Vector offset) { if (this.relativeOffset == null) { this.relativeOffset = offset.clone(); } else { this.relativeOffset.add(offset); } this.updateOffsets(); } public Entity getEntity() { return entity == null ? null : entity.get(); } public Location getLocation() { return location; } protected Location getEntityLocation(Entity entity) { if (entity instanceof LivingEntity) { return ((LivingEntity) entity).getEyeLocation(); } return entity.getLocation(); } public void setDirection(Vector direction) { location.setDirection(direction); updateDirection(); } public void updateDirection() { if (yaw != null) { location.setYaw(yaw); } if (pitch != null) { location.setPitch(pitch); } if (yawOffset != 0) { location.setYaw(location.getYaw() + yawOffset); } if (pitchOffset != 0) { location.setPitch(location.getPitch() + pitchOffset); } } public void updateFrom(Location newLocation) { if (originalLocation != null) { originalLocation.setX(newLocation.getX()); originalLocation.setY(newLocation.getY()); originalLocation.setZ(newLocation.getZ()); } updateOffsets(); } public void updateOffsets() { if (originalLocation == null || location == null) return; location.setX(originalLocation.getX()); location.setY(originalLocation.getY()); location.setZ(originalLocation.getZ()); if (offset != null) { location.add(offset); } if (relativeOffset != null) { location.add(VectorUtils.rotateVector(relativeOffset, location)); } if (entityOffset != null) { location.add(entityOffset); } } public void setUpdateLocation(boolean update) { updateLocation = update; } public void update() { if (location == null || (!updateLocation && !updateDirection)) { return; } Entity entityReference = entity == null ? null : entity.get(); if (entityReference != null) { Location currentLocation = getEntityLocation(entityReference); if (updateDirection) { setDirection(currentLocation.getDirection()); } if (updateLocation) { updateFrom(currentLocation); } } } public void setUpdateDirection(boolean updateDirection) { this.updateDirection = updateDirection; } public void setDirectionOffset(float yawOffset, float pitchOffset) { this.pitchOffset = pitchOffset; this.yawOffset = yawOffset; } public void setPitch(Float pitch) { this.pitch = pitch; } public void setYaw(Float yaw) { this.yaw = yaw; } public boolean hasValidEntity() { Entity entity = this.getEntity(); return entity != null && entity.isValid(); } }