Back ported SafeSpotTeleport from the ASkyBlock effort

This commit is contained in:
Tastybento 2018-02-17 14:54:58 -08:00
parent 9715811303
commit ca13f23918

View File

@ -26,15 +26,16 @@ import us.tastybento.bskyblock.util.Pair;
*/ */
public class SafeSpotTeleport { public class SafeSpotTeleport {
private static final int MAX_CHUNKS = 50; private static final int MAX_CHUNKS = 200;
private static final long SPEED = 5; private static final long SPEED = 1;
private static final int MAX_RADIUS = 200;
private boolean checking = true; private boolean checking = true;
private BukkitTask task; private BukkitTask task;
// Parameters // Parameters
private final Entity entity; private final Entity entity;
private final Location location; private final Location location;
private final boolean portal; private boolean portal;
private final int homeNumber; private final int homeNumber;
// Locations // Locations
@ -46,14 +47,14 @@ public class SafeSpotTeleport {
/** /**
* Teleports and entity to a safe spot on island * Teleports and entity to a safe spot on island
* @param plugin * @param plugin - BSkyBlock plugin object
* @param entity * @param entity
* @param location * @param location
* @param failureMessage - already translated failure message * @param failureMessage - already translated failure message
* @param portal * @param portal
* @param homeNumber * @param homeNumber
*/ */
protected SafeSpotTeleport(BSkyBlock plugin, Entity entity, Location location, String failureMessage, boolean portal, protected SafeSpotTeleport(BSkyBlock plugin, final Entity entity, final Location location, final String failureMessage, boolean portal,
int homeNumber) { int homeNumber) {
this.plugin = plugin; this.plugin = plugin;
this.entity = entity; this.entity = entity;
@ -73,24 +74,29 @@ public class SafeSpotTeleport {
checking = true; checking = true;
// Start a recurring task until done or cancelled // Start a recurring task until done or cancelled
task = plugin.getServer().getScheduler().runTaskTimer(plugin, () -> { task = plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() {
List<ChunkSnapshot> chunkSnapshot = new ArrayList<>();
if (checking) { @Override
Iterator<Pair<Integer, Integer>> it = chunksToScan.iterator(); public void run() {
if (!it.hasNext()) { List<ChunkSnapshot> chunkSnapshot = new ArrayList<>();
// Nothing left if (checking) {
tidyUp(entity, failureMessage); Iterator<Pair<Integer, Integer>> it = chunksToScan.iterator();
return; if (!it.hasNext()) {
// Nothing left
tidyUp(entity, failureMessage);
return;
}
// Add chunk snapshots to the list
while (it.hasNext() && chunkSnapshot.size() < MAX_CHUNKS) {
Pair<Integer, Integer> pair = it.next();
chunkSnapshot.add(location.getWorld().getChunkAt(pair.x, pair.z).getChunkSnapshot());
it.remove();
}
// Move to next step
checking = false;
checkChunks(chunkSnapshot);
} }
// Add chunk snapshots to the list
while (it.hasNext() && chunkSnapshot.size() < MAX_CHUNKS) {
Pair<Integer, Integer> pair = it.next();
chunkSnapshot.add(location.getWorld().getChunkAt(pair.x, pair.z).getChunkSnapshot());
it.remove();
}
// Move to next step
checking = false;
checkChunks(chunkSnapshot);
} }
}, 0L, SPEED); }, 0L, SPEED);
} }
@ -102,12 +108,13 @@ public class SafeSpotTeleport {
if (portal && bestSpot != null) { if (portal && bestSpot != null) {
// No portals found, teleport to the best spot we found // No portals found, teleport to the best spot we found
teleportEntity(bestSpot); teleportEntity(bestSpot);
return; } else if (entity instanceof Player && !failureMessage.isEmpty()) {
} // Failed, no safe spot
// Failed - no safe spot
if (entity instanceof Player && !failureMessage.isEmpty()) {
entity.sendMessage(failureMessage); entity.sendMessage(failureMessage);
} }
if (entity instanceof Player && ((Player)entity).getGameMode().equals(GameMode.SPECTATOR)) {
((Player)entity).setGameMode(GameMode.SURVIVAL);
}
} }
/** /**
@ -121,13 +128,15 @@ public class SafeSpotTeleport {
// Get island if available // Get island if available
Optional<Island> island = plugin.getIslands().getIslandAt(location); Optional<Island> island = plugin.getIslands().getIslandAt(location);
int maxRadius = island.map(Island::getProtectionRange).orElse(plugin.getSettings().getIslandProtectionRange()); int maxRadius = island.map(Island::getProtectionRange).orElse(plugin.getSettings().getIslandProtectionRange());
maxRadius = maxRadius > MAX_RADIUS ? MAX_RADIUS : maxRadius;
int x = location.getBlockX(); int x = location.getBlockX();
int z = location.getBlockZ(); int z = location.getBlockZ();
// Create ever increasing squares around the target location // Create ever increasing squares around the target location
int radius = 0; int radius = 0;
do { do {
for (int i = x - radius; i <= x + radius; i++) { for (int i = x - radius; i <= x + radius; i+=16) {
for (int j = z - radius; j <= z + radius; j++) { for (int j = z - radius; j <= z + radius; j+=16) {
addChunk(result, island, new Pair<>(i,j), new Pair<>(i/16, j/16)); addChunk(result, island, new Pair<>(i,j), new Pair<>(i/16, j/16));
} }
} }
@ -151,17 +160,15 @@ public class SafeSpotTeleport {
}); });
} }
} }
} }
/** /**
* Loops through the chunks and if a safe spot is found, fires off the teleportation * Loops through the chunks and if a safe spot is found, fires off the teleportation
* @param chunkSnapshot * @param chunkSnapshot
*/ */
private void checkChunks(List<ChunkSnapshot> chunkSnapshot) { private void checkChunks(final List<ChunkSnapshot> chunkSnapshot) {
// Run async task to scan chunks // Run async task to scan chunks
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
for (ChunkSnapshot chunk: chunkSnapshot) { for (ChunkSnapshot chunk: chunkSnapshot) {
if (scanChunk(chunk)) { if (scanChunk(chunk)) {
task.cancel(); task.cancel();
@ -198,7 +205,7 @@ public class SafeSpotTeleport {
/** /**
* Teleports entity to the safe spot * Teleports entity to the safe spot
*/ */
private void teleportEntity(Location loc) { private void teleportEntity(final Location loc) {
task.cancel(); task.cancel();
// Return to main thread and teleport the player // Return to main thread and teleport the player
plugin.getServer().getScheduler().runTask(plugin, () -> { plugin.getServer().getScheduler().runTask(plugin, () -> {
@ -269,24 +276,20 @@ public class SafeSpotTeleport {
break; break;
case PORTAL: case PORTAL:
if (portal) { if (portal) {
Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D); // A portal has been found, switch to non-portal mode now
// Teleport as soon as we find a portal portal = false;
teleportEntity(newSpot.toLocation(world));
return true;
} }
break; break;
default: default:
return safe(world, chunk, x, y, z); return safe(chunk, x, y, z, world);
} }
} }
} }
return false; return false;
} }
private boolean safe(World world, ChunkSnapshot chunk, int x, int y, int z) { private boolean safe(ChunkSnapshot chunk, int x, int y, int z, World world) {
// Safe
Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D); Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D);
// Check for portal
if (portal) { if (portal) {
if (bestSpot == null) { if (bestSpot == null) {
// Stash the best spot // Stash the best spot
@ -294,11 +297,8 @@ public class SafeSpotTeleport {
} }
return false; return false;
} else { } else {
// Regular search - teleport as soon as we find something
teleportEntity(newSpot.toLocation(world)); teleportEntity(newSpot.toLocation(world));
return true; return true;
} }
} }
} }