Fix some bugs, implement new navigation customisation

This commit is contained in:
fullwall 2012-09-01 23:09:42 +08:00
parent 8cae31cc88
commit 50c18d22dd
7 changed files with 71 additions and 11 deletions

View File

@ -26,7 +26,9 @@ import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityCombustByBlockEvent;
import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.entity.EntityCombustEvent;
@ -135,6 +137,12 @@ public class EventListen implements Listener {
npc.despawn();
}
@EventHandler(priority = EventPriority.LOWEST)
public void onEntitySpawn(CreatureSpawnEvent event) {
if (event.isCancelled() && npcRegistry.isNPC(event.getEntity()))
event.setCancelled(false);
}
@EventHandler
public void onEntityTarget(EntityTargetEvent event) {
if (npcRegistry.isNPC(event.getEntity()) && event.getTarget() instanceof Player) {

View File

@ -57,6 +57,7 @@ public class Settings {
DEFAULT_PATHFINDING_RANGE("npc.default.pathfinding.range", 25F),
DEFAULT_RANDOM_TALKER("npc.default.random-talker", true),
DEFAULT_REALISTIC_LOOKING("npc.default.realistic-looking", false),
DEFAULT_STATIONARY_TICKS("npc.default.stationary-ticks", -1),
DEFAULT_TALK_CLOSE("npc.default.talk-close.enabled", false),
DEFAULT_TALK_CLOSE_RANGE("npc.default.talk-close.range", 5),
DEFAULT_TEXT("npc.default.text.0", "Hi, I'm <npc>!") {

View File

@ -104,7 +104,8 @@ public class NPCCommands {
desc = "Sets the behaviour of a NPC",
modifiers = { "behaviour", "ai" },
flags = "r",
min = 2)
min = 2,
permission = "npc.behaviour")
public void behaviour(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
Iterable<String> files = Splitter.on(',').split(args.getJoinedStrings(1, ','));
if (args.hasFlag('r')) {

View File

@ -4,6 +4,7 @@ import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.ai.EntityTarget;
import net.citizensnpcs.api.ai.Navigator;
import net.citizensnpcs.api.ai.NavigatorParameters;
import net.citizensnpcs.api.ai.StuckAction;
import net.citizensnpcs.api.ai.TargetType;
import net.citizensnpcs.api.ai.event.CancelReason;
import net.citizensnpcs.api.ai.event.NavigationBeginEvent;
@ -13,6 +14,7 @@ import net.citizensnpcs.api.ai.event.NavigationReplaceEvent;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.util.NMS;
import net.minecraft.server.EntityLiving;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@ -20,10 +22,14 @@ import org.bukkit.entity.LivingEntity;
public class CitizensNavigator implements Navigator {
private final NavigatorParameters defaultParams = new NavigatorParameters().speed(UNINITIALISED_SPEED)
.range(Setting.DEFAULT_PATHFINDING_RANGE.asFloat());
.range(Setting.DEFAULT_PATHFINDING_RANGE.asFloat())
.stationaryTicks(Setting.DEFAULT_STATIONARY_TICKS.asInt());
private PathStrategy executing;
private NavigatorParameters localParams = defaultParams;
private final CitizensNPC npc;
private int stationaryTicks;
private boolean updatedAvoidWater = false;
public CitizensNavigator(CitizensNPC npc) {
this.npc = npc;
@ -70,19 +76,32 @@ public class CitizensNavigator implements Navigator {
public void load(DataKey root) {
defaultParams.speed((float) root.getDouble("speed", UNINITIALISED_SPEED));
defaultParams.range((float) root.getDouble("pathfinding-range",
defaultParams.range((float) root.getDouble("pathfindingrange",
Setting.DEFAULT_PATHFINDING_RANGE.asFloat()));
defaultParams
.stationaryTicks(root.getInt("stationaryticks", Setting.DEFAULT_STATIONARY_TICKS.asInt()));
defaultParams.speedModifier((float) root.getDouble("speedmodifier", 1F));
if (root.keyExists("avoidwater"))
defaultParams.avoidWater(root.getBoolean("avoidwater"));
}
public void onSpawn() {
if (defaultParams.speed() == UNINITIALISED_SPEED)
defaultParams.speed(NMS.getSpeedFor(npc.getHandle()));
updatePathfindingRange();
if (!updatedAvoidWater) {
boolean defaultAvoidWater = npc.getHandle().getNavigation().a();
defaultParams.avoidWater(defaultAvoidWater);
updatedAvoidWater = true;
}
}
public void save(DataKey root) {
root.setDouble("speed", defaultParams.speed());
root.setDouble("pathfinding-range", defaultParams.range());
root.setDouble("speed", defaultParams.baseSpeed());
root.setDouble("pathfindingrange", defaultParams.range());
root.setInt("stationaryticks", defaultParams.stationaryTicks());
root.setDouble("speedmodifier", defaultParams.speedModifier());
root.setBoolean("avoidwater", defaultParams.avoidWater());
}
@Override
@ -122,7 +141,7 @@ public class CitizensNavigator implements Navigator {
}
public void update() {
if (!isNavigating() || !npc.isSpawned())
if (!isNavigating() || !npc.isSpawned() || updateStationaryStatus())
return;
boolean finished = executing.update();
if (finished) {
@ -135,5 +154,21 @@ public class CitizensNavigator implements Navigator {
NMS.updatePathfindingRange(npc, localParams.range());
}
private boolean updateStationaryStatus() {
if (localParams.stationaryTicks() < 0)
return false;
EntityLiving handle = npc.getHandle();
if ((int) handle.lastX == (int) handle.locX && (int) handle.lastY == (int) handle.locY
&& (int) handle.lastZ == (int) handle.locZ
&& ++stationaryTicks >= localParams.stationaryTicks()) {
StuckAction action = localParams.stuckAction();
if (action != null)
action.run(npc, this);
Bukkit.getPluginManager().callEvent(new NavigationCancelEvent(this, CancelReason.STUCK));
stopNavigating();
}
return true;
}
private static int UNINITIALISED_SPEED = Integer.MIN_VALUE;
}

View File

@ -43,6 +43,7 @@ public class MCNavigationStrategy implements PathStrategy {
@Override
public boolean update() {
navigation.a(parameters.avoidWater());
navigation.a(parameters.speed());
return navigation.f();
}

View File

@ -71,7 +71,6 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
@Override
public void begin() {
Messaging.send(player, "<b>Entered the text editor!");
conversation.begin();
}
@ -83,13 +82,16 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
}
public boolean hasIndex(int index) {
return text.size() > index;
return index >= 0 && text.size() > index;
}
@Override
public void load(DataKey key) throws NPCLoadException {
// TODO: backwards compat, remove later
for (DataKey sub : key.getIntegerSubKeys())
text.add(sub.getString(""));
for (DataKey sub : key.getRelative("text").getIntegerSubKeys())
text.add(sub.getString(""));
if (text.isEmpty())
populateDefaultText();
@ -153,8 +155,12 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
key.setBoolean("random-talker", randomTalker);
key.setBoolean("realistic-looking", realisticLooker);
key.setDouble("range", range);
// TODO: for backwards compat purposes, remove later
for (int i = 0; i < 100; i++)
key.removeKey(String.valueOf(i));
key.removeKey("text");
for (int i = 0; i < text.size(); i++)
key.setString(String.valueOf(i), text.get(i));
key.setString("text." + String.valueOf(i), text.get(i));
}
public boolean sendPage(Player player, int page) {

View File

@ -5,13 +5,13 @@ import java.util.List;
import javax.annotation.Nullable;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.Goal;
import net.citizensnpcs.api.ai.GoalSelector;
import net.citizensnpcs.api.ai.Navigator;
import net.citizensnpcs.api.ai.event.NavigationCompleteEvent;
import net.citizensnpcs.api.event.NPCDespawnEvent;
import net.citizensnpcs.api.event.NPCRemoveEvent;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.editor.Editor;
@ -72,6 +72,12 @@ public class LinearWaypointProvider implements WaypointProvider {
end();
}
@EventHandler
public void onNPCRemove(NPCRemoveEvent event) {
if (event.getNPC().equals(npc))
end();
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (!event.getPlayer().equals(player) || event.getAction() == Action.PHYSICAL)
@ -82,12 +88,13 @@ public class LinearWaypointProvider implements WaypointProvider {
|| event.getAction() == Action.LEFT_CLICK_AIR) {
if (event.getClickedBlock() == null)
return;
event.setCancelled(true);
Location at = event.getClickedBlock().getLocation();
Location prev = getPreviousWaypoint(editingSlot);
if (prev != null) {
double distance = at.distanceSquared(prev);
double maxDistance = Setting.DEFAULT_PATHFINDING_RANGE.asDouble();
double maxDistance = npc.getNavigator().getDefaultParameters().range();
maxDistance = Math.pow(maxDistance, 2);
if (distance > maxDistance) {
Messaging.sendF(player, ChatColor.RED
@ -105,6 +112,7 @@ public class LinearWaypointProvider implements WaypointProvider {
String.format("<e>Added<a> a waypoint at (" + formatLoc(at)
+ ") (<e>%d<a>, <e>%d<a>)", editingSlot + 1, waypoints.size()));
} else if (waypoints.size() > 0) {
event.setCancelled(true);
editingSlot = Math.min(0, Math.max(waypoints.size() - 1, editingSlot));
waypoints.remove(editingSlot);
editingSlot = Math.max(0, editingSlot - 1);