From 787e114faaca356a1a0a081b592dde7321b1e72e Mon Sep 17 00:00:00 2001 From: fullwall Date: Sat, 6 Oct 2018 17:11:57 +0800 Subject: [PATCH] Add a super simple follow trait --- .../citizensnpcs/commands/NPCCommands.java | 19 ++++++ .../npc/CitizensTraitFactory.java | 4 +- .../net/citizensnpcs/trait/FollowTrait.java | 68 +++++++++++++++++++ .../java/net/citizensnpcs/util/Messages.java | 3 + .../src/main/resources/messages_en.properties | 2 + 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 main/src/main/java/net/citizensnpcs/trait/FollowTrait.java diff --git a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java index ab58af32c..43ff6656d 100644 --- a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -73,6 +73,7 @@ import net.citizensnpcs.trait.Anchors; import net.citizensnpcs.trait.ArmorStandTrait; import net.citizensnpcs.trait.Controllable; import net.citizensnpcs.trait.CurrentLocation; +import net.citizensnpcs.trait.FollowTrait; import net.citizensnpcs.trait.Gravity; import net.citizensnpcs.trait.HorseModifiers; import net.citizensnpcs.trait.LookClose; @@ -509,6 +510,24 @@ public class NPCCommands { Messaging.sendTr(sender, flyable ? Messages.FLYABLE_SET : Messages.FLYABLE_UNSET, npc.getName()); } + @Command( + aliases = { "npc" }, + usage = "follow (player name) (-p[rotect])", + desc = "Toggles NPC following you", + modifiers = { "follow" }, + min = 1, + max = 1, + permission = "citizens.npc.follow") + public void follow(CommandContext args, Player sender, NPC npc) throws CommandException { + boolean protect = args.hasFlag('p'); + String name = sender.getName(); + if (args.argsLength() > 1) { + name = args.getString(1); + } + boolean following = npc.getTrait(FollowTrait.class).toggle(name, protect); + Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(), name); + } + @Command( aliases = { "npc" }, usage = "gamemode [gamemode]", diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java index 6bf5066bb..29ce1d21d 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java @@ -24,6 +24,7 @@ import net.citizensnpcs.trait.Anchors; import net.citizensnpcs.trait.ArmorStandTrait; import net.citizensnpcs.trait.Controllable; import net.citizensnpcs.trait.CurrentLocation; +import net.citizensnpcs.trait.FollowTrait; import net.citizensnpcs.trait.Gravity; import net.citizensnpcs.trait.HorseModifiers; import net.citizensnpcs.trait.LookClose; @@ -53,11 +54,12 @@ public class CitizensTraitFactory implements TraitFactory { registerTrait(TraitInfo.create(ArmorStandTrait.class)); registerTrait(TraitInfo.create(Anchors.class)); registerTrait(TraitInfo.create(Controllable.class)); + registerTrait(TraitInfo.create(CurrentLocation.class)); registerTrait(TraitInfo.create(Equipment.class)); + registerTrait(TraitInfo.create(FollowTrait.class)); registerTrait(TraitInfo.create(Gravity.class)); registerTrait(TraitInfo.create(HorseModifiers.class)); registerTrait(TraitInfo.create(Inventory.class)); - registerTrait(TraitInfo.create(CurrentLocation.class)); registerTrait(TraitInfo.create(LookClose.class)); registerTrait(TraitInfo.create(OcelotModifiers.class)); registerTrait(TraitInfo.create(Owner.class)); diff --git a/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java b/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java new file mode 100644 index 000000000..69f00b518 --- /dev/null +++ b/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java @@ -0,0 +1,68 @@ +package net.citizensnpcs.trait; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +import net.citizensnpcs.api.persistence.Persist; +import net.citizensnpcs.api.trait.Trait; +import net.citizensnpcs.api.trait.TraitName; + +@TraitName("followtrait") +public class FollowTrait extends Trait { + @Persist + private boolean active = false; + @Persist + private String followingName; + private Player player; + @Persist("protect") + private boolean protect; + + public FollowTrait() { + super("followtrait"); + } + + private boolean isActive() { + return active && npc.isSpawned() && player != null && npc.getEntity().getWorld().equals(player.getWorld()); + } + + @EventHandler + public void onEntityDamage(EntityDamageByEntityEvent event) { + if (isActive() && event.getEntity().equals(player)) { + npc.getNavigator().setTarget(event.getDamager(), true); + } + } + + @Override + public void run() { + if (player == null || !player.isValid()) { + if (followingName == null) + return; + player = Bukkit.getPlayerExact(followingName); + if (player == null) { + return; + } + } + if (!isActive()) { + return; + } + if (!npc.getNavigator().isNavigating()) { + npc.getNavigator().setTarget(player, false); + } + } + + public boolean toggle(String name, boolean protect) { + this.protect = protect; + if (name.equalsIgnoreCase(this.followingName) || this.followingName == null) { + this.active = !active; + } + this.followingName = name; + if (npc.getNavigator().isNavigating() && player != null + && player == npc.getNavigator().getEntityTarget().getTarget()) { + npc.getNavigator().cancelNavigation(); + } + this.player = null; + return this.active; + } +} diff --git a/main/src/main/java/net/citizensnpcs/util/Messages.java b/main/src/main/java/net/citizensnpcs/util/Messages.java index 0ab3dc6f5..7d1cb7471 100644 --- a/main/src/main/java/net/citizensnpcs/util/Messages.java +++ b/main/src/main/java/net/citizensnpcs/util/Messages.java @@ -80,6 +80,9 @@ public class Messages { public static final String FAILED_TO_REMOVE = "citizens.commands.trait.failed-to-remove"; public static final String FLYABLE_SET = "citizens.commands.npc.flyable.set"; public static final String FLYABLE_UNSET = "citizens.commands.npc.flyable.unset"; + public static final String FOLLOW_PLAYER_NOT_INGAME = "citizens.commands.npc.follow.player-not-ingame"; + public static final String FOLLOW_SET = "citizens.commands.npc.follow.set"; + public static final String FOLLOW_UNSET = "citizens.commands.npc.follow.unset"; public static final String FROM_ENTITY_NOT_FOUND = "citizens.commands.npc.tpto.from-not-found"; public static final String GAMEMODE_DESCRIBE = "citizens.commands.npc.gamemode.describe"; public static final String GAMEMODE_INVALID = "citizens.commands.npc.gamemode.invalid"; diff --git a/main/src/main/resources/messages_en.properties b/main/src/main/resources/messages_en.properties index be9c15322..33c95e3c9 100644 --- a/main/src/main/resources/messages_en.properties +++ b/main/src/main/resources/messages_en.properties @@ -39,6 +39,8 @@ citizens.commands.npc.create.no-player-for-spawn=No player could be found by tha citizens.commands.npc.despawn.despawned=You despawned [[{0}]]. citizens.commands.npc.flyable.set=[[{0}]] is now flyable. citizens.commands.npc.flyable.unset=[[{0}]] is no longer flyable. +citizens.commands.npc.follow.set=[[{0}]] is now following [[{1}]]. +citizens.commands.npc.follow.unset=[[{0}]] is no longer following anyone. citizens.commands.npc.gamemode.describe={0}''s gamemode is [[{1}]]. citizens.commands.npc.gamemode.invalid={0} is not a valid gamemode. citizens.commands.npc.gamemode.set=Gamemode set to [[{0}]].