Citizens2/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java

143 lines
4.1 KiB
Java
Raw Normal View History

2018-10-06 11:11:57 +02:00
package net.citizensnpcs.trait;
import java.util.UUID;
2018-10-06 11:11:57 +02:00
import org.bukkit.Bukkit;
2019-11-28 09:10:35 +01:00
import org.bukkit.entity.Entity;
2018-10-06 11:11:57 +02:00
import org.bukkit.entity.Player;
2019-11-28 09:10:35 +01:00
import org.bukkit.entity.Projectile;
2018-10-06 11:11:57 +02:00
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
2018-10-06 11:11:57 +02:00
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.ai.flocking.Flocker;
import net.citizensnpcs.api.ai.flocking.RadiusNPCFlock;
import net.citizensnpcs.api.ai.flocking.SeparationBehavior;
2018-10-06 11:11:57 +02:00
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
2023-12-02 07:55:37 +01:00
import net.citizensnpcs.util.Util;
2018-10-06 11:11:57 +02:00
2019-05-16 13:58:29 +02:00
/**
* Persists a {@link Player} to follow while spawned. Optionally allows protecting of the player as well.
*/
2018-10-06 11:11:57 +02:00
@TraitName("followtrait")
public class FollowTrait extends Trait {
private Entity entity;
private Flocker flock;
2018-10-06 11:11:57 +02:00
@Persist
private UUID followingUUID;
@Persist
2023-10-01 11:27:38 +02:00
private double margin = -1;
@Persist
2018-10-06 11:11:57 +02:00
private boolean protect;
public FollowTrait() {
super("followtrait");
}
private void cancelNavigationIfActive() {
if (npc.getNavigator().isNavigating() && entity != null && npc.getNavigator().getEntityTarget() != null
&& entity == npc.getNavigator().getEntityTarget().getTarget()) {
npc.getNavigator().cancelNavigation();
}
}
2023-05-05 18:45:57 +02:00
/**
* Sets the {@link Entity} to follow
*/
public void follow(Entity follow) {
cancelNavigationIfActive();
followingUUID = follow == null ? null : follow.getUniqueId();
entity = null;
2023-05-05 18:45:57 +02:00
}
public Entity getFollowing() {
return entity;
2020-10-07 13:16:41 +02:00
}
2023-10-01 11:27:38 +02:00
public double getFollowingMargin() {
return margin;
}
2019-05-16 13:58:29 +02:00
/**
* Returns whether the trait is actively following a {@link Entity}.
2019-05-16 13:58:29 +02:00
*/
public boolean isActive() {
2023-03-30 17:13:38 +02:00
return npc.isSpawned() && entity != null;
2019-05-16 13:58:29 +02:00
}
public boolean isEnabled() {
2023-03-30 17:13:38 +02:00
return followingUUID != null;
2018-10-06 11:11:57 +02:00
}
@Override
2021-03-02 13:52:41 +01:00
public void onDespawn() {
flock = null;
}
2018-10-06 11:11:57 +02:00
@EventHandler
2019-05-16 13:58:29 +02:00
private void onEntityDamage(EntityDamageByEntityEvent event) {
if (isActive() && protect && event.getEntity().equals(entity)) {
2019-11-28 09:10:35 +01:00
Entity damager = event.getDamager();
if (event.getEntity() instanceof Projectile) {
Projectile projectile = (Projectile) event.getEntity();
if (projectile.getShooter() instanceof Entity) {
damager = (Entity) projectile.getShooter();
}
}
npc.getNavigator().setTarget(damager, true);
2018-10-06 11:11:57 +02:00
}
}
2021-03-02 13:52:41 +01:00
@Override
public void onSpawn() {
flock = new Flocker(npc, new RadiusNPCFlock(4, 4), new SeparationBehavior(1));
2021-03-02 13:52:41 +01:00
}
2018-10-06 11:11:57 +02:00
@Override
public void run() {
if (entity == null || !entity.isValid()) {
if (followingUUID == null)
2018-10-06 11:11:57 +02:00
return;
entity = Bukkit.getPlayer(followingUUID);
if (entity == null) {
2023-12-02 07:55:37 +01:00
entity = Util.getEntity(followingUUID);
}
2023-03-30 18:11:29 +02:00
if (entity == null)
2018-10-06 11:11:57 +02:00
return;
}
2023-03-30 18:11:29 +02:00
if (!isActive())
2018-10-06 11:11:57 +02:00
return;
2023-03-30 18:11:29 +02:00
if (!npc.getEntity().getWorld().equals(entity.getWorld())) {
if (Setting.FOLLOW_ACROSS_WORLDS.asBoolean()) {
npc.teleport(entity.getLocation(), TeleportCause.PLUGIN);
}
return;
}
2018-10-06 11:11:57 +02:00
if (!npc.getNavigator().isNavigating()) {
npc.getNavigator().setTarget(entity, false);
2023-10-01 11:27:38 +02:00
if (margin > 0) {
npc.getNavigator().getLocalParameters().distanceMargin(margin);
}
} else {
flock.run();
2018-10-06 11:11:57 +02:00
}
}
2023-10-01 11:27:38 +02:00
public void setFollowingMargin(double margin) {
this.margin = margin;
cancelNavigationIfActive();
2023-10-01 11:27:38 +02:00
}
2019-05-16 13:58:29 +02:00
/**
2023-05-05 18:45:57 +02:00
* Sets whether to protect the followed Entity (similar to wolves in Minecraft, attack whoever attacks the entity).
2019-05-16 13:58:29 +02:00
*/
2023-05-05 18:45:57 +02:00
public void setProtect(boolean protect) {
2018-10-06 11:11:57 +02:00
this.protect = protect;
cancelNavigationIfActive();
2018-10-06 11:11:57 +02:00
}
}