Allow /npc follow to work with entities rather than just players

This commit is contained in:
fullwall 2023-03-18 23:28:33 +08:00
parent 14e90b11b3
commit 48a30c56ff
4 changed files with 41 additions and 34 deletions

View File

@ -92,6 +92,12 @@
<version>2.5.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.joml</groupId>
<artifactId>joml</artifactId>
<version>1.10.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.citizensnpcs</groupId>
<artifactId>citizensapi</artifactId>
@ -227,6 +233,10 @@
<pattern>net.kyori</pattern>
<shadedPattern>clib.net.kyori</shadedPattern>
</relocation>
<relocation>
<pattern>org.joml</pattern>
<shadedPattern>clib.org.joml</shadedPattern>
</relocation>
<relocation>
<pattern>net.byteflux.libby</pattern>
<shadedPattern>clib.net.byteflux.libby</shadedPattern>

View File

@ -971,20 +971,16 @@ public class NPCCommands {
if (!(sender instanceof ConsoleCommandSender)
&& !followingNPC.getOrAddTrait(Owner.class).isOwnedBy(sender))
throw new CommandException(CommandMessages.MUST_BE_OWNER);
if (followingNPC.getEntity() instanceof Player) {
boolean following = followingNPC.getOrAddTrait(FollowTrait.class)
.toggle((Player) followingNPC.getEntity(), protect);
Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(),
followingNPC.getName());
} else {
throw new CommandException();
}
boolean following = followingNPC.getOrAddTrait(FollowTrait.class).toggle(followingNPC.getEntity(),
protect);
Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(),
followingNPC.getName());
};
NPCCommandSelector.startWithCallback(callback, CitizensAPI.getNPCRegistry(), sender, args,
args.getString(1));
return;
}
boolean following = npc.getOrAddTrait(FollowTrait.class).toggle(player, protect);
boolean following = npc.getOrAddTrait(FollowTrait.class).toggle(player.getPlayer(), protect);
Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(),
player.getName());
}

View File

@ -3,7 +3,6 @@ package net.citizensnpcs.trait;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
@ -26,10 +25,10 @@ import net.citizensnpcs.api.trait.TraitName;
public class FollowTrait extends Trait {
@Persist("active")
private boolean enabled = false;
private Entity entity;
private Flocker flock;
@Persist
private UUID followingUUID;
private Player player;
@Persist
private boolean protect;
@ -37,15 +36,15 @@ public class FollowTrait extends Trait {
super("followtrait");
}
public Player getFollowingPlayer() {
return player;
public Entity getFollowing() {
return entity;
}
/**
* Returns whether the trait is actively following a {@link Player}.
* Returns whether the trait is actively following a {@link Entity}.
*/
public boolean isActive() {
return enabled && npc.isSpawned() && player != null;
return enabled && npc.isSpawned() && entity != null;
}
public boolean isEnabled() {
@ -59,7 +58,7 @@ public class FollowTrait extends Trait {
@EventHandler
private void onEntityDamage(EntityDamageByEntityEvent event) {
if (isActive() && protect && event.getEntity().equals(player)) {
if (isActive() && protect && event.getEntity().equals(entity)) {
Entity damager = event.getDamager();
if (event.getEntity() instanceof Projectile) {
Projectile projectile = (Projectile) event.getEntity();
@ -78,53 +77,57 @@ public class FollowTrait extends Trait {
@Override
public void run() {
if (player == null || !player.isValid()) {
if (entity == null || !entity.isValid()) {
if (followingUUID == null)
return;
player = Bukkit.getPlayer(followingUUID);
if (player == null) {
entity = Bukkit.getPlayer(followingUUID);
if (entity == null) {
return;
}
entity = Bukkit.getEntity(followingUUID);
if (entity == null) {
return;
}
}
if (!isActive()) {
return;
}
if (!npc.getEntity().getWorld().equals(player.getWorld())) {
if (!npc.getEntity().getWorld().equals(entity.getWorld())) {
if (Setting.FOLLOW_ACROSS_WORLDS.asBoolean()) {
npc.teleport(player.getLocation(), TeleportCause.PLUGIN);
npc.teleport(entity.getLocation(), TeleportCause.PLUGIN);
}
return;
}
if (!npc.getNavigator().isNavigating()) {
npc.getNavigator().setTarget(player, false);
npc.getNavigator().setTarget(entity, false);
} else {
flock.run();
}
}
/**
* Toggles and/or sets the {@link OfflinePlayer} to follow and whether to protect them (similar to wolves in
* Minecraft, attack whoever attacks the player).
* Toggles and/or sets the {@link Entity} to follow and whether to protect them (similar to wolves in Minecraft,
* attack whoever attacks the entity).
*
* Will toggle if the {@link OfflinePlayer} is the player currently being followed.
* Will toggle if the {@link Entity} is the entity currently being followed.
*
* @param player
* @param entity
* the player to follow
* @param protect
* whether to protect the player
* @return whether the trait is enabled
*/
public boolean toggle(OfflinePlayer player, boolean protect) {
public boolean toggle(Entity entity, boolean protect) {
this.protect = protect;
if (player.getUniqueId().equals(this.followingUUID) || this.followingUUID == null) {
if (entity.getUniqueId().equals(this.followingUUID) || this.followingUUID == null) {
this.enabled = !enabled;
}
this.followingUUID = player.getUniqueId();
if (npc.getNavigator().isNavigating() && this.player != null && npc.getNavigator().getEntityTarget() != null
&& this.player == npc.getNavigator().getEntityTarget().getTarget()) {
this.followingUUID = entity.getUniqueId();
if (npc.getNavigator().isNavigating() && this.entity != null && npc.getNavigator().getEntityTarget() != null
&& this.entity == npc.getNavigator().getEntityTarget().getTarget()) {
npc.getNavigator().cancelNavigation();
}
this.player = null;
this.entity = null;
return this.enabled;
}
}

View File

@ -9,7 +9,6 @@ import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.Placeholders;
import net.citizensnpcs.npc.skin.SkinnableEntity;
import net.md_5.bungee.api.ChatColor;
@ -37,7 +36,6 @@ public class SkinTrait extends Trait {
if (skinName == null)
return;
String filled = ChatColor.stripColor(Placeholders.replace(skinName, null, npc).toLowerCase());
Messaging.idebug(() -> skinName + " " + filled + " " + filledPlaceholder);
if (!filled.equalsIgnoreCase(skinName) && !filled.equalsIgnoreCase(filledPlaceholder)) {
filledPlaceholder = filled;
if (update) {