Fix traits/lookclose, use less memory in MCTargetStrategy, improve Behaviour (ie. scripts don't need to implement hashCode() any more)

This commit is contained in:
fullwall 2012-08-06 17:22:04 +08:00
parent 358cf996b1
commit eacf70202d
7 changed files with 72 additions and 32 deletions

View File

@ -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<String> 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(

View File

@ -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"))) {

View File

@ -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<? extends Trait> clazz = CitizensAPI.getTraitFactory().getTraitClass(args.getString(1));

View File

@ -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) {

View File

@ -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) {

View File

@ -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<Goal, Integer> addedGoals = Maps.newHashMap();
private final List<BehaviourGoalEntry> addedGoals = Lists.newArrayList();
private final Function<String, File> fileConverterFunction = new Function<String, File>() {
@Override
public File apply(String arg0) {
@ -63,14 +63,14 @@ public class Behaviour extends Trait {
@Override
public void onSpawn() {
for (Entry<Goal, Integer> 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<Goal, Integer> goals = Maps.newHashMap();
private final List<BehaviourGoalEntry> 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<Goal, Integer> 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<String> files) {
Iterable<File> transformed = Iterables.transform(files, fileConverterFunction);
boolean isSpawned = npc.isSpawned();
for (File file : transformed) {
if (isSpawned) {
Iterator<BehaviourGoalEntry> 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);
}
}
}

View File

@ -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);
}