From 59f2c8b62ed9e711327c1a76ccc1e5bbcb987b1c Mon Sep 17 00:00:00 2001 From: "main()" Date: Thu, 26 Jan 2012 18:55:09 +0100 Subject: [PATCH] (Re)designed SafeTTeleporter for extension. --- .../onarandombox/MultiverseCore/MVWorld.java | 5 +- .../MultiverseCore/MultiverseCore.java | 30 +- .../onarandombox/MultiverseCore/api/Core.java | 22 +- .../MultiverseCore/api/SafeTTeleporter.java | 71 ++++ .../MultiverseCore/commands/SpawnCommand.java | 2 +- .../commands/TeleportCommand.java | 4 +- .../MultiverseCore/event/MVTeleportEvent.java | 1 + .../listeners/MVPlayerListener.java | 3 +- .../MultiverseCore/utils/MVTravelAgent.java | 3 +- .../MultiverseCore/utils/SafeTTeleporter.java | 3 + .../utils/SimpleSafeTTeleporter.java | 337 ++++++++++++++++++ .../MultiverseCore/utils/WorldManager.java | 3 +- 12 files changed, 469 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/SimpleSafeTTeleporter.java diff --git a/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java b/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java index 00c6cf65..463e93c7 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java @@ -15,7 +15,7 @@ import com.onarandombox.MultiverseCore.configuration.MVConfigProperty; import com.onarandombox.MultiverseCore.enums.EnglishChatColor; import com.onarandombox.MultiverseCore.event.MVWorldPropertyChangeEvent; import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException; -import com.onarandombox.MultiverseCore.utils.SafeTTeleporter; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import org.bukkit.ChatColor; import org.bukkit.Difficulty; import org.bukkit.GameMode; @@ -32,7 +32,6 @@ import org.bukkit.permissions.PermissionDefault; import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; @@ -985,7 +984,7 @@ public class MVWorld implements MultiverseWorld { // Set the worldspawn to our configspawn w.setSpawnLocation(configLocation.getBlockX(), configLocation.getBlockY(), configLocation.getBlockZ()); - SafeTTeleporter teleporter = this.plugin.getTeleporter(); + SafeTTeleporter teleporter = this.plugin.getSafeTTeleporter(); BlockSafety bs = this.plugin.getBlockSafety(); // Verify that location was safe if (!bs.playerCanSpawnHereSafely(configLocation)) { diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java index 33497df4..b60e5120 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java @@ -16,6 +16,7 @@ import com.onarandombox.MultiverseCore.api.MVPlugin; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MultiverseMessaging; import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.commands.*; import com.onarandombox.MultiverseCore.destination.AnchorDestination; import com.onarandombox.MultiverseCore.destination.BedDestination; @@ -167,6 +168,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { private MultiverseMessaging messaging; private BlockSafety blockSafety; private LocationManipulation locationManipulation; + private SafeTTeleporter safeTTeleporter; private File serverFolder = new File(System.getProperty("user.dir")); @@ -180,6 +182,8 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { this.blockSafety = new SimpleBlockSafety(this); // Setup our LocationManipulation this.locationManipulation = new SimpleLocationManipulation(); + // Setup our SafeTTeleporter + this.safeTTeleporter = new SimpleSafeTTeleporter(this); } /** @@ -447,10 +451,13 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { /** * {@inheritDoc} + * + * @deprecated This is deprecated. */ @Override - public SafeTTeleporter getTeleporter() { - return new SafeTTeleporter(this); + @Deprecated + public com.onarandombox.MultiverseCore.utils.SafeTTeleporter getTeleporter() { + return new com.onarandombox.MultiverseCore.utils.SafeTTeleporter(this); } /** @@ -639,7 +646,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { */ public void teleportPlayer(CommandSender teleporter, Player p, Location l) { // This command is the override, and MUST NOT TELEPORT SAFELY - this.getTeleporter().safelyTeleport(teleporter, p, l, false); + this.getSafeTTeleporter().safelyTeleport(teleporter, p, l, false); } /** @@ -781,7 +788,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { } if (this.worldManager.deleteWorld(name, false)) { this.worldManager.loadWorlds(false); - SafeTTeleporter teleporter = this.getTeleporter(); + SafeTTeleporter teleporter = this.getSafeTTeleporter(); Location newSpawn = this.getServer().getWorld(name).getSpawnLocation(); // Send all players that were in the old world, BACK to it! for (Player p : ps) { @@ -832,4 +839,19 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { this.locationManipulation = locationManipulation; } + /** + * {@inheritDoc} + */ + @Override + public SafeTTeleporter getSafeTTeleporter() { + return safeTTeleporter; + } + + /** + * {@inheritDoc} + */ + @Override + public void setSafeTTeleporter(SafeTTeleporter safeTTeleporter) { + this.safeTTeleporter = safeTTeleporter; + } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java index cd957f25..4e1007f9 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java @@ -66,8 +66,11 @@ public interface Core { * safe teleports. * * @return A non-null {@link SafeTTeleporter}. + * + * @deprecated Use {@link #getSafeTTeleporter()} instead. */ - SafeTTeleporter getTeleporter(); + @Deprecated + com.onarandombox.MultiverseCore.utils.SafeTTeleporter getTeleporter(); /** * Multiverse uses an advanced permissions setup, this object @@ -195,4 +198,21 @@ public interface Core { * @see SimpleLocationManipulation */ void setLocationManipulation(LocationManipulation locationManipulation); + + /** + * Gets the {@link SafeTTeleporter} this {@link Core} is using. + * @return The {@link SafeTTeleporter} this {@link Core} is using. + * @see SafeTTeleporter + * @see SimpleSafeTTeleporter + */ + SafeTTeleporter getSafeTTeleporter(); + + /** + * Sets the {@link SafeTTeleporter} this {@link Core} is using. + * @param safeTTeleporter The new {@link SafeTTeleporter}. + * @see SafeTTeleporter + * @see SimpleSafeTTeleporter + */ + void setSafeTTeleporter(SafeTTeleporter safeTTeleporter); + } diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java b/src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java new file mode 100644 index 00000000..a38140e1 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java @@ -0,0 +1,71 @@ +package com.onarandombox.MultiverseCore.api; + +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; + +import com.onarandombox.MultiverseCore.enums.TeleportResult; + +/** + * Used to safely teleport people. + */ +public interface SafeTTeleporter { + + /** + * Gets the next safe location around the given location. + * @param l A {@link Location}. + * @return A safe {@link Location}. + */ + Location getSafeLocation(Location l); + + /** + * Gets the next safe location around the given location. + * @param l A {@link Location}. + * @param tolerance The tolerance. + * @param radius The radius. + * @return A safe {@link Location}. + */ + Location getSafeLocation(Location l, int tolerance, int radius); + + /** + * Safely teleport the entity to the MVDestination. This will perform checks to see if the place is safe, and if + * it's not, will adjust the final destination accordingly. + * + * @param teleporter Person who performed the teleport command. + * @param teleportee Entity to teleport + * @param d Destination to teleport them to + * @return true for success, false for failure + */ + TeleportResult safelyTeleport(CommandSender teleporter, Entity teleportee, MVDestination d); + + /** + * Safely teleport the entity to the Location. This may perform checks to + * see if the place is safe, and if + * it's not, will adjust the final destination accordingly. + * + * @param teleporter Person who issued the teleport command. + * @param teleportee Entity to teleport. + * @param location Location to teleport them to. + * @param safely Should the destination be checked for safety before teleport? + * @return true for success, false for failure. + */ + TeleportResult safelyTeleport(CommandSender teleporter, Entity teleportee, Location location, + boolean safely); + + /** + * Returns a safe location for the entity to spawn at. + * + * @param e The entity to spawn + * @param d The MVDestination to take the entity to. + * @return A new location to spawn the entity at. + */ + Location getSafeLocation(Entity e, MVDestination d); + + /** + * Finds a portal-block next to the specified {@link Location}. + * @param l The {@link Location} + * @return The next portal-block's {@link Location}. + */ + Location findPortalBlockNextTo(Location l); + +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/SpawnCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/SpawnCommand.java index 80620b78..5925d887 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/SpawnCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/SpawnCommand.java @@ -85,6 +85,6 @@ public class SpawnCommand extends MultiverseCommand { } else { spawnLocation = player.getWorld().getSpawnLocation(); } - this.plugin.getTeleporter().safelyTeleport(player, player, spawnLocation, false); + this.plugin.getSafeTTeleporter().safelyTeleport(player, player, spawnLocation, false); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java index 667dacc6..8232c5bb 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java @@ -14,7 +14,7 @@ import com.onarandombox.MultiverseCore.destination.InvalidDestination; import com.onarandombox.MultiverseCore.destination.WorldDestination; import com.onarandombox.MultiverseCore.enums.TeleportResult; import com.onarandombox.MultiverseCore.event.MVTeleportEvent; -import com.onarandombox.MultiverseCore.utils.SafeTTeleporter; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; @@ -42,7 +42,7 @@ public class TeleportCommand extends MultiverseCommand { this.setArgRange(1, 2); this.addKey("mvtp"); this.addKey("mv tp"); - this.playerTeleporter = new SafeTTeleporter(this.plugin); + this.playerTeleporter = this.plugin.getSafeTTeleporter(); this.setPermission(menu); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java index ea2ff031..3728c7d0 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java @@ -8,6 +8,7 @@ package com.onarandombox.MultiverseCore.event; import com.onarandombox.MultiverseCore.api.MVDestination; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import org.bukkit.Location; import org.bukkit.command.CommandSender; diff --git a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java index ad62c4d4..e0e8d004 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java +++ b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java @@ -12,7 +12,6 @@ import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MultiverseWorld; import com.onarandombox.MultiverseCore.event.MVRespawnEvent; import com.onarandombox.MultiverseCore.utils.PermissionTools; -import com.onarandombox.MultiverseCore.utils.SafeTTeleporter; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; @@ -225,7 +224,7 @@ public class MVPlayerListener implements Listener { // REMEMBER! getTo MAY be NULL HERE!!! // If the player was actually outside of the portal, adjust the from location if (event.getFrom().getWorld().getBlockAt(event.getFrom()).getType() != Material.PORTAL) { - Location newloc = SafeTTeleporter.findPortalBlockNextTo(event.getFrom()); + Location newloc = this.plugin.getSafeTTeleporter().findPortalBlockNextTo(event.getFrom()); // TODO: Fix this. Currently, we only check for PORTAL blocks. I'll have to figure out what // TODO: we want to do here. if (newloc != null) { diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVTravelAgent.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVTravelAgent.java index 2fd2fe22..0f3ada97 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVTravelAgent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVTravelAgent.java @@ -9,6 +9,7 @@ package com.onarandombox.MultiverseCore.utils; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVDestination; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.destination.CannonDestination; import org.bukkit.Location; import org.bukkit.TravelAgent; @@ -106,7 +107,7 @@ public class MVTravelAgent implements TravelAgent { if (this.destination instanceof CannonDestination) { this.core.log(Level.FINE, "Using Stock TP method. This cannon will have 0 velocity"); } - SafeTTeleporter teleporter = new SafeTTeleporter(this.core); + SafeTTeleporter teleporter = this.core.getSafeTTeleporter(); Location newLoc = this.destination.getLocation(this.player); if (this.destination.useSafeTeleporter()) { newLoc = teleporter.getSafeLocation(this.player, this.destination); diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java b/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java index 11916b60..130abbaa 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java @@ -28,7 +28,10 @@ import java.util.logging.Level; /** * The {@link SafeTTeleporter}. + * + * @deprecated Use instead: {@link com.onarandombox.MultiverseCore.api.SafeTTeleporter} and {@link SimpleSafeTTeleporter}. */ +@Deprecated public class SafeTTeleporter { private MultiverseCore plugin; diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleSafeTTeleporter.java b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleSafeTTeleporter.java new file mode 100644 index 00000000..fa216e64 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleSafeTTeleporter.java @@ -0,0 +1,337 @@ +/****************************************************************************** + * Multiverse 2 Copyright (c) the Multiverse Team 2011. * + * Multiverse 2 is licensed under the BSD License. * + * For more information please check the README.md file included * + * with this project. * + ******************************************************************************/ + +package com.onarandombox.MultiverseCore.utils; + +import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.BlockSafety; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; +import com.onarandombox.MultiverseCore.api.MVDestination; +import com.onarandombox.MultiverseCore.destination.InvalidDestination; +import com.onarandombox.MultiverseCore.enums.TeleportResult; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Minecart; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.util.Vector; + +import java.util.logging.Level; + +/** + * The default-implementation of {@link SafeTTeleporter}. + */ +public class SimpleSafeTTeleporter implements SafeTTeleporter { + + private MultiverseCore plugin; + private BlockSafety bs; + + public SimpleSafeTTeleporter(MultiverseCore plugin) { + this.plugin = plugin; + this.bs = plugin.getBlockSafety(); + } + + private static final int DEFAULT_TOLERANCE = 6; + private static final int DEFAULT_RADIUS = 9; + + /** + * {@inheritDoc} + */ + @Override + public Location getSafeLocation(Location l) { + return this.getSafeLocation(l, DEFAULT_TOLERANCE, DEFAULT_RADIUS); + } + + /** + * {@inheritDoc} + */ + @Override + public Location getSafeLocation(Location l, int tolerance, int radius) { + // Check around the player first in a configurable radius: + // TODO: Make this configurable + Location safe = checkAboveAndBelowLocation(l, tolerance, radius); + if (safe != null) { + safe.setX(safe.getBlockX() + .5); // SUPPRESS CHECKSTYLE: MagicNumberCheck + safe.setZ(safe.getBlockZ() + .5); // SUPPRESS CHECKSTYLE: MagicNumberCheck + this.plugin.log(Level.FINE, "Hey! I found one: " + plugin.getLocationManipulation().strCoordsRaw(safe)); + } else { + this.plugin.log(Level.FINE, "Uh oh! No safe place found!"); + } + return safe; + } + + private Location checkAboveAndBelowLocation(Location l, int tolerance, int radius) { + // Tolerance must be an even number: + if (tolerance % 2 != 0) { + tolerance += 1; + } + // We want half of it, so we can go up and down + tolerance /= 2; + this.plugin.log(Level.FINER, "Given Location of: " + plugin.getLocationManipulation().strCoordsRaw(l)); + this.plugin.log(Level.FINER, "Checking +-" + tolerance + " with a radius of " + radius); + + // For now this will just do a straight up block. + Location locToCheck = l.clone(); + // Check the main level + Location safe = this.checkAroundLocation(locToCheck, radius); + if (safe != null) { + return safe; + } + // We've already checked zero right above this. + int currentLevel = 1; + while (currentLevel <= tolerance) { + // Check above + locToCheck = l.clone(); + locToCheck.add(0, currentLevel, 0); + safe = this.checkAroundLocation(locToCheck, radius); + if (safe != null) { + return safe; + } + + // Check below + locToCheck = l.clone(); + locToCheck.subtract(0, currentLevel, 0); + safe = this.checkAroundLocation(locToCheck, radius); + if (safe != null) { + return safe; + } + currentLevel++; + } + + return null; + } + + /* + * For my crappy algorithm, radius MUST be odd. + */ + private Location checkAroundLocation(Location l, int diameter) { + if (diameter % 2 == 0) { + diameter += 1; + } + Location checkLoc = l.clone(); + + // Start at 3, the min diameter around a block + int loopcounter = 3; + while (loopcounter <= diameter) { + boolean foundSafeArea = checkAroundSpecificDiameter(checkLoc, loopcounter); + // If a safe area was found: + if (foundSafeArea) { + // Return the checkLoc, it is the safe location. + return checkLoc; + } + // Otherwise, let's reset our location + checkLoc = l.clone(); + // And increment the radius + loopcounter += 2; + } + return null; + } + + private boolean checkAroundSpecificDiameter(Location checkLoc, int circle) { + // Adjust the circle to get how many blocks to step out. + // A radius of 3 makes the block step 1 + // A radius of 5 makes the block step 2 + // A radius of 7 makes the block step 3 + // ... + int adjustedCircle = ((circle - 1) / 2); + checkLoc.add(adjustedCircle, 0, 0); + if (this.bs.playerCanSpawnHereSafely(checkLoc)) { + return true; + } + // Now we go to the right that adjustedCircle many + for (int i = 0; i < adjustedCircle; i++) { + checkLoc.add(0, 0, 1); + if (this.bs.playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + + // Then down adjustedCircle *2 + for (int i = 0; i < adjustedCircle * 2; i++) { + checkLoc.add(-1, 0, 0); + if (this.bs.playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + + // Then left adjustedCircle *2 + for (int i = 0; i < adjustedCircle * 2; i++) { + checkLoc.add(0, 0, -1); + if (this.bs.playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + + // Then up Then left adjustedCircle *2 + for (int i = 0; i < adjustedCircle * 2; i++) { + checkLoc.add(1, 0, 0); + if (this.bs.playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + + // Then finish up by doing adjustedCircle - 1 + for (int i = 0; i < adjustedCircle - 1; i++) { + checkLoc.add(0, 0, 1); + if (this.bs.playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public TeleportResult safelyTeleport(CommandSender teleporter, Entity teleportee, MVDestination d) { + if (d instanceof InvalidDestination) { + this.plugin.log(Level.FINER, "Entity tried to teleport to an invalid destination"); + return TeleportResult.FAIL_INVALID; + } + Player teleporteePlayer = null; + if (teleportee instanceof Player) { + teleporteePlayer = ((Player) teleportee); + } else if (teleportee.getPassenger() instanceof Player) { + teleporteePlayer = ((Player) teleportee.getPassenger()); + } + + if (teleporteePlayer == null) { + return TeleportResult.FAIL_INVALID; + } + MultiverseCore.addPlayerToTeleportQueue(teleporter.getName(), teleporteePlayer.getName()); + + Location safeLoc = d.getLocation(teleportee); + if (d.useSafeTeleporter()) { + safeLoc = this.getSafeLocation(teleportee, d); + } + + if (safeLoc != null) { + if (teleportee.teleport(safeLoc)) { + if (!d.getVelocity().equals(new Vector(0, 0, 0))) { + teleportee.setVelocity(d.getVelocity()); + } + return TeleportResult.SUCCESS; + } + return TeleportResult.FAIL_OTHER; + } + return TeleportResult.FAIL_UNSAFE; + } + + /** + * {@inheritDoc} + */ + @Override + public TeleportResult safelyTeleport(CommandSender teleporter, Entity teleportee, Location location, boolean safely) { + if (safely) { + location = this.getSafeLocation(location); + } + + if (location != null) { + if (teleportee.teleport(location)) { + return TeleportResult.SUCCESS; + } + return TeleportResult.FAIL_OTHER; + } + return TeleportResult.FAIL_UNSAFE; + } + + /** + * {@inheritDoc} + */ + @Override + public Location getSafeLocation(Entity e, MVDestination d) { + Location l = d.getLocation(e); + if (this.bs.playerCanSpawnHereSafely(l)) { + plugin.log(Level.FINE, "The first location you gave me was safe."); + return l; + } + if (e instanceof Minecart) { + Minecart m = (Minecart) e; + if (!this.bs.canSpawnCartSafely(m)) { + return null; + } + } else if (e instanceof Vehicle) { + Vehicle v = (Vehicle) e; + if (!this.bs.canSpawnVehicleSafely(v)) { + return null; + } + } + Location safeLocation = this.getSafeLocation(l); + if (safeLocation != null) { + // Add offset to account for a vehicle on dry land! + if (e instanceof Minecart && !this.bs.isEntitiyOnTrack(safeLocation)) { + safeLocation.setY(safeLocation.getBlockY() + .5); + this.plugin.log(Level.FINER, "Player was inside a minecart. Offsetting Y location."); + } + this.plugin.log(Level.FINE, "Had to look for a bit, but I found a safe place for ya!"); + return safeLocation; + } + if (e instanceof Player) { + Player p = (Player) e; + this.plugin.getMessaging().sendMessage(p, "No safe locations found!", false); + this.plugin.log(Level.FINER, "No safe location found for " + p.getName()); + } else if (e.getPassenger() instanceof Player) { + Player p = (Player) e.getPassenger(); + this.plugin.getMessaging().sendMessage(p, "No safe locations found!", false); + this.plugin.log(Level.FINER, "No safe location found for " + p.getName()); + } + this.plugin.log(Level.FINE, "Sorry champ, you're basically trying to teleport into a minefield. I should just kill you now."); + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public Location findPortalBlockNextTo(Location l) { + Block b = l.getWorld().getBlockAt(l); + Location foundLocation = null; + if (b.getType() == Material.PORTAL) { + return l; + } + if (b.getRelative(BlockFace.NORTH).getType() == Material.PORTAL) { + foundLocation = getCloserBlock(l, b.getRelative(BlockFace.NORTH).getLocation(), foundLocation); + } + if (b.getRelative(BlockFace.SOUTH).getType() == Material.PORTAL) { + foundLocation = getCloserBlock(l, b.getRelative(BlockFace.SOUTH).getLocation(), foundLocation); + } + if (b.getRelative(BlockFace.EAST).getType() == Material.PORTAL) { + foundLocation = getCloserBlock(l, b.getRelative(BlockFace.EAST).getLocation(), foundLocation); + } + if (b.getRelative(BlockFace.WEST).getType() == Material.PORTAL) { + foundLocation = getCloserBlock(l, b.getRelative(BlockFace.WEST).getLocation(), foundLocation); + } + return foundLocation; + } + + private static Location getCloserBlock(Location source, Location blockA, Location blockB) { + // If B wasn't given, return a. + if (blockB == null) { + return blockA; + } + // Center our calculations + blockA.add(.5, 0, .5); + blockB.add(.5, 0, .5); + + // Retrieve the distance to the normalized blocks + double testA = source.distance(blockA); + double testB = source.distance(blockB); + + // Compare and return + if (testA <= testB) { + return blockA; + } + return blockB; + } + +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java index b8bc41fb..cbfc74f9 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java @@ -11,6 +11,7 @@ import com.onarandombox.MultiverseCore.MVWorld; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.commands.EnvironmentCommand; import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent; import org.bukkit.World; @@ -371,7 +372,7 @@ public class WorldManager implements MVWorldManager { if (w != null) { World safeWorld = this.plugin.getServer().getWorlds().get(0); List ps = w.getPlayers(); - SafeTTeleporter teleporter = this.plugin.getTeleporter(); + SafeTTeleporter teleporter = this.plugin.getSafeTTeleporter(); for (Player p : ps) { // We're removing players forcefully from a world, they'd BETTER spawn safely. teleporter.safelyTeleport(null, p, safeWorld.getSpawnLocation(), true);