Work on new waypoint provider

This commit is contained in:
fullwall 2013-09-26 23:55:12 +08:00
parent d75f380084
commit 42172100ab
8 changed files with 343 additions and 47 deletions

View File

@ -176,8 +176,9 @@ public class EventListen implements Listener {
@EventHandler(ignoreCancelled = true)
public void onEntityDeath(EntityDeathEvent event) {
final NPC npc = npcRegistry.getNPC(event.getEntity());
if (npc == null)
if (npc == null) {
return;
}
Bukkit.getPluginManager().callEvent(new NPCDeathEvent(npc, event));
final Location location = npc.getBukkitEntity().getLocation();
npc.despawn(DespawnReason.DEATH);

View File

@ -45,8 +45,9 @@ public class WaypointCommands {
if (args.argsLength() == 1) {
if (args.hasFlag('d')) {
waypoints.describeProviders(sender);
} else
} else {
Messaging.sendTr(sender, Messages.CURRENT_WAYPOINT_PROVIDER, waypoints.getCurrentProviderName());
}
return;
}
boolean success = waypoints.setWaypointProvider(args.getString(1));

View File

@ -0,0 +1,271 @@
package net.citizensnpcs.trait.waypoint;
import java.util.Iterator;
import java.util.List;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.Goal;
import net.citizensnpcs.api.ai.GoalSelector;
import net.citizensnpcs.api.ai.event.CancelReason;
import net.citizensnpcs.api.ai.event.NavigatorCallback;
import net.citizensnpcs.api.astar.AStarGoal;
import net.citizensnpcs.api.astar.AStarMachine;
import net.citizensnpcs.api.astar.AStarNode;
import net.citizensnpcs.api.astar.Agent;
import net.citizensnpcs.api.astar.Plan;
import net.citizensnpcs.api.command.CommandContext;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Util;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.metadata.FixedMetadataValue;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
public class JeebissFindingWaypointProvider implements WaypointProvider {
@Persist("availablewaypoints")
private final List<Waypoint> available = Lists.newArrayList();
private JeebissFindingWaypointProviderGoal currentGoal;
@Persist("helperwaypoints")
private final List<Waypoint> helpers = Lists.newArrayList();
private NPC npc;
private boolean paused;
@Override
public WaypointEditor createEditor(final Player player, CommandContext args) {
return new WaypointEditor() {
WaypointMarkers markers = new WaypointMarkers(player.getWorld());
@Override
public void begin() {
showPath();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_BEGIN);
}
private void createWaypointMarkerWithData(Waypoint element) {
Entity entity = markers.createWaypointMarker(element);
if (entity == null)
return;
entity.setMetadata("citizens.waypointhashcode",
new FixedMetadataValue(CitizensAPI.getPlugin(), element.hashCode()));
}
@Override
public void end() {
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_END);
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event) {
if (!event.getPlayer().equals(player) || event.getAction() == Action.PHYSICAL
|| event.getClickedBlock() == null)
return;
if (event.getPlayer().getWorld() != npc.getBukkitEntity().getWorld())
return;
event.setCancelled(true);
Location at = event.getClickedBlock().getLocation();
Waypoint element = new Waypoint(at);
if (player.isSneaking()) {
available.add(element);
} else {
helpers.add(element);
}
createWaypointMarkerWithData(element);
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
if (!event.getRightClicked().hasMetadata("citizens.waypointhashcode"))
return;
int hashcode = event.getRightClicked().getMetadata("citizens.waypointhashcode").get(0).asInt();
Iterator<Waypoint> itr = Iterables.concat(available, helpers).iterator();
while (itr.hasNext()) {
if (itr.next().hashCode() == hashcode) {
itr.remove();
break;
}
}
}
private void showPath() {
for (Waypoint element : Iterables.concat(available, helpers)) {
createWaypointMarkerWithData(element);
}
}
};
}
@Override
public boolean isPaused() {
return paused;
}
@Override
public void load(DataKey key) {
}
@Override
public void onSpawn(NPC npc) {
this.npc = npc;
if (currentGoal == null) {
currentGoal = new JeebissFindingWaypointProviderGoal();
CitizensAPI.registerEvents(currentGoal);
npc.getDefaultGoalController().addGoal(currentGoal, 1);
}
}
@Override
public void save(DataKey key) {
}
@Override
public void setPaused(boolean paused) {
this.paused = paused;
}
private class JeebissFindingWaypointProviderGoal implements Goal {
JeebissPlan plan;
@Override
public void reset() {
plan = null;
}
@Override
public void run(GoalSelector selector) {
if (plan.isComplete()) {
selector.finish();
return;
}
Waypoint current = plan.getCurrentWaypoint();
npc.getNavigator().setTarget(current.getLocation());
npc.getNavigator().getLocalParameters().addSingleUseCallback(new NavigatorCallback() {
@Override
public void onCompletion(CancelReason cancelReason) {
plan.update(npc);
}
});
}
@Override
public boolean shouldExecute(GoalSelector selector) {
if (paused || available.size() == 0 || !npc.isSpawned() || npc.getNavigator().isNavigating())
return false;
Waypoint target = available.get(Util.getFastRandom().nextInt(available.size()));
ASTAR.runFully(new JeebissGoal(target), null);
return true;
}
}
private static class JeebissGoal implements AStarGoal<JeebissNode> {
private final Waypoint dest;
public JeebissGoal(Waypoint dest) {
this.dest = dest;
}
@Override
public float g(JeebissNode from, JeebissNode to) {
return (float) from.distance(to.waypoint);
}
@Override
public float getInitialCost(JeebissNode node) {
return h(node);
}
@Override
public float h(JeebissNode from) {
return (float) from.distance(dest);
}
@Override
public boolean isFinished(JeebissNode node) {
return node.waypoint.equals(dest);
}
}
private static class JeebissNode extends AStarNode {
private Waypoint waypoint;
@Override
public Plan buildPlan() {
return new JeebissPlan(this.<JeebissNode> getParents());
}
public double distance(Waypoint dest) {
return waypoint.distance(dest);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
JeebissNode other = (JeebissNode) obj;
if (waypoint == null) {
if (other.waypoint != null) {
return false;
}
} else if (!waypoint.equals(other.waypoint)) {
return false;
}
return true;
}
@Override
public Iterable<AStarNode> getNeighbours() {
return null;
}
@Override
public int hashCode() {
return 31 + ((waypoint == null) ? 0 : waypoint.hashCode());
}
}
private static class JeebissPlan implements Plan {
private int index = 0;
private final Waypoint[] path;
public JeebissPlan(Iterable<JeebissNode> path) {
this.path = Iterables.toArray(Iterables.transform(path, new Function<JeebissNode, Waypoint>() {
@Override
public Waypoint apply(JeebissNode to) {
return to.waypoint;
}
}), Waypoint.class);
}
public Waypoint getCurrentWaypoint() {
return path[index];
}
@Override
public boolean isComplete() {
return index >= path.length;
}
@Override
public void update(Agent agent) {
index++;
}
}
private static final AStarMachine<JeebissNode, JeebissPlan> ASTAR = AStarMachine.createWithDefaultStorage();
}

View File

@ -2,7 +2,6 @@ package net.citizensnpcs.trait.waypoint;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@ -23,16 +22,12 @@ import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.trait.waypoint.triggers.TriggerEditPrompt;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.Util;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.conversations.Conversation;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
@ -40,10 +35,8 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.metadata.FixedMetadataValue;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class LinearWaypointProvider implements WaypointProvider {
private LinearWaypointGoal currentGoal;
@ -121,12 +114,13 @@ public class LinearWaypointProvider implements WaypointProvider {
Conversation conversation;
boolean editing = true;
int editingSlot = waypoints.size() - 1;
WaypointMarkers markers;
private final Player player;
private boolean showPath;
private final Map<Waypoint, Entity> waypointMarkers = Maps.newHashMap();
private LinearWaypointEditor(Player player) {
this.player = player;
this.markers = new WaypointMarkers(player.getWorld());
}
@Override
@ -138,31 +132,16 @@ public class LinearWaypointProvider implements WaypointProvider {
editingSlot = 0;
waypoints.clear();
onWaypointsModified();
destroyWaypointMarkers();
markers.destroyWaypointMarkers();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_WAYPOINTS_CLEARED);
}
private void createWaypointMarker(int index, Waypoint waypoint) {
Entity entity = spawnMarker(player.getWorld(), waypoint.getLocation().clone().add(0, 1, 0));
if (entity == null)
return;
entity.setMetadata("waypointindex", new FixedMetadataValue(CitizensAPI.getPlugin(), index));
waypointMarkers.put(waypoint, entity);
}
private void createWaypointMarkers() {
for (int i = 0; i < waypoints.size(); i++) {
createWaypointMarker(i, waypoints.get(i));
markers.createWaypointMarker(waypoints.get(i));
}
}
private void destroyWaypointMarkers() {
for (Entity entity : waypointMarkers.values()) {
entity.remove();
}
waypointMarkers.clear();
}
@Override
public void end() {
if (!editing)
@ -173,7 +152,7 @@ public class LinearWaypointProvider implements WaypointProvider {
editing = false;
if (!showPath)
return;
destroyWaypointMarkers();
markers.destroyWaypointMarkers();
}
private String formatLoc(Location location) {
@ -275,8 +254,9 @@ public class LinearWaypointProvider implements WaypointProvider {
Waypoint element = new Waypoint(at);
normaliseEditingSlot();
waypoints.add(editingSlot, element);
if (showPath)
createWaypointMarker(editingSlot, element);
if (showPath) {
markers.createWaypointMarker(element);
}
editingSlot = Math.min(editingSlot + 1, waypoints.size());
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_ADDED_WAYPOINT, formatLoc(at),
editingSlot + 1, waypoints.size());
@ -284,8 +264,9 @@ public class LinearWaypointProvider implements WaypointProvider {
event.setCancelled(true);
normaliseEditingSlot();
Waypoint waypoint = waypoints.remove(editingSlot);
if (showPath)
removeWaypointMarker(waypoint);
if (showPath) {
markers.removeWaypointMarker(waypoint);
}
editingSlot = Math.max(0, editingSlot - 1);
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_REMOVED_WAYPOINT, waypoints.size(),
editingSlot + 1);
@ -331,23 +312,13 @@ public class LinearWaypointProvider implements WaypointProvider {
}
}
private void removeWaypointMarker(Waypoint waypoint) {
Entity entity = waypointMarkers.remove(waypoint);
if (entity != null)
entity.remove();
}
private Entity spawnMarker(World world, Location at) {
return NMS.spawnCustomEntity(world, at, EntityEnderCrystalMarker.class, EntityType.ENDER_CRYSTAL);
}
private void togglePath() {
showPath = !showPath;
if (showPath) {
createWaypointMarkers();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_SHOWING_MARKERS);
} else {
destroyWaypointMarkers();
markers.destroyWaypointMarkers();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_NOT_SHOWING_MARKERS);
}
}

View File

@ -24,13 +24,11 @@ public class WanderWaypointProvider implements WaypointProvider {
@Override
public void begin() {
// TODO Auto-generated method stub
}
@Override
public void end() {
// TODO Auto-generated method stub
}
};
}

View File

@ -35,6 +35,10 @@ public class Waypoint {
triggers.add(trigger);
}
public double distance(Waypoint dest) {
return location.distance(dest.location);
}
public Location getLocation() {
return location;
}

View File

@ -0,0 +1,46 @@
package net.citizensnpcs.trait.waypoint;
import java.util.Map;
import net.citizensnpcs.util.NMS;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import com.google.common.collect.Maps;
public class WaypointMarkers {
private final Map<Waypoint, Entity> waypointMarkers = Maps.newHashMap();
private final World world;
public WaypointMarkers(World world) {
this.world = world;
}
public Entity createWaypointMarker(Waypoint waypoint) {
Entity entity = spawnMarker(world, waypoint.getLocation().clone().add(0, 1, 0));
if (entity == null)
return null;
waypointMarkers.put(waypoint, entity);
return entity;
}
public void destroyWaypointMarkers() {
for (Entity entity : waypointMarkers.values()) {
entity.remove();
}
waypointMarkers.clear();
}
public void removeWaypointMarker(Waypoint waypoint) {
Entity entity = waypointMarkers.remove(waypoint);
if (entity != null)
entity.remove();
}
public Entity spawnMarker(World world, Location at) {
return NMS.spawnCustomEntity(world, at, EntityEnderCrystalMarker.class, EntityType.ENDER_CRYSTAL);
}
}

View File

@ -5,6 +5,7 @@ import java.util.Map.Entry;
import net.citizensnpcs.api.command.CommandContext;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.PersistenceLoader;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.Messaging;
@ -74,6 +75,7 @@ public class Waypoints extends Trait {
}
if (provider == null)
return;
PersistenceLoader.load(provider, key.getRelative(providerName));
provider.load(key.getRelative(providerName));
}
@ -87,6 +89,7 @@ public class Waypoints extends Trait {
public void save(DataKey key) {
if (provider == null)
return;
PersistenceLoader.save(provider, key.getRelative(providerName));
provider.save(key.getRelative(providerName));
key.setString("provider", providerName);
}
@ -113,8 +116,6 @@ public class Waypoints extends Trait {
return true;
}
private static final Map<String, Class<? extends WaypointProvider>> providers = Maps.newHashMap();
/**
* Registers a {@link WaypointProvider}, which can be subsequently used by
* NPCs.
@ -128,8 +129,11 @@ public class Waypoints extends Trait {
providers.put(name, clazz);
}
private static final Map<String, Class<? extends WaypointProvider>> providers = Maps.newHashMap();
static {
providers.put("linear", LinearWaypointProvider.class);
providers.put("wander", WanderWaypointProvider.class);
providers.put("jeebissfinding", JeebissFindingWaypointProvider.class);
}
}