mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-08-20 12:54:03 +02:00
Add a setting to use the new pathfinder (temporary, will be removed)
This commit is contained in:
parent
ae199ad98a
commit
153026b8bd
|
@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -45,7 +45,6 @@ public class CitizensMagmaCubeNPC extends CitizensMobNPC {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void bl() {
|
||||
super.bl();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -118,7 +118,7 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable
|
|||
enabled = !enabled;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LookClose{" + enabled + "}";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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())
|
||||
|
|
Loading…
Reference in New Issue
Block a user