From f7e85f08abf421e774f67d535e595b1d0db1669b Mon Sep 17 00:00:00 2001 From: fullwall Date: Sat, 21 Apr 2012 14:12:30 +0800 Subject: [PATCH] Rework lookclose logic, Controllable is now Toggleable --- .../command/command/NPCCommands.java | 5 +- .../net/citizensnpcs/trait/Controllable.java | 10 ++- .../net/citizensnpcs/trait/LookClose.java | 76 +++++++++++++------ 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java index 17e9c63a3..c572503e5 100644 --- a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java @@ -459,11 +459,10 @@ public class NPCCommands { max = 1, permission = "npc.controllable") public void controllable(CommandContext args, Player player, NPC npc) { - if (npc.hasTrait(Controllable.class)) { - npc.removeTrait(Controllable.class); + boolean enabled = npc.getTrait(Controllable.class).toggle(); + if (enabled) { Messaging.send(player, StringHelper.wrap(npc.getName()) + " can no longer be controlled."); } else { - npc.addTrait(traitManager.getTrait(Controllable.class, npc)); Messaging.send(player, StringHelper.wrap(npc.getName()) + " can now be controlled."); } diff --git a/src/main/java/net/citizensnpcs/trait/Controllable.java b/src/main/java/net/citizensnpcs/trait/Controllable.java index 91c69823d..3d958a92d 100644 --- a/src/main/java/net/citizensnpcs/trait/Controllable.java +++ b/src/main/java/net/citizensnpcs/trait/Controllable.java @@ -15,8 +15,9 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; //TODO: reduce reliance on CitizensNPC -public class Controllable extends Trait implements Runnable, Listener { +public class Controllable extends Trait implements Runnable, Listener, Toggleable { private final CitizensNPC npc; + private boolean enabled; public Controllable(NPC npc) { this.npc = (CitizensNPC) npc; @@ -30,6 +31,7 @@ public class Controllable extends Trait implements Runnable, Listener { @Override public void load(DataKey key) throws NPCLoadException { + enabled = key.getBoolean("enabled"); } @EventHandler @@ -63,7 +65,13 @@ public class Controllable extends Trait implements Runnable, Listener { @Override public void save(DataKey key) { + key.setBoolean("enabled", enabled); } private static final double JUMP_VELOCITY = 0.6; + + @Override + public boolean toggle() { + return (enabled = !enabled); + } } diff --git a/src/main/java/net/citizensnpcs/trait/LookClose.java b/src/main/java/net/citizensnpcs/trait/LookClose.java index a1746c25c..d3d2dfccf 100644 --- a/src/main/java/net/citizensnpcs/trait/LookClose.java +++ b/src/main/java/net/citizensnpcs/trait/LookClose.java @@ -1,33 +1,38 @@ package net.citizensnpcs.trait; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.exception.NPCLoadException; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.util.DataKey; -import net.citizensnpcs.npc.CitizensNPC; - import net.minecraft.server.EntityLiving; import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; public class LookClose extends Trait implements Runnable, Toggleable { - private boolean lookClose = Setting.DEFAULT_LOOK_CLOSE.asBoolean(); + private boolean enabled = Setting.DEFAULT_LOOK_CLOSE.asBoolean(); + private Player lookingAt; private final NPC npc; public LookClose(NPC npc) { this.npc = npc; } - private void faceEntity(CitizensNPC npc, Entity target) { - if (npc.getBukkitEntity().getWorld() != target.getWorld()) + private void faceEntity(Entity from, Entity at) { + if (from.getWorld() != at.getWorld()) return; - Location loc = npc.getBukkitEntity().getLocation(); + Location loc = from.getLocation(); - double xDiff = target.getLocation().getX() - loc.getX(); - double yDiff = target.getLocation().getY() - loc.getY(); - double zDiff = target.getLocation().getZ() - loc.getZ(); + double xDiff = at.getLocation().getX() - loc.getX(); + double yDiff = at.getLocation().getY() - loc.getY(); + double zDiff = at.getLocation().getZ() - loc.getZ(); double distanceXZ = Math.sqrt(xDiff * xDiff + zDiff * zDiff); double distanceY = Math.sqrt(distanceXZ * distanceXZ + yDiff * yDiff); @@ -38,38 +43,65 @@ public class LookClose extends Trait implements Runnable, Toggleable { yaw = yaw + (Math.abs(180 - yaw) * 2); } - npc.getHandle().yaw = (float) yaw - 90; - npc.getHandle().pitch = (float) pitch; - npc.getHandle().X = npc.getHandle().yaw; + EntityLiving handle = ((CraftLivingEntity) from).getHandle(); + handle.yaw = (float) yaw - 90; + handle.pitch = (float) pitch; + handle.X = handle.yaw; } @Override public void load(DataKey key) throws NPCLoadException { - lookClose = key.getBoolean(""); + enabled = key.getBoolean("enabled"); } @Override public void run() { - EntityLiving search = null; - CitizensNPC handle = (CitizensNPC) npc; - if (!npc.getAI().hasDestination() - && (search = handle.getHandle().world.findNearbyPlayer(handle.getHandle(), 5)) != null && lookClose) - faceEntity(handle, search.getBukkitEntity()); + if (!enabled || npc.getAI().hasDestination()) + return; + if (hasInvalidTarget()) { + findNewTarget(); + } else { + faceEntity(npc.getBukkitEntity(), lookingAt); + } + } + + private void findNewTarget() { + List nearby = npc.getBukkitEntity().getNearbyEntities(2.5, 5, 2.5); + Collections.sort(nearby, new Comparator() { + @Override + public int compare(Entity o1, Entity o2) { + double d1 = o1.getLocation().distanceSquared(npc.getBukkitEntity().getLocation()); + double d2 = o2.getLocation().distanceSquared(npc.getBukkitEntity().getLocation()); + return Double.compare(d1, d2); + } + }); + for (Entity entity : nearby) { + if (entity instanceof Player) { + lookingAt = (Player) entity; + return; + } + } + lookingAt = null; + } + + private boolean hasInvalidTarget() { + return lookingAt == null || !lookingAt.isOnline() + || lookingAt.getLocation().distanceSquared(npc.getBukkitEntity().getLocation()) > 5; } @Override public void save(DataKey key) { - key.setBoolean("", lookClose); + key.setBoolean("enabled", enabled); } @Override public boolean toggle() { - lookClose = !lookClose; - return lookClose; + enabled = !enabled; + return enabled; } @Override public String toString() { - return "LookClose{" + lookClose + "}"; + return "LookClose{" + enabled + "}"; } } \ No newline at end of file