mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2025-02-17 04:41:31 +01:00
Properly remove wander waypoint marker
This commit is contained in:
parent
a0e3b23bc3
commit
41f4c6e1b4
@ -32,289 +32,291 @@ import net.citizensnpcs.util.Messages;
|
|||||||
import net.citizensnpcs.util.Util;
|
import net.citizensnpcs.util.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wandering waypoint provider that wanders between either a box centered at the current location or inside a region
|
* A wandering waypoint provider that wanders between either a box centered at
|
||||||
* defined by a list of boxes.
|
* the current location or inside a region defined by a list of boxes.
|
||||||
*/
|
*/
|
||||||
public class WanderWaypointProvider
|
public class WanderWaypointProvider
|
||||||
implements WaypointProvider, Supplier<PhTreeSolid<Boolean>>, Function<NPC, Location> {
|
implements WaypointProvider, Supplier<PhTreeSolid<Boolean>>, Function<NPC, Location> {
|
||||||
private WanderGoal currentGoal;
|
private WanderGoal currentGoal;
|
||||||
@Persist
|
@Persist
|
||||||
public int delay = -1;
|
public int delay = -1;
|
||||||
private NPC npc;
|
private NPC npc;
|
||||||
private volatile boolean paused;
|
private volatile boolean paused;
|
||||||
@Persist
|
@Persist
|
||||||
private final List<Location> regionCentres = Lists.newArrayList();
|
private final List<Location> regionCentres = Lists.newArrayList();
|
||||||
private PhTreeSolid<Boolean> tree = PhTreeSolid.create(3);
|
private PhTreeSolid<Boolean> tree = PhTreeSolid.create(3);
|
||||||
@Persist
|
@Persist
|
||||||
public int xrange = DEFAULT_XRANGE;
|
public int xrange = DEFAULT_XRANGE;
|
||||||
@Persist
|
@Persist
|
||||||
public int yrange = DEFAULT_YRANGE;
|
public int yrange = DEFAULT_YRANGE;
|
||||||
|
|
||||||
public void addRegionCentre(Location centre) {
|
public void addRegionCentre(Location centre) {
|
||||||
regionCentres.add(centre);
|
regionCentres.add(centre);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRegionCentres(Collection<Location> centre) {
|
public void addRegionCentres(Collection<Location> centre) {
|
||||||
regionCentres.addAll(centre);
|
regionCentres.addAll(centre);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Location apply(NPC npc) {
|
public Location apply(NPC npc) {
|
||||||
Location closestCentre = null;
|
Location closestCentre = null;
|
||||||
double minDist = Double.MAX_VALUE;
|
double minDist = Double.MAX_VALUE;
|
||||||
for (Location centre : regionCentres) {
|
for (Location centre : regionCentres) {
|
||||||
double d = centre.distanceSquared(npc.getStoredLocation());
|
double d = centre.distanceSquared(npc.getStoredLocation());
|
||||||
if (d < minDist) {
|
if (d < minDist) {
|
||||||
minDist = d;
|
minDist = d;
|
||||||
closestCentre = centre;
|
closestCentre = centre;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (closestCentre != null) {
|
if (closestCentre != null) {
|
||||||
// TODO: should find closest edge block that is valid
|
// TODO: should find closest edge block that is valid
|
||||||
return MinecraftBlockExaminer.findValidLocation(closestCentre, xrange, yrange);
|
return MinecraftBlockExaminer.findValidLocation(closestCentre, xrange, yrange);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WaypointEditor createEditor(final CommandSender sender, CommandContext args) {
|
public WaypointEditor createEditor(final CommandSender sender, CommandContext args) {
|
||||||
return new WaypointEditor() {
|
return new WaypointEditor() {
|
||||||
boolean editingRegions = false;
|
boolean editingRegions = false;
|
||||||
EntityMarkers<Location> markers = new EntityMarkers<Location>();
|
EntityMarkers<Location> markers = new EntityMarkers<Location>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin() {
|
public void begin() {
|
||||||
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_BEGIN);
|
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_BEGIN);
|
||||||
if (currentGoal != null) {
|
if (currentGoal != null) {
|
||||||
currentGoal.pause();
|
currentGoal.pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void end() {
|
public void end() {
|
||||||
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_END);
|
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_END);
|
||||||
editingRegions = false;
|
editingRegions = false;
|
||||||
if (currentGoal != null) {
|
if (currentGoal != null) {
|
||||||
currentGoal.unpause();
|
currentGoal.unpause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatLoc(Location location) {
|
private String formatLoc(Location location) {
|
||||||
return String.format("[[%d]], [[%d]], [[%d]]", location.getBlockX(), location.getBlockY(),
|
return String.format("[[%d]], [[%d]], [[%d]]", location.getBlockX(), location.getBlockY(),
|
||||||
location.getBlockZ());
|
location.getBlockZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||||
if (!event.getPlayer().equals(sender))
|
if (!event.getPlayer().equals(sender))
|
||||||
return;
|
return;
|
||||||
String message = event.getMessage().toLowerCase();
|
String message = event.getMessage().toLowerCase();
|
||||||
if (message.startsWith("xrange") || message.startsWith("yrange")) {
|
if (message.startsWith("xrange") || message.startsWith("yrange")) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
int range = 0;
|
int range = 0;
|
||||||
try {
|
try {
|
||||||
range = Integer.parseInt(message.split(" ", 2)[1]);
|
range = Integer.parseInt(message.split(" ", 2)[1]);
|
||||||
if (range <= 0) {
|
if (range <= 0) {
|
||||||
range = 0;
|
range = 0;
|
||||||
}
|
}
|
||||||
if (message.startsWith("xrange")) {
|
if (message.startsWith("xrange")) {
|
||||||
xrange = range;
|
xrange = range;
|
||||||
} else {
|
} else {
|
||||||
yrange = range;
|
yrange = range;
|
||||||
}
|
}
|
||||||
if (currentGoal != null) {
|
if (currentGoal != null) {
|
||||||
currentGoal.setXYRange(xrange, yrange);
|
currentGoal.setXYRange(xrange, yrange);
|
||||||
}
|
}
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_RANGE_SET, xrange, yrange);
|
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_RANGE_SET, xrange, yrange);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (message.startsWith("regions")) {
|
} else if (message.startsWith("regions")) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
editingRegions = !editingRegions;
|
editingRegions = !editingRegions;
|
||||||
if (editingRegions) {
|
if (editingRegions) {
|
||||||
for (Location regionCentre : regionCentres) {
|
for (Location regionCentre : regionCentres) {
|
||||||
Entity entity = markers.createMarker(regionCentre, regionCentre);
|
Entity entity = markers.createMarker(regionCentre, regionCentre);
|
||||||
entity.setMetadata("wandermarker",
|
entity.setMetadata("wandermarker",
|
||||||
new FixedMetadataValue(CitizensAPI.getPlugin(), regionCentre));
|
new FixedMetadataValue(CitizensAPI.getPlugin(), regionCentre));
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_REGION_EDITING_START);
|
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_REGION_EDITING_START);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
markers.destroyMarkers();
|
markers.destroyMarkers();
|
||||||
}
|
}
|
||||||
} else if (message.startsWith("delay")) {
|
} else if (message.startsWith("delay")) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
try {
|
try {
|
||||||
delay = Integer.parseInt(message.split(" ")[1]);
|
delay = Integer.parseInt(message.split(" ")[1]);
|
||||||
if (currentGoal != null) {
|
if (currentGoal != null) {
|
||||||
currentGoal.setDelay(delay);
|
currentGoal.setDelay(delay);
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_DELAY_SET, delay);
|
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_DELAY_SET, delay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (
|
} catch (
|
||||||
|
|
||||||
Exception e) {
|
Exception e) {
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Messaging.sendErrorTr(sender, Messages.WANDER_WAYPOINTS_INVALID_DELAY);
|
Messaging.sendErrorTr(sender, Messages.WANDER_WAYPOINTS_INVALID_DELAY);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
if (!event.getPlayer().equals(sender) || event.getAction() == Action.PHYSICAL || !npc.isSpawned()
|
if (!event.getPlayer().equals(sender) || event.getAction() == Action.PHYSICAL || !npc.isSpawned()
|
||||||
|| event.getPlayer().getWorld() != npc.getEntity().getWorld() || Util.isOffHand(event))
|
|| !editingRegions || event.getPlayer().getWorld() != npc.getEntity().getWorld()
|
||||||
return;
|
|| Util.isOffHand(event))
|
||||||
if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR) {
|
return;
|
||||||
if (event.getClickedBlock() == null)
|
if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR) {
|
||||||
return;
|
if (event.getClickedBlock() == null)
|
||||||
event.setCancelled(true);
|
return;
|
||||||
Location at = event.getClickedBlock().getLocation().add(0, 1, 0);
|
event.setCancelled(true);
|
||||||
if (!regionCentres.contains(at)) {
|
Location at = event.getClickedBlock().getLocation().add(0, 1, 0);
|
||||||
regionCentres.add(at);
|
if (!regionCentres.contains(at)) {
|
||||||
Entity entity = markers.createMarker(at, at);
|
regionCentres.add(at);
|
||||||
entity.setMetadata("wandermarker", new FixedMetadataValue(CitizensAPI.getPlugin(), at));
|
Entity entity = markers.createMarker(at, at);
|
||||||
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_ADDED_REGION, formatLoc(at),
|
entity.setMetadata("wandermarker", new FixedMetadataValue(CitizensAPI.getPlugin(), at));
|
||||||
regionCentres.size());
|
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_ADDED_REGION, formatLoc(at),
|
||||||
recalculateTree();
|
regionCentres.size());
|
||||||
}
|
recalculateTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||||
if (!sender.equals(event.getPlayer()) || !editingRegions || Util.isOffHand(event))
|
if (!sender.equals(event.getPlayer()) || !editingRegions || Util.isOffHand(event))
|
||||||
return;
|
return;
|
||||||
if (!event.getRightClicked().hasMetadata("wandermarker"))
|
if (!event.getRightClicked().hasMetadata("wandermarker"))
|
||||||
return;
|
return;
|
||||||
regionCentres.remove(event.getRightClicked().getMetadata("wandermarker").get(0).value());
|
regionCentres.remove(event.getRightClicked().getMetadata("wandermarker").get(0).value());
|
||||||
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_REMOVED_REGION,
|
markers.removeMarker((Location) event.getRightClicked().getMetadata("wandermarker").get(0).value());
|
||||||
formatLoc((Location) event.getRightClicked().getMetadata("wandermarker").get(0).value()),
|
Messaging.sendTr(sender, Messages.WANDER_WAYPOINTS_REMOVED_REGION,
|
||||||
regionCentres.size());
|
formatLoc((Location) event.getRightClicked().getMetadata("wandermarker").get(0).value()),
|
||||||
recalculateTree();
|
regionCentres.size());
|
||||||
}
|
recalculateTree();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PhTreeSolid<Boolean> get() {
|
public PhTreeSolid<Boolean> get() {
|
||||||
return regionCentres.isEmpty() ? null : tree;
|
return regionCentres.isEmpty() ? null : tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Location> getRegionCentres() {
|
public List<Location> getRegionCentres() {
|
||||||
return new RecalculateList();
|
return new RecalculateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPaused() {
|
public boolean isPaused() {
|
||||||
return paused;
|
return paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(DataKey key) {
|
public void load(DataKey key) {
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRemove() {
|
public void onRemove() {
|
||||||
npc.getDefaultGoalController().removeGoal(currentGoal);
|
npc.getDefaultGoalController().removeGoal(currentGoal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpawn(NPC npc) {
|
public void onSpawn(NPC npc) {
|
||||||
this.npc = npc;
|
this.npc = npc;
|
||||||
if (currentGoal == null) {
|
if (currentGoal == null) {
|
||||||
currentGoal = WanderGoal.createWithNPCAndRangeAndTreeAndFallback(npc, xrange, yrange,
|
currentGoal = WanderGoal.createWithNPCAndRangeAndTreeAndFallback(npc, xrange, yrange,
|
||||||
WanderWaypointProvider.this, WanderWaypointProvider.this);
|
WanderWaypointProvider.this, WanderWaypointProvider.this);
|
||||||
currentGoal.setDelay(delay);
|
currentGoal.setDelay(delay);
|
||||||
}
|
}
|
||||||
npc.getDefaultGoalController().addGoal(currentGoal, 1);
|
npc.getDefaultGoalController().addGoal(currentGoal, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recalculateTree() {
|
private void recalculateTree() {
|
||||||
tree = PhTreeSolid.create(3);
|
tree = PhTreeSolid.create(3);
|
||||||
for (Location loc : regionCentres) {
|
for (Location loc : regionCentres) {
|
||||||
long[] lower = { loc.getBlockX() - xrange, loc.getBlockY() - yrange, loc.getBlockZ() - xrange };
|
long[] lower = { loc.getBlockX() - xrange, loc.getBlockY() - yrange, loc.getBlockZ() - xrange };
|
||||||
long[] upper = { loc.getBlockX() + xrange, loc.getBlockY() + yrange, loc.getBlockZ() + xrange };
|
long[] upper = { loc.getBlockX() + xrange, loc.getBlockY() + yrange, loc.getBlockZ() + xrange };
|
||||||
tree.put(lower, upper, true);
|
tree.put(lower, upper, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeRegionCentre(Location centre) {
|
public void removeRegionCentre(Location centre) {
|
||||||
regionCentres.remove(centre);
|
regionCentres.remove(centre);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeRegionCentres(Collection<Location> centre) {
|
public void removeRegionCentres(Collection<Location> centre) {
|
||||||
regionCentres.removeAll(centre);
|
regionCentres.removeAll(centre);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(DataKey key) {
|
public void save(DataKey key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPaused(boolean paused) {
|
public void setPaused(boolean paused) {
|
||||||
this.paused = paused;
|
this.paused = paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RecalculateList extends ForwardingList<Location> {
|
private class RecalculateList extends ForwardingList<Location> {
|
||||||
@Override
|
@Override
|
||||||
public void add(int idx, Location loc) {
|
public void add(int idx, Location loc) {
|
||||||
super.add(idx, loc);
|
super.add(idx, loc);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(Location loc) {
|
public boolean add(Location loc) {
|
||||||
boolean val = super.add(loc);
|
boolean val = super.add(loc);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Location> delegate() {
|
protected List<Location> delegate() {
|
||||||
return regionCentres;
|
return regionCentres;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Location remove(int idx) {
|
public Location remove(int idx) {
|
||||||
Location val = super.remove(idx);
|
Location val = super.remove(idx);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Location set(int idx, Location idx2) {
|
public Location set(int idx, Location idx2) {
|
||||||
Location val = super.set(idx, idx2);
|
Location val = super.set(idx, idx2);
|
||||||
recalculateTree();
|
recalculateTree();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int DEFAULT_XRANGE = 3;
|
private static final int DEFAULT_XRANGE = 3;
|
||||||
private static final int DEFAULT_YRANGE = 25;
|
private static final int DEFAULT_YRANGE = 25;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user