Files
AuPet/src/main/java/com/yaohun/petsystem/util/wolf/CustomWolf.java
2026-06-03 07:09:32 +08:00

125 lines
4.1 KiB
Java

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);
}
}
}