Add a setting to use the new pathfinder (temporary, will be removed)

This commit is contained in:
fullwall 2012-11-27 22:09:42 +08:00
parent 4ec8a3c280
commit 6a637fe903
17 changed files with 239 additions and 134 deletions

View File

@ -62,7 +62,7 @@ public class EventListen implements Listener {
private final ListMultimap<ChunkCoord, Integer> toRespawn = ArrayListMultimap.create();
public EventListen() {
instance = this;
instance = this; // TODO: remove singleton
}
/*

View File

@ -85,7 +85,8 @@ public class Settings {
SUBPLUGIN_FOLDER("subplugins.folder", "plugins"),
TALK_CLOSE_MAXIMUM_COOLDOWN("npc.text.max-talk-cooldown", 60),
TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 30),
TALK_ITEM("npc.text.talk-item", "340");
TALK_ITEM("npc.text.talk-item", "340"),
USE_NEW_PATHFINDER("npc.pathfinding.use-new-finder", false);
protected String path;
protected Object value;

View File

@ -223,14 +223,12 @@ public class CommandManager {
// Requirements
if (cmdRequirements.selected()) {
boolean canRedefineSelected = context.hasValueFlag("id")
&& sender.hasPermission("npc.select");
boolean canRedefineSelected = context.hasValueFlag("id") && sender.hasPermission("npc.select");
String error = Messaging.tr(Messages.COMMAND_MUST_HAVE_SELECTED);
if (canRedefineSelected) {
npc = CitizensAPI.getNPCRegistry().getById(context.getFlagInteger("id"));
if (npc == null)
error += ' ' + Messaging.tr(Messages.COMMAND_ID_NOT_FOUND,
context.getFlagInteger("id"));
error += ' ' + Messaging.tr(Messages.COMMAND_ID_NOT_FOUND, context.getFlagInteger("id"));
}
if (npc == null)
throw new RequirementMissingException(error);
@ -249,8 +247,7 @@ public class CommandManager {
}
if (npc != null) {
Set<EntityType> types = Sets.newEnumSet(Arrays.asList(cmdRequirements.types()),
EntityType.class);
Set<EntityType> types = Sets.newEnumSet(Arrays.asList(cmdRequirements.types()), EntityType.class);
if (types.contains(EntityType.UNKNOWN))
types = EnumSet.allOf(EntityType.class);
types.removeAll(Sets.newHashSet(cmdRequirements.excludedTypes()));

View File

@ -0,0 +1,65 @@
package net.citizensnpcs.npc.ai;
import net.citizensnpcs.api.ai.NavigatorParameters;
import net.citizensnpcs.api.ai.TargetType;
import net.citizensnpcs.api.ai.event.CancelReason;
import net.citizensnpcs.api.astar.AStarMachine;
import net.citizensnpcs.api.astar.pathfinder.ChunkBlockSource;
import net.citizensnpcs.api.astar.pathfinder.Path;
import net.citizensnpcs.api.astar.pathfinder.VectorGoal;
import net.citizensnpcs.api.astar.pathfinder.VectorNode;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.util.NMS;
import org.bukkit.Location;
import org.bukkit.util.Vector;
public class AStarNavigationStrategy extends AbstractPathStrategy {
private final Location dest;
private final CitizensNPC npc;
private final NavigatorParameters params;
private Path plan;
private Vector vector;
AStarNavigationStrategy(CitizensNPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.params = params;
this.dest = dest;
this.npc = npc;
Location location = npc.getBukkitEntity().getLocation();
plan = (Path) ASTAR.runFully(new VectorGoal(dest), new VectorNode(location, new ChunkBlockSource(
location, params.range()), params.examiners()), 10000);
if (plan == null || plan.isComplete())
setCancelReason(CancelReason.STUCK);
else
vector = plan.getCurrentVector();
}
@Override
public Location getTargetAsLocation() {
return dest;
}
@Override
public void stop() {
plan = null;
}
@Override
public boolean update() {
if (getCancelReason() != null)
return true;
if (plan.isComplete())
return true;
if (NMS.distanceSquared(npc.getHandle(), vector) <= params.distanceMargin()) {
plan.update(npc);
if (plan.isComplete())
return true;
vector = plan.getCurrentVector();
}
npc.getHandle().getControllerMove().a(vector.getX(), vector.getY(), vector.getZ(), params.speed());
return false;
}
private static final AStarMachine ASTAR = AStarMachine.createWithDefaultStorage();
}

View File

@ -0,0 +1,32 @@
package net.citizensnpcs.npc.ai;
import net.citizensnpcs.api.ai.TargetType;
import net.citizensnpcs.api.ai.event.CancelReason;
public abstract class AbstractPathStrategy implements PathStrategy {
private CancelReason cancelReason;
private final TargetType type;
protected AbstractPathStrategy(TargetType type) {
this.type = type;
}
@Override
public void clearCancelReason() {
cancelReason = null;
}
@Override
public CancelReason getCancelReason() {
return cancelReason;
}
@Override
public TargetType getTargetType() {
return type;
}
protected void setCancelReason(CancelReason reason) {
cancelReason = reason;
}
}

View File

@ -12,6 +12,7 @@ import net.citizensnpcs.api.ai.event.NavigationBeginEvent;
import net.citizensnpcs.api.ai.event.NavigationCancelEvent;
import net.citizensnpcs.api.ai.event.NavigationCompleteEvent;
import net.citizensnpcs.api.ai.event.NavigationReplaceEvent;
import net.citizensnpcs.api.astar.pathfinder.MinecraftBlockExaminer;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.npc.CitizensNPC;
@ -26,7 +27,7 @@ public class CitizensNavigator implements Navigator {
private final NavigatorParameters defaultParams = new NavigatorParameters()
.baseSpeed(UNINITIALISED_SPEED).range(Setting.DEFAULT_PATHFINDING_RANGE.asFloat())
.stationaryTicks(Setting.DEFAULT_STATIONARY_TICKS.asInt())
.stuckAction(TeleportStuckAction.INSTANCE);
.stuckAction(TeleportStuckAction.INSTANCE).examiner(new MinecraftBlockExaminer());
private PathStrategy executing;
private int lastX, lastY, lastZ;
private NavigatorParameters localParams = defaultParams;
@ -136,7 +137,11 @@ public class CitizensNavigator implements Navigator {
return;
}
localParams = defaultParams.clone();
PathStrategy newStrategy = new MCNavigationStrategy(npc, target, localParams);
PathStrategy newStrategy;
if (Setting.USE_NEW_PATHFINDER.asBoolean())
newStrategy = new AStarNavigationStrategy(npc, target, localParams);
else
newStrategy = new MCNavigationStrategy(npc, target, localParams);
switchStrategyTo(newStrategy);
}

View File

@ -9,13 +9,13 @@ import net.minecraft.server.Navigation;
import org.bukkit.Location;
public class MCNavigationStrategy implements PathStrategy {
private CancelReason cancelReason;
public class MCNavigationStrategy extends AbstractPathStrategy {
private final Navigation navigation;
private final NavigatorParameters parameters;
private final Location target;
MCNavigationStrategy(final CitizensNPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.target = dest;
this.parameters = params;
if (npc.getHandle() instanceof EntityPlayer) {
@ -28,17 +28,7 @@ public class MCNavigationStrategy implements PathStrategy {
navigation.a(parameters.avoidWater());
navigation.a(dest.getX(), dest.getY(), dest.getZ(), parameters.speed());
if (navigation.f())
cancelReason = CancelReason.STUCK;
}
@Override
public void clearCancelReason() {
cancelReason = null;
}
@Override
public CancelReason getCancelReason() {
return cancelReason;
setCancelReason(CancelReason.STUCK);
}
@Override
@ -58,7 +48,7 @@ public class MCNavigationStrategy implements PathStrategy {
@Override
public boolean update() {
if (cancelReason != null)
if (getCancelReason() != null)
return true;
navigation.a(parameters.avoidWater());
navigation.a(parameters.speed());

View File

@ -45,7 +45,6 @@ public class CitizensMagmaCubeNPC extends CitizensMobNPC {
}
}
@Override
public void bl() {
super.bl();

View File

@ -131,8 +131,9 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder {
NMS.updateSenses(this);
Navigation navigation = getNavigation();
if (!navigation.f()) {
navigation.e();
if (npc.getNavigator().isNavigating()) {
if (!navigation.f())
navigation.e();
moveOnCurrentHeading();
} else if (motX != 0 || motZ != 0 || motY != 0)
e(0, 0); // is this necessary? it does controllable but sometimes

View File

@ -14,7 +14,7 @@ public class CurrentLocation extends Trait {
}
public Location getLocation() {
if (loc.getWorld() == null)
if (loc != null && loc.getWorld() == null)
return null;
return loc;
}

View File

@ -14,9 +14,9 @@ public class Gravity extends Trait implements Toggleable {
}
public void gravitate(boolean gravitate) {
enabled = gravitate;
enabled = gravitate;
}
@Override
public void run() {
if (!npc.isSpawned() || !enabled)

View File

@ -118,7 +118,7 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable
enabled = !enabled;
return enabled;
}
@Override
public String toString() {
return "LookClose{" + enabled + "}";

View File

@ -107,6 +107,7 @@ public class LinearWaypointProvider implements WaypointProvider {
private void clearWaypoints() {
editingSlot = 0;
waypoints.clear();
onWaypointsModified();
destroyWaypointMarkers();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_WAYPOINTS_CLEARED);
}
@ -185,7 +186,8 @@ public class LinearWaypointProvider implements WaypointProvider {
public void onPlayerChat(AsyncPlayerChatEvent event) {
if (!event.getPlayer().equals(player))
return;
if (event.getMessage().equalsIgnoreCase("triggers")) {
String message = event.getMessage();
if (message.equalsIgnoreCase("triggers")) {
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
@ -193,8 +195,7 @@ public class LinearWaypointProvider implements WaypointProvider {
}
});
return;
}
if (event.getMessage().equalsIgnoreCase("clear")) {
} else if (message.equalsIgnoreCase("clear")) {
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
@ -202,17 +203,17 @@ public class LinearWaypointProvider implements WaypointProvider {
}
});
return;
}
if (!event.getMessage().equalsIgnoreCase("toggle path"))
} else if (message.equalsIgnoreCase("toggle path")) {
event.setCancelled(true);
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
// we need to spawn entities on the main thread.
togglePath();
}
});
return;
event.setCancelled(true);
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
// we need to spawn entities, get back on the main thread.
togglePath();
}
});
}
}
@EventHandler(ignoreCancelled = true)
@ -256,7 +257,7 @@ public class LinearWaypointProvider implements WaypointProvider {
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_REMOVED_WAYPOINT, waypoints.size(),
editingSlot + 1);
}
currentGoal.onProviderChanged();
onWaypointsModified();
}
@EventHandler(ignoreCancelled = true)
@ -291,6 +292,11 @@ public class LinearWaypointProvider implements WaypointProvider {
formatLoc(waypoints.get(editingSlot).getLocation()));
}
private void onWaypointsModified() {
if (currentGoal != null)
currentGoal.onProviderChanged();
}
private void removeWaypointMarker(Waypoint waypoint) {
Entity entity = waypointMarkers.remove(waypoint);
if (entity != null)
@ -380,7 +386,7 @@ public class LinearWaypointProvider implements WaypointProvider {
public void setPaused(boolean pause) {
if (pause && currentDestination != null)
selector.finish();
this.paused = pause;
paused = pause;
}
@Override

View File

@ -9,49 +9,49 @@ import org.bukkit.Location;
*/
public class Anchor {
private final Location location;
private final String name;
private final Location location;
private final String name;
public Anchor(String name, Location location) {
this.location = location;
this.name = name;
}
@Override
public boolean equals(Object object) {
if (object == null) return false;
if (object == this) return true;
if (object.getClass() != getClass())
return false;
Anchor op = (Anchor) object;
return new EqualsBuilder().
append(name, op.getName()).
isEquals();
}
public Location getLocation() {
return location;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
return new HashCodeBuilder(13, 21).
append(name).
toHashCode();
public Anchor(String name, Location location) {
this.location = location;
this.name = name;
}
public String stringValue() {
return name + ";" + location.getWorld().getName() + ";" + location.getX() + ";" + location.getY() + ";" + location.getZ();
}
@Override
public String toString() {
return "Name: " + name + " World: " + location.getWorld().getName() + " Location: " + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ();
}
@Override
public boolean equals(Object object) {
if (object == null)
return false;
if (object == this)
return true;
if (object.getClass() != getClass())
return false;
Anchor op = (Anchor) object;
return new EqualsBuilder().append(name, op.getName()).isEquals();
}
public Location getLocation() {
return location;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
return new HashCodeBuilder(13, 21).append(name).toHashCode();
}
public String stringValue() {
return name + ";" + location.getWorld().getName() + ";" + location.getX() + ";" + location.getY()
+ ";" + location.getZ();
}
@Override
public String toString() {
return "Name: " + name + " World: " + location.getWorld().getName() + " Location: "
+ location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ();
}
}

View File

@ -33,6 +33,7 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.material.Stairs;
import org.bukkit.material.Step;
import org.bukkit.util.Vector;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@ -120,6 +121,15 @@ public class NMS {
}
}
public static double distance(EntityLiving handle, Vector vector) {
return Math.sqrt(distanceSquared(handle, vector));
}
public static double distanceSquared(EntityLiving handle, Vector vector) {
return Math.pow(handle.locX - vector.getX(), 2) + Math.pow(handle.locY - vector.getY(), 2)
+ Math.pow(handle.locZ - vector.getZ(), 2);
}
private static Constructor<? extends Entity> getCustomEntityConstructor(Class<? extends Entity> clazz,
EntityType type) throws SecurityException, NoSuchMethodException {
Constructor<? extends Entity> constructor = ENTITY_CONSTRUCTOR_CACHE.get(clazz);

View File

@ -8,55 +8,53 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
*/
public class Pose {
private final String name;
private final float pitch;
private final float yaw;
private final String name;
private final float pitch;
private final float yaw;
public Pose(String name, float pitch, float yaw) {
this.yaw = yaw;
this.pitch = pitch;
this.name = name;
}
@Override
public boolean equals(Object object) {
if (object == null) return false;
if (object == this) return true;
if (object.getClass() != getClass())
return false;
Pose op = (Pose) object;
return new EqualsBuilder().
append(name, op.getName()).
isEquals();
}
public String getName() {
return name;
}
public float getPitch() {
return pitch;
}
public float getYaw() {
return yaw;
}
@Override
public int hashCode() {
return new HashCodeBuilder(13, 21).
append(name).
toHashCode();
public Pose(String name, float pitch, float yaw) {
this.yaw = yaw;
this.pitch = pitch;
this.name = name;
}
public String stringValue() {
return name + ";" + pitch + ";" + yaw;
}
@Override
public String toString() {
return "Name: " + name + " Pitch: " + pitch + " Yaw: " + yaw;
}
@Override
public boolean equals(Object object) {
if (object == null)
return false;
if (object == this)
return true;
if (object.getClass() != getClass())
return false;
Pose op = (Pose) object;
return new EqualsBuilder().append(name, op.getName()).isEquals();
}
public String getName() {
return name;
}
public float getPitch() {
return pitch;
}
public float getYaw() {
return yaw;
}
@Override
public int hashCode() {
return new HashCodeBuilder(13, 21).append(name).toHashCode();
}
public String stringValue() {
return name + ";" + pitch + ";" + yaw;
}
@Override
public String toString() {
return "Name: " + name + " Pitch: " + pitch + " Yaw: " + yaw;
}
}

View File

@ -84,6 +84,7 @@ public class StringHelper {
String highlight = Setting.HIGHLIGHT_COLOUR.asString();
return highlight + "=====[ " + string.toString() + highlight + " ]=====";
}
static {
String colors = "";
for (ChatColor color : ChatColor.values())