package com.yaohun.petsystem.util.wolf; import com.yaohun.petsystem.PetMain; import com.yaohun.petsystem.model.PetNbt; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.block.Block; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Wolf; import org.bukkit.scheduler.BukkitRunnable; import java.util.UUID; public class CustomWolf { private static final double STOP_DISTANCE_SQ = 9.0D; private static final double TELEPORT_DISTANCE_SQ = 144.0D; private static final double FOLLOW_SPEED = 1.2D; private static final double DEFAULT_MOVEMENT_SPEED = 0.4D; private static final long FOLLOW_INTERVAL_TICKS = 10L; private final UUID ownerUuid; private final Wolf wolf; private CustomWolf(UUID ownerUuid, Wolf wolf) { this.ownerUuid = ownerUuid; this.wolf = wolf; startFollowTask(); } public Wolf getBukkitEntity() { return wolf; } public LivingEntity getBukkitLivingEntity() { return wolf; } public UUID getUUID() { return wolf.getUniqueId(); } public boolean isRemoved() { return !wolf.isValid(); } public static CustomWolf spawnCustomWolf(Player owner, PetNbt petNbt) { Wolf wolf = owner.getWorld().spawn(owner.getLocation(), Wolf.class, entity -> { entity.setSilent(true); entity.setTamed(true); entity.setOwner(owner); entity.setSitting(false); entity.setRemoveWhenFarAway(false); double maxHealth = Math.max(1.0D, petNbt.maxHealth); double health = Math.max(1.0D, Math.min(petNbt.health, maxHealth)); double damage = Math.max(0.0D, petNbt.damage); setAttribute(entity, Attribute.MAX_HEALTH, maxHealth); setAttribute(entity, Attribute.MOVEMENT_SPEED, DEFAULT_MOVEMENT_SPEED); setAttribute(entity, Attribute.ATTACK_DAMAGE, damage); entity.setHealth(health); }); return new CustomWolf(owner.getUniqueId(), wolf); } private void startFollowTask() { new BukkitRunnable() { @Override public void run() { if (!wolf.isValid() || wolf.isDead()) { cancel(); return; } Player owner = Bukkit.getPlayer(ownerUuid); if (owner == null || !owner.isOnline()) { wolf.remove(); cancel(); return; } if (owner.isDead()) { wolf.setTarget(null); return; } if (!owner.getWorld().equals(wolf.getWorld())) { teleportToOwner(owner); return; } double distanceSq = wolf.getLocation().distanceSquared(owner.getLocation()); if (distanceSq < STOP_DISTANCE_SQ) { wolf.setTarget(null); return; } if (distanceSq > TELEPORT_DISTANCE_SQ) { teleportToOwner(owner); } } }.runTaskTimer(PetMain.inst(), FOLLOW_INTERVAL_TICKS, FOLLOW_INTERVAL_TICKS); } private void teleportToOwner(Player owner) { Location location = owner.getLocation(); if (isSafeTeleportLocation(location)) { wolf.teleport(location); } } private boolean isSafeTeleportLocation(Location location) { Block feet = location.getBlock(); Block head = feet.getRelative(0, 1, 0); Block ground = feet.getRelative(0, -1, 0); return feet.isPassable() && head.isPassable() && ground.getType().isSolid(); } private static void setAttribute(LivingEntity entity, Attribute attribute, double value) { AttributeInstance instance = entity.getAttribute(attribute); if (instance != null) { instance.setBaseValue(value); } } }