From eacf70202d5bd4a5918de2771c92e997d060a434 Mon Sep 17 00:00:00 2001 From: fullwall Date: Mon, 6 Aug 2012 17:22:04 +0800 Subject: [PATCH] Fix traits/lookclose, use less memory in MCTargetStrategy, improve Behaviour (ie. scripts don't need to implement hashCode() any more) --- .../command/command/NPCCommands.java | 15 +++-- .../command/command/ScriptCommands.java | 2 +- .../command/command/TraitCommands.java | 4 +- .../npc/ai/MCNavigationStrategy.java | 6 -- .../citizensnpcs/npc/ai/MCTargetStrategy.java | 5 +- .../net/citizensnpcs/trait/Behaviour.java | 63 ++++++++++++++----- .../net/citizensnpcs/trait/LookClose.java | 9 ++- 7 files changed, 72 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java index e4a31b2b3..eb8d158af 100644 --- a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java @@ -96,15 +96,20 @@ public class NPCCommands { @Command( aliases = { "npc" }, - usage = "behaviour [scripts]", + usage = "behaviour [scripts] (-r)", desc = "Sets the behaviour of a NPC", modifiers = { "behaviour", "ai" }, - min = 2, - max = -1) + flags = "r", + min = 2) public void behaviour(CommandContext args, CommandSender sender, NPC npc) throws CommandException { Iterable files = Splitter.on(',').split(args.getJoinedStrings(1, ',')); - npc.getTrait(Behaviour.class).addScripts(files); - sender.sendMessage(ChatColor.GREEN + "Behaviours added."); + if (args.hasFlag('r')) { + npc.getTrait(Behaviour.class).addScripts(files); + sender.sendMessage(ChatColor.GREEN + "Behaviours added."); + } else { + npc.getTrait(Behaviour.class).removeScripts(files); + sender.sendMessage(ChatColor.GREEN + "Behaviours removed."); + } } @Command( diff --git a/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java b/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java index e74a52216..83eec27a9 100644 --- a/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java @@ -40,7 +40,7 @@ public class ScriptCommands { } @Override - public void onScriptCompiled(ScriptFactory script) { + public void onScriptCompiled(File file, ScriptFactory script) { Script s = script.newInstance(); if (args.hasValueFlag("methods")) { for (String m : Splitter.on(',').split(args.getFlag("methods"))) { diff --git a/src/main/java/net/citizensnpcs/command/command/TraitCommands.java b/src/main/java/net/citizensnpcs/command/command/TraitCommands.java index d5f53d4ae..919e7ea19 100644 --- a/src/main/java/net/citizensnpcs/command/command/TraitCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/TraitCommands.java @@ -26,7 +26,7 @@ public class TraitCommands { flags = "r", permission = "npc.trait") public void add(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String traitName = args.getString(1); + String traitName = args.getString(0); if (!sender.hasPermission("citizens.npc.trait." + traitName)) throw new NoPermissionsException(); if (args.hasFlag('r')) { @@ -57,7 +57,7 @@ public class TraitCommands { flags = "*", permission = "npc.trait-configure") public void configure(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String traitName = args.getString(1); + String traitName = args.getString(0); if (!sender.hasPermission("citizens.npc.trait-configure." + traitName)) throw new NoPermissionsException(); Class clazz = CitizensAPI.getTraitFactory().getTraitClass(args.getString(1)); diff --git a/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java b/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java index 197286559..1eb98892d 100644 --- a/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java +++ b/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java @@ -15,12 +15,6 @@ public class MCNavigationStrategy implements PathStrategy { MCNavigationStrategy(final CitizensNPC npc, Location dest, float speed) { this(npc.getHandle(), dest); navigation.a(dest.getX(), dest.getY(), dest.getZ(), speed); - - } - - MCNavigationStrategy(EntityLiving entity, EntityLiving target, float speed) { - this(entity, target.getBukkitEntity().getLocation()); - navigation.a(target, speed); } private MCNavigationStrategy(EntityLiving entity, Location target) { diff --git a/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java b/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java index 75095fab5..7dda1b802 100644 --- a/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java +++ b/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java @@ -7,6 +7,7 @@ import net.citizensnpcs.util.Util; import net.minecraft.server.EntityLiving; import net.minecraft.server.EntityMonster; import net.minecraft.server.EntityPlayer; +import net.minecraft.server.Navigation; import net.minecraft.server.Packet18ArmAnimation; import org.bukkit.Location; @@ -18,10 +19,12 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { private int attackTicks; private final EntityLiving handle, target; private final float speed; + private final Navigation navigation; public MCTargetStrategy(CitizensNPC handle, LivingEntity target, boolean aggro, float speed) { this.handle = handle.getHandle(); this.target = ((CraftLivingEntity) target).getHandle(); + this.navigation = this.handle.getNavigation(); this.aggro = aggro; this.speed = speed; } @@ -60,7 +63,7 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { public boolean update() { if (target == null || target.dead) return true; - new MCNavigationStrategy(handle, target, speed).update(); + navigation.a(target, speed); handle.getControllerLook().a(target, 10.0F, handle.bf()); if (aggro && canAttack()) { if (handle instanceof EntityMonster) { diff --git a/src/main/java/net/citizensnpcs/trait/Behaviour.java b/src/main/java/net/citizensnpcs/trait/Behaviour.java index 90ddabde7..29d3eecf3 100644 --- a/src/main/java/net/citizensnpcs/trait/Behaviour.java +++ b/src/main/java/net/citizensnpcs/trait/Behaviour.java @@ -1,12 +1,13 @@ package net.citizensnpcs.trait; import java.io.File; +import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.ai.Goal; +import net.citizensnpcs.api.ai.GoalController.GoalEntry; +import net.citizensnpcs.api.ai.SimpleGoalEntry; import net.citizensnpcs.api.exception.NPCLoadException; import net.citizensnpcs.api.scripting.CompileCallback; import net.citizensnpcs.api.scripting.ScriptFactory; @@ -20,10 +21,9 @@ import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; public class Behaviour extends Trait { - private final Map addedGoals = Maps.newHashMap(); + private final List addedGoals = Lists.newArrayList(); private final Function fileConverterFunction = new Function() { @Override public File apply(String arg0) { @@ -63,14 +63,14 @@ public class Behaviour extends Trait { @Override public void onSpawn() { - for (Entry entry : addedGoals.entrySet()) { - npc.getDefaultGoalController().addGoal(entry.getKey(), entry.getValue()); + for (GoalEntry entry : addedGoals) { + npc.getDefaultGoalController().addGoal(entry.getGoal(), entry.getPriority()); } } private void removeGoals() { - for (Goal entry : addedGoals.keySet()) { - npc.getDefaultGoalController().removeGoal(entry); + for (GoalEntry entry : addedGoals) { + npc.getDefaultGoalController().removeGoal(entry.getGoal()); } } @@ -85,27 +85,60 @@ public class Behaviour extends Trait { key.setString("scripts", Joiner.on(",").join(scripts)); } + private static class BehaviourGoalEntry extends SimpleGoalEntry { + private final File file; + + private BehaviourGoalEntry(Goal goal, int priority, File file) { + super(goal, priority); + this.file = file; + } + } + public class BehaviourCallback implements CompileCallback { - private final Map goals = Maps.newHashMap(); + private final List goals = Lists.newArrayList(); + private File fileInUse; public void addGoal(int priority, Goal goal) { Validate.notNull(goal); - goals.put(goal, priority); + goals.add(new BehaviourGoalEntry(goal, priority, fileInUse)); } @Override public void onCompileTaskFinished() { - addedGoals.putAll(goals); + addedGoals.addAll(goals); if (!npc.isSpawned()) return; - for (Entry entry : goals.entrySet()) { - npc.getDefaultGoalController().addGoal(entry.getKey(), entry.getValue()); + for (GoalEntry entry : goals) { + npc.getDefaultGoalController().addGoal(entry.getGoal(), entry.getPriority()); } } @Override - public void onScriptCompiled(ScriptFactory script) { - script.newInstance().invoke("addGoals", this, npc); + public void onScriptCompiled(File file, ScriptFactory script) { + synchronized (goals) { + fileInUse = file; + script.newInstance().invoke("addGoals", this, npc); + scripts.add(file); + fileInUse = null; + } + } + } + + public void removeScripts(Iterable files) { + Iterable transformed = Iterables.transform(files, fileConverterFunction); + boolean isSpawned = npc.isSpawned(); + for (File file : transformed) { + if (isSpawned) { + Iterator itr = addedGoals.iterator(); + while (itr.hasNext()) { + BehaviourGoalEntry entry = itr.next(); + if (file.equals(entry.file)) { + itr.remove(); + npc.getDefaultGoalController().removeGoal(entry.getGoal()); + } + } + } + scripts.remove(file); } } } diff --git a/src/main/java/net/citizensnpcs/trait/LookClose.java b/src/main/java/net/citizensnpcs/trait/LookClose.java index 9bc3837e9..835a92043 100644 --- a/src/main/java/net/citizensnpcs/trait/LookClose.java +++ b/src/main/java/net/citizensnpcs/trait/LookClose.java @@ -73,7 +73,8 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable @Override public void load(DataKey key) throws NPCLoadException { - enabled = key.getBoolean(""); + enabled = key.getBoolean("enabled", key.getBoolean("")); + // TODO: remove key.getBoolean("") ^ after a few updates range = key.getDouble("range", range); realisticLooking = key.getBoolean("realistic-looking", false); } @@ -90,7 +91,11 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable @Override public void save(DataKey key) { - key.setBoolean("", enabled); + if (key.keyExists("")) { + // TODO: remove after a few updates + key.removeKey(""); + } + key.setBoolean("enabled", enabled); key.setDouble("range", range); key.setBoolean("realistic-looking", realisticLooking); }