diff --git a/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java b/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java index a7806c34..c6292ffd 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java @@ -7,6 +7,7 @@ package com.onarandombox.MultiverseCore; +import com.onarandombox.MultiverseCore.api.BlockSafety; import com.onarandombox.MultiverseCore.api.MultiverseWorld; import com.onarandombox.MultiverseCore.configuration.ConfigPropertyFactory; import com.onarandombox.MultiverseCore.configuration.MVActiveConfigProperty; @@ -14,9 +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.BlockSafety; -import com.onarandombox.MultiverseCore.utils.LocationManipulation; -import com.onarandombox.MultiverseCore.utils.SafeTTeleporter; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import org.bukkit.ChatColor; import org.bukkit.Difficulty; import org.bukkit.GameMode; @@ -33,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; @@ -433,7 +431,7 @@ public class MVWorld implements MultiverseWorld { } else { this.world.setSpawnFlags(true, this.world.getAllowAnimals()); } - this.plugin.getMVWorldManager().getWorldPurger().purgeWorld(null, this); + this.plugin.getMVWorldManager().getTheWorldPurger().purgeWorld(this); } /** @@ -986,8 +984,8 @@ public class MVWorld implements MultiverseWorld { // Set the worldspawn to our configspawn w.setSpawnLocation(configLocation.getBlockX(), configLocation.getBlockY(), configLocation.getBlockZ()); - SafeTTeleporter teleporter = this.plugin.getTeleporter(); - BlockSafety bs = new BlockSafety(); + SafeTTeleporter teleporter = this.plugin.getSafeTTeleporter(); + BlockSafety bs = this.plugin.getBlockSafety(); // Verify that location was safe if (!bs.playerCanSpawnHereSafely(configLocation)) { if (!this.getAdjustSpawn()) { @@ -999,7 +997,7 @@ public class MVWorld implements MultiverseWorld { } // If it's not, find a better one. this.plugin.log(Level.WARNING, "Spawn location from world.dat file was unsafe. Adjusting..."); - this.plugin.log(Level.WARNING, "Original Location: " + LocationManipulation.strCoordsRaw(spawnLocation)); + this.plugin.log(Level.WARNING, "Original Location: " + plugin.getLocationManipulation().strCoordsRaw(spawnLocation)); Location newSpawn = teleporter.getSafeLocation(spawnLocation, SPAWN_LOCATION_SEARCH_TOLERANCE, SPAWN_LOCATION_SEARCH_RADIUS); // I think we could also do this, as I think this is what Notch does. @@ -1008,7 +1006,8 @@ public class MVWorld implements MultiverseWorld { if (newSpawn != null) { this.setSpawnLocation(newSpawn); configLocation = this.getSpawnLocation(); - this.plugin.log(Level.INFO, "New Spawn for '" + this.getName() + "' is Located at: " + LocationManipulation.locationToString(configLocation)); + this.plugin.log(Level.INFO, "New Spawn for '" + this.getName() + + "' is Located at: " + plugin.getLocationManipulation().locationToString(configLocation)); } else { // If it's a standard end world, let's check in a better place: Location newerSpawn; @@ -1017,7 +1016,7 @@ public class MVWorld implements MultiverseWorld { this.setSpawnLocation(newerSpawn); configLocation = this.getSpawnLocation(); this.plugin.log(Level.INFO, "New Spawn for '" + this.getName() - + "' is Located at: " + LocationManipulation.locationToString(configLocation)); + + "' is Located at: " + plugin.getLocationManipulation().locationToString(configLocation)); } else { this.plugin.log(Level.SEVERE, "New safe spawn NOT found!!!"); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java index 4ad99513..b60e5120 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java @@ -9,10 +9,14 @@ package com.onarandombox.MultiverseCore; import com.fernferret.allpay.AllPay; import com.fernferret.allpay.GenericBank; +import com.onarandombox.MultiverseCore.api.BlockSafety; import com.onarandombox.MultiverseCore.api.Core; +import com.onarandombox.MultiverseCore.api.LocationManipulation; 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; @@ -26,14 +30,7 @@ import com.onarandombox.MultiverseCore.listeners.MVEntityListener; import com.onarandombox.MultiverseCore.listeners.MVPlayerListener; import com.onarandombox.MultiverseCore.listeners.MVPluginListener; import com.onarandombox.MultiverseCore.listeners.MVWeatherListener; -import com.onarandombox.MultiverseCore.utils.AnchorManager; -import com.onarandombox.MultiverseCore.utils.DebugLog; -import com.onarandombox.MultiverseCore.utils.MVMessaging; -import com.onarandombox.MultiverseCore.utils.MVPermissions; -import com.onarandombox.MultiverseCore.utils.MVPlayerSession; -import com.onarandombox.MultiverseCore.utils.SafeTTeleporter; -import com.onarandombox.MultiverseCore.utils.SpoutInterface; -import com.onarandombox.MultiverseCore.utils.WorldManager; +import com.onarandombox.MultiverseCore.utils.*; import com.pneumaticraft.commandhandler.CommandHandler; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -168,7 +165,10 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { private SpoutInterface spoutInterface = null; private static final double ALLPAY_VERSION = 5; private static final double CH_VERSION = 4; - private MVMessaging messaging; + private MultiverseMessaging messaging; + private BlockSafety blockSafety; + private LocationManipulation locationManipulation; + private SafeTTeleporter safeTTeleporter; private File serverFolder = new File(System.getProperty("user.dir")); @@ -178,6 +178,12 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { getDataFolder().mkdirs(); // Setup our Debug Log debugLog = new DebugLog("Multiverse-Core", getDataFolder() + File.separator + "debug.log"); + // Setup our BlockSafety + this.blockSafety = new SimpleBlockSafety(this); + // Setup our LocationManipulation + this.locationManipulation = new SimpleLocationManipulation(); + // Setup our SafeTTeleporter + this.safeTTeleporter = new SimpleSafeTTeleporter(this); } /** @@ -375,7 +381,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { * {@inheritDoc} */ @Override - public MVMessaging getMessaging() { + public MultiverseMessaging getMessaging() { return this.messaging; } @@ -445,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); } /** @@ -637,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); } /** @@ -779,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) { @@ -798,4 +807,51 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { return this.anchorManager; } + /** + * {@inheritDoc} + */ + @Override + public BlockSafety getBlockSafety() { + return blockSafety; + } + + /** + * {@inheritDoc} + */ + @Override + public void setBlockSafety(BlockSafety bs) { + this.blockSafety = bs; + } + + /** + * {@inheritDoc} + */ + @Override + public LocationManipulation getLocationManipulation() { + return locationManipulation; + } + + /** + * {@inheritDoc} + */ + @Override + public void setLocationManipulation(LocationManipulation locationManipulation) { + 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/BlockSafety.java b/src/main/java/com/onarandombox/MultiverseCore/api/BlockSafety.java new file mode 100644 index 00000000..db25a17e --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/api/BlockSafety.java @@ -0,0 +1,72 @@ +package com.onarandombox.MultiverseCore.api; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Minecart; +import org.bukkit.entity.Vehicle; + +/** + * Used to get block/location-related information. + */ +public interface BlockSafety { + /** + * This function checks whether the block at the given coordinates are above air or not. + * @param l The {@link Location} of the block. + * @return True if the block at that {@link Location} is above air. + */ + boolean isBlockAboveAir(Location l); + + /** + * Checks if a player can spawn safely at the given coordinates. + * @param world The {@link World}. + * @param x The x-coordinate. + * @param y The y-coordinate. + * @param z The z-coordinate. + * @return True if a player can spawn safely at the given coordinates. + */ + boolean playerCanSpawnHereSafely(World world, double x, double y, double z); + + /** + * This function checks whether the block at the coordinates given is safe or not by checking for Lava/Fire/Air + * etc. This also ensures there is enough space for a player to spawn! + * + * @param l The {@link Location} + * @return Whether the player can spawn safely at the given {@link Location} + */ + boolean playerCanSpawnHereSafely(Location l); + + /** + * Gets the location of the top block at the specified {@link Location}. + * @param l Any {@link Location}. + * @return The {@link Location} of the top-block. + */ + Location getTopBlock(Location l); + + /** + * Gets the location of the top block at the specified {@link Location}. + * @param l Any {@link Location}. + * @return The {@link Location} of the top-block. + */ + Location getBottomBlock(Location l); + + /** + * Checks if an entity would be on track at the specified {@link Location}. + * @param l The {@link Location}. + * @return True if an entity would be on tracks at the specified {@link Location}. + */ + boolean isEntitiyOnTrack(Location l); + + /** + * Checks if the specified {@link Minecart} can spawn safely. + * @param cart The {@link Minecart}. + * @return True if the minecart can spawn safely. + */ + boolean canSpawnCartSafely(Minecart cart); + + /** + * Checks if the specified {@link Vehicle} can spawn safely. + * @param vehicle The {@link Vehicle}. + * @return True if the vehicle can spawn safely. + */ + boolean canSpawnVehicleSafely(Vehicle vehicle); +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java index 7eec0ba2..4e1007f9 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java @@ -46,9 +46,9 @@ public interface Core { * Gets the Multiverse message system. This allows you to send messages * to users at specified intervals. * - * @return The loaded {@link MVMessaging}. + * @return The loaded {@link MultiverseMessaging}. */ - MVMessaging getMessaging(); + MultiverseMessaging getMessaging(); /** * Gets the {@link MVPlayerSession} for the given player. @@ -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 @@ -163,4 +166,53 @@ public interface Core { * @return The readable authors-{@link String} */ String getAuthors(); + + /** + * Gets the {@link BlockSafety} this {@link Core} is using. + * @return The {@link BlockSafety} this {@link Core} is using. + * @see BlockSafety + * @see SimpleBlockSafety + */ + BlockSafety getBlockSafety(); + + /** + * Sets the {@link BlockSafety} this {@link Core} is using. + * @param blockSafety The new {@link BlockSafety}. + * @see BlockSafety + * @see SimpleBlockSafety + */ + void setBlockSafety(BlockSafety blockSafety); + + /** + * Gets the {@link LocationManipulation} this {@link Core} is using. + * @return The {@link LocationManipulation} this {@link Core} is using. + * @see LocationManipulation + * @see SimpleLocationManipulation + */ + LocationManipulation getLocationManipulation(); + + /** + * Sets the {@link LocationManipulation} this {@link Core} is using. + * @param locationManipulation The new {@link LocationManipulation}. + * @see LocationManipulation + * @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/LocationManipulation.java b/src/main/java/com/onarandombox/MultiverseCore/api/LocationManipulation.java new file mode 100644 index 00000000..38c5f3f9 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/api/LocationManipulation.java @@ -0,0 +1,99 @@ +package com.onarandombox.MultiverseCore.api; + +import org.bukkit.Location; +import org.bukkit.entity.Vehicle; +import org.bukkit.util.Vector; + +/** + * Used to manipulate locations. + */ +public interface LocationManipulation { + /** + * Convert a Location into a Colon separated string to allow us to store it in text. + *

+ * WORLD:X,Y,Z:yaw:pitch + *

+ * The corresponding String2Loc function is {@link #stringToLocation} + * + * @param location The Location to save. + * @return The location as a string in this format: WORLD:x,y,z:yaw:pitch + */ + String locationToString(Location location); + + /** + * This method simply does some rounding, rather than forcing a call to the server to get the blockdata. + * + * @param l The location to round to the block location + * @return A rounded location. + */ + Location getBlockLocation(Location l); + + /** + * Returns a new location from a given string. The format is as follows: + *

+ * WORLD:X,Y,Z:yaw:pitch + *

+ * The corresponding Location2String function is {@link #stringToLocation} + * + * @param locationString The location represented as a string (WORLD:X,Y,Z:yaw:pitch) + * @return A new location defined by the string or null if the string was invalid. + */ + Location stringToLocation(String locationString); + + /** + * Returns a colored string with the coords. + * + * @param l The {@link Location} + * @return The {@link String} + */ + String strCoords(Location l); + + /** + * Converts a location to a printable readable formatted string including pitch/yaw. + * + * @param l The {@link Location} + * @return The {@link String} + */ + String strCoordsRaw(Location l); + + /** + * Return the NESW Direction a Location is facing. + * + * @param location The {@link Location} + * @return The NESW Direction + */ + String getDirection(Location location); + + /** + * Returns the float yaw position for the given cardinal direction. + * + * @param orientation The cardinal direction + * @return The yaw + */ + float getYaw(String orientation); + + /** + * Returns a speed float from a given vector. + * + * @param v The {@link Vector} + * @return The speed + */ + float getSpeed(Vector v); + + /** + * Returns a translated vector from the given direction. + * + * @param v The old {@link Vector} + * @param direction The new direction + * @return The translated {@link Vector} + */ + Vector getTranslatedVector(Vector v, String direction); + + /** + * Returns the next Location that a {@link Vehicle} is traveling at. + * + * @param v The {@link Vehicle} + * @return The {@link Location} + */ + Location getNextBlock(Vehicle v); +} \ No newline at end of file diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java index 40300ef0..023bf1b6 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java @@ -8,6 +8,8 @@ package com.onarandombox.MultiverseCore.api; import com.onarandombox.MultiverseCore.utils.PurgeWorlds; +import com.onarandombox.MultiverseCore.utils.SimpleWorldPurger; + import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.WorldType; @@ -168,9 +170,21 @@ public interface MVWorldManager { * Return the World Purger. * * @return A valid {@link PurgeWorlds}. + * @deprecated {@link PurgeWorlds} is deprecated! */ + @Deprecated PurgeWorlds getWorldPurger(); + /** + * Gets the {@link WorldPurger}. + *

+ * TODO: Remove {@link #getWorldPurger()} and replace it with this method. + * @return The {@link WorldPurger} this {@link MVWorldManager} is using. + * @see WorldPurger + * @see SimpleWorldPurger + */ + WorldPurger getTheWorldPurger(); + /** * Gets the world players will spawn in on first join. * Currently this always returns worlds.get(0) from Bukkit. diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseMessaging.java b/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseMessaging.java new file mode 100644 index 00000000..ae2bd004 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseMessaging.java @@ -0,0 +1,56 @@ +package com.onarandombox.MultiverseCore.api; + +import java.util.Collection; + +import org.bukkit.command.CommandSender; + +/** + * Multiverse-messaging. + */ +public interface MultiverseMessaging { + /** + * Sets the message-cooldown. + * @param milliseconds The new message-cooldown in milliseconds. + */ + void setCooldown(int milliseconds); + + /** + * Sends a message to the specified sender if the cooldown has passed. + * + * @param sender The person/console to send the message to. + * @param message The message to send. + * @param ignoreCooldown If true this message will always be sent. Useful for things like menus + * @return true if the message was sent, false if not. + */ + boolean sendMessage(CommandSender sender, String message, boolean ignoreCooldown); + + /** + * Sends a group of messages to the specified sender if the cooldown has passed. + * This method is needed, since sending many messages in quick succession would violate + * the cooldown. + * + * @param sender The person/console to send the message to. + * @param messages The messages to send. + * @param ignoreCooldown If true these messages will always be sent. Useful for things like menus + * @return true if the message was sent, false if not. + */ + boolean sendMessages(CommandSender sender, String[] messages, boolean ignoreCooldown); + + /** + * Sends a group of messages to the specified sender if the cooldown has passed. + * This method is needed, since sending many messages in quick succession would violate + * the cooldown. + * + * @param sender The person/console to send the message to. + * @param messages The messages to send. + * @param ignoreCooldown If true these messages will always be sent. Useful for things like menus + * @return true if the message was sent, false if not. + */ + boolean sendMessages(CommandSender sender, Collection messages, boolean ignoreCooldown); + + /** + * Gets the message-cooldown. + * @return The message-cooldown. + */ + int getCooldown(); +} 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/api/WorldPurger.java b/src/main/java/com/onarandombox/MultiverseCore/api/WorldPurger.java new file mode 100644 index 00000000..6be96bba --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/api/WorldPurger.java @@ -0,0 +1,49 @@ +package com.onarandombox.MultiverseCore.api; + +import java.util.List; + +import org.bukkit.command.CommandSender; + +/** + * Used to remove animals from worlds that don't belong there. + */ +public interface WorldPurger { + + /** + * Synchronizes the given world with it's settings. + * + * @param worlds A list of {@link MultiverseWorld} + */ + void purgeWorlds(List worlds); + + /** + * Convenience method for {@link #purgeWorld(CommandSender, MultiverseWorld, List, boolean, boolean)} that takes the settings from the world-config. + * + * @param world The {@link MultiverseWorld}. + */ + void purgeWorld(MultiverseWorld world); + + /** + * Clear all animals/monsters that do not belong to a world according to the config. + * + * @param mvworld The {@link MultiverseWorld}. + * @param thingsToKill A {@link List} of animals/monsters to be killed. + * @param negateAnimals Whether the monsters in the list should be negated. + * @param negateMonsters Whether the animals in the list should be negated. + */ + void purgeWorld(MultiverseWorld mvworld, List thingsToKill, boolean negateAnimals, + boolean negateMonsters); + + /** + * Clear all animals/monsters that do not belong to a world according to the config. + * + * @param mvworld The {@link MultiverseWorld}. + * @param thingsToKill A {@link List} of animals/monsters to be killed. + * @param negateAnimals Whether the monsters in the list should be negated. + * @param negateMonsters Whether the animals in the list should be negated. + * @param sender The {@link CommandSender} that initiated the action. He will/should be notified. + */ + void purgeWorld(MultiverseWorld mvworld, List thingsToKill, boolean negateAnimals, + boolean negateMonsters, CommandSender sender); + +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CoordCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CoordCommand.java index f2d09887..944d8029 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CoordCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CoordCommand.java @@ -10,7 +10,6 @@ package com.onarandombox.MultiverseCore.commands; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MultiverseWorld; -import com.onarandombox.MultiverseCore.utils.LocationManipulation; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.World; @@ -61,8 +60,8 @@ public class CoordCommand extends MultiverseCommand { DecimalFormat df = new DecimalFormat(); df.setMinimumFractionDigits(0); df.setMaximumFractionDigits(2); - p.sendMessage(ChatColor.AQUA + "Coordinates: " + ChatColor.WHITE + LocationManipulation.strCoords(p.getLocation())); - p.sendMessage(ChatColor.AQUA + "Direction: " + ChatColor.WHITE + LocationManipulation.getDirection(p.getLocation())); + p.sendMessage(ChatColor.AQUA + "Coordinates: " + ChatColor.WHITE + plugin.getLocationManipulation().strCoords(p.getLocation())); + p.sendMessage(ChatColor.AQUA + "Direction: " + ChatColor.WHITE + plugin.getLocationManipulation().getDirection(p.getLocation())); p.sendMessage(ChatColor.AQUA + "Block: " + ChatColor.WHITE + Material.getMaterial(world.getBlockTypeIdAt(p.getLocation()))); } else { sender.sendMessage("This command needs to be used from a Player."); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/InfoCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/InfoCommand.java index dffbd882..c33b06ec 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/InfoCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/InfoCommand.java @@ -14,7 +14,6 @@ import com.onarandombox.MultiverseCore.api.MultiverseWorld; import com.onarandombox.MultiverseCore.utils.FancyColorScheme; import com.onarandombox.MultiverseCore.utils.FancyHeader; import com.onarandombox.MultiverseCore.utils.FancyMessage; -import com.onarandombox.MultiverseCore.utils.LocationManipulation; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.command.CommandSender; @@ -113,7 +112,7 @@ public class InfoCommand extends MultiverseCommand { message.add(new FancyMessage("World Type: ", world.getWorldType().toString(), colors)); //message.add(new FancyMessage("Game Mode: ", StringUtils.capitalize(world.getGameMode().toString()), colors)); Location spawn = world.getSpawnLocation(); - message.add(new FancyMessage("Spawn Location: ", LocationManipulation.strCoords(spawn), colors)); + message.add(new FancyMessage("Spawn Location: ", plugin.getLocationManipulation().strCoords(spawn), colors)); message.add(new FancyMessage("World Scale: ", world.getScaling() + "", colors)); if (world.getPrice() > 0) { message.add(new FancyMessage("Price to enter this world: ", diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/MultiverseCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/MultiverseCommand.java index 9790b110..ae54a9b8 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/MultiverseCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/MultiverseCommand.java @@ -8,7 +8,7 @@ package com.onarandombox.MultiverseCore.commands; import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.utils.MVMessaging; +import com.onarandombox.MultiverseCore.api.MultiverseMessaging; import com.pneumaticraft.commandhandler.Command; import org.bukkit.command.CommandSender; @@ -24,9 +24,9 @@ public abstract class MultiverseCommand extends Command { */ protected MultiverseCore plugin; /** - * The reference to {@link MVMessaging}. + * The reference to {@link MultiverseMessaging}. */ - protected MVMessaging messaging; + protected MultiverseMessaging messaging; public MultiverseCommand(MultiverseCore plugin) { super(plugin); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/PurgeCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/PurgeCommand.java index 89950d5b..8112fd0f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/PurgeCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/PurgeCommand.java @@ -10,7 +10,7 @@ package com.onarandombox.MultiverseCore.commands; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MultiverseWorld; -import com.onarandombox.MultiverseCore.utils.PurgeWorlds; +import com.onarandombox.MultiverseCore.api.WorldPurger; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -78,7 +78,7 @@ public class PurgeCommand extends MultiverseCommand { worldsToRemoveEntitiesFrom.add(this.worldManager.getMVWorld(worldName)); } - PurgeWorlds purger = this.worldManager.getWorldPurger(); + WorldPurger purger = this.worldManager.getTheWorldPurger(); ArrayList thingsToKill = new ArrayList(); if (deathName.equalsIgnoreCase("all") || deathName.equalsIgnoreCase("animals") || deathName.equalsIgnoreCase("monsters")) { thingsToKill.add(deathName.toUpperCase()); @@ -86,7 +86,7 @@ public class PurgeCommand extends MultiverseCommand { Collections.addAll(thingsToKill, deathName.toUpperCase().split(",")); } for (MultiverseWorld w : worldsToRemoveEntitiesFrom) { - purger.purgeWorld(sender, w, thingsToKill, false, false); + purger.purgeWorld(w, thingsToKill, false, false, sender); } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/SetSpawnCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/SetSpawnCommand.java index ba8863e9..0e0cd96d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/SetSpawnCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/SetSpawnCommand.java @@ -8,9 +8,8 @@ package com.onarandombox.MultiverseCore.commands; import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.BlockSafety; import com.onarandombox.MultiverseCore.api.MultiverseWorld; -import com.onarandombox.MultiverseCore.utils.BlockSafety; -import com.onarandombox.MultiverseCore.utils.LocationManipulation; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; @@ -56,7 +55,7 @@ public class SetSpawnCommand extends MultiverseCommand { MultiverseWorld foundWorld = this.plugin.getMVWorldManager().getMVWorld(w.getName()); if (foundWorld != null) { foundWorld.setSpawnLocation(p.getLocation()); - BlockSafety bs = new BlockSafety(); + BlockSafety bs = this.plugin.getBlockSafety(); if (!bs.playerCanSpawnHereSafely(p.getLocation()) && foundWorld.getAdjustSpawn()) { sender.sendMessage("It looks like that location would normally be unsafe. But I trust you."); sender.sendMessage("I'm turning off the Safe-T-Teleporter for spawns to this world."); @@ -64,7 +63,7 @@ public class SetSpawnCommand extends MultiverseCommand { sender.sendMessage(ChatColor.AQUA + "/mvm set adjustspawn true " + foundWorld.getAlias()); foundWorld.setAdjustSpawn(false); } - sender.sendMessage("Spawn was set to: " + LocationManipulation.strCoords(p.getLocation())); + sender.sendMessage("Spawn was set to: " + plugin.getLocationManipulation().strCoords(p.getLocation())); } else { w.setSpawnLocation(l.getBlockX(), l.getBlockY(), l.getBlockZ()); sender.sendMessage("Multiverse does not know about this world, only X,Y and Z set. Please import it to set the spawn fully (Pitch/Yaws)."); 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 8adc91ac..8232c5bb 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java @@ -14,8 +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.LocationManipulation; -import com.onarandombox.MultiverseCore.utils.SafeTTeleporter; +import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; @@ -43,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); } @@ -163,7 +162,8 @@ public class TeleportCommand extends MultiverseCommand { } TeleportResult result = this.playerTeleporter.safelyTeleport(teleporter, teleportee, d); if (result == TeleportResult.FAIL_UNSAFE) { - this.plugin.log(Level.FINE, "Could not teleport " + teleportee.getName() + " to " + LocationManipulation.strCoordsRaw(d.getLocation(teleportee))); + this.plugin.log(Level.FINE, "Could not teleport " + teleportee.getName() + + " to " + plugin.getLocationManipulation().strCoordsRaw(d.getLocation(teleportee))); this.plugin.log(Level.FINE, "Queueing Command"); Class[] paramTypes = { CommandSender.class, Player.class, Location.class }; List items = new ArrayList(); diff --git a/src/main/java/com/onarandombox/MultiverseCore/configuration/LocationConfigProperty.java b/src/main/java/com/onarandombox/MultiverseCore/configuration/LocationConfigProperty.java index b1af4ae1..9a7096f7 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/configuration/LocationConfigProperty.java +++ b/src/main/java/com/onarandombox/MultiverseCore/configuration/LocationConfigProperty.java @@ -61,6 +61,7 @@ public class LocationConfigProperty implements MVActiveConfigProperty */ @Override public boolean parseValue(String value) { + // TODO: oh my god, what should we do here? Location parsed = LocationManipulation.stringToLocation(value); return this.setValue(parsed); } @@ -108,6 +109,7 @@ public class LocationConfigProperty implements MVActiveConfigProperty double yaw = this.section.getDouble(this.configNode + ".yaw", defaultValue.getYaw()); String w = this.section.getString(this.configNode + ".world", defaultValue.getWorld().getName()); Location found = LocationManipulation.stringToLocation(w + ":" + x + "," + y + "," + z + ":" + yaw + ":" + pitch); + // TODO: oh my god, what should we do here? if (found != null) { return found; } @@ -116,6 +118,7 @@ public class LocationConfigProperty implements MVActiveConfigProperty @Override public String toString() { + // TODO: oh my god, what should we do here? return LocationManipulation.strCoordsRaw(this.value); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/destination/WorldDestination.java b/src/main/java/com/onarandombox/MultiverseCore/destination/WorldDestination.java index a7ba3313..6a584596 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/destination/WorldDestination.java +++ b/src/main/java/com/onarandombox/MultiverseCore/destination/WorldDestination.java @@ -8,9 +8,9 @@ package com.onarandombox.MultiverseCore.destination; import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.Core; import com.onarandombox.MultiverseCore.api.MVDestination; import com.onarandombox.MultiverseCore.api.MultiverseWorld; -import com.onarandombox.MultiverseCore.utils.LocationManipulation; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.plugin.java.JavaPlugin; @@ -93,6 +93,9 @@ public class WorldDestination implements MVDestination { */ @Override public void setDestination(JavaPlugin plugin, String destination) { + // TODO Taking a JavaPlugin here is rather useless, if we keep casting it up to MultiverseCore. + // We should change that. + Core core = (Core) plugin; String[] items = destination.split(":"); if (items.length > 3) { isValid = false; @@ -100,19 +103,20 @@ public class WorldDestination implements MVDestination { } if (items.length == 1 && ((MultiverseCore) plugin).getMVWorldManager().isMVWorld(items[0])) { isValid = true; - this.world = ((MultiverseCore) plugin).getMVWorldManager().getMVWorld(items[0]); + this.world = core.getMVWorldManager().getMVWorld(items[0]); return; } if (items.length == 2 && ((MultiverseCore) plugin).getMVWorldManager().isMVWorld(items[0])) { - this.world = ((MultiverseCore) plugin).getMVWorldManager().getMVWorld(items[0]); - this.yaw = LocationManipulation.getYaw(items[1]); + this.world = core.getMVWorldManager().getMVWorld(items[0]); + this.yaw = core.getLocationManipulation().getYaw(items[1]); return; } if (items[0].equalsIgnoreCase("w") && ((MultiverseCore) plugin).getMVWorldManager().isMVWorld(items[1])) { this.world = ((MultiverseCore) plugin).getMVWorldManager().getMVWorld(items[1]); isValid = true; if (items.length == 3) { - this.yaw = LocationManipulation.getYaw(items[2]); + // TODO: oh my god, what should we do here? + this.yaw = core.getLocationManipulation().getYaw(items[2]); } } } 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/AnchorManager.java b/src/main/java/com/onarandombox/MultiverseCore/utils/AnchorManager.java index 3bb77465..c06c7da8 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/AnchorManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/AnchorManager.java @@ -48,7 +48,7 @@ public class AnchorManager { Set anchorKeys = anchorsSection.getKeys(false); for (String key : anchorKeys) { //world:x,y,z:pitch:yaw - Location anchorLocation = LocationManipulation.stringToLocation(anchorsSection.getString(key, "")); + Location anchorLocation = plugin.getLocationManipulation().stringToLocation(anchorsSection.getString(key, "")); if (anchorLocation != null) { MultiverseCore.staticLog(Level.INFO, "Loading anchor: '" + key + "'..."); this.anchors.put(key, anchorLocation); @@ -98,7 +98,7 @@ public class AnchorManager { * @return True if the anchor was successfully saved. */ public boolean saveAnchorLocation(String anchor, String location) { - Location parsed = LocationManipulation.stringToLocation(location); + Location parsed = plugin.getLocationManipulation().stringToLocation(location); return parsed != null && this.saveAnchorLocation(anchor, parsed); } @@ -112,7 +112,7 @@ public class AnchorManager { if (l == null) { return false; } - this.anchorConfig.set("anchors." + anchor, LocationManipulation.locationToString(l)); + this.anchorConfig.set("anchors." + anchor, plugin.getLocationManipulation().locationToString(l)); this.anchors.put(anchor, l); return this.saveAnchors(); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/BlockSafety.java b/src/main/java/com/onarandombox/MultiverseCore/utils/BlockSafety.java index aee6bb64..f5aca91e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/BlockSafety.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/BlockSafety.java @@ -18,7 +18,10 @@ import java.util.logging.Level; /** * Used to determine block/location-related facts. + * + * @deprecated Use instead: {@link com.onarandombox.MultiverseCore.api.BlockSafety} and {@link SimpleBlockSafety}. */ +@Deprecated public class BlockSafety { /** diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/LocationManipulation.java b/src/main/java/com/onarandombox/MultiverseCore/utils/LocationManipulation.java index 0c605309..eeb8203c 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/LocationManipulation.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/LocationManipulation.java @@ -22,7 +22,10 @@ import java.util.Map; /** * Utility class to manipulate locations. + * + * @deprecated Use instead: {@link com.onarandombox.MultiverseCore.api.LocationManipulation} and {@link SimpleLocationManipulation}. */ +@Deprecated public class LocationManipulation { private LocationManipulation() { } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVMessaging.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVMessaging.java index 497e076e..45e73654 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVMessaging.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVMessaging.java @@ -10,14 +10,16 @@ package com.onarandombox.MultiverseCore.utils; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import com.onarandombox.MultiverseCore.api.MultiverseMessaging; + import java.util.Collection; import java.util.HashMap; import java.util.Map; /** - * Utility-class for messaging. + * The default-implementation of {@link MultiverseMessaging}. */ -public class MVMessaging { +public class MVMessaging implements MultiverseMessaging { private Map sentList; private int cooldown; @@ -27,35 +29,25 @@ public class MVMessaging { } /** - * Sets the message-cooldown. - * @param milliseconds The new message-cooldown in milliseconds. + * {@inheritDoc} */ + @Override public void setCooldown(int milliseconds) { this.cooldown = milliseconds; } /** - * Sends a message to the specified sender if the cooldown has passed. - * - * @param sender The person/console to send the message to. - * @param message The message to send. - * @param ignoreCooldown If true this message will always be sent. Useful for things like menus - * @return true if the message was sent, false if not. + * {@inheritDoc} */ + @Override public boolean sendMessage(CommandSender sender, String message, boolean ignoreCooldown) { return this.sendMessages(sender, new String[]{ message }, ignoreCooldown); } /** - * Sends a group of messages to the specified sender if the cooldown has passed. - * This method is needed, since sending many messages in quick succession would violate - * the cooldown. - * - * @param sender The person/console to send the message to. - * @param messages The messages to send. - * @param ignoreCooldown If true these messages will always be sent. Useful for things like menus - * @return true if the message was sent, false if not. + * {@inheritDoc} */ + @Override public boolean sendMessages(CommandSender sender, String[] messages, boolean ignoreCooldown) { if (!(sender instanceof Player) || ignoreCooldown) { @@ -78,15 +70,9 @@ public class MVMessaging { } /** - * Sends a group of messages to the specified sender if the cooldown has passed. - * This method is needed, since sending many messages in quick succession would violate - * the cooldown. - * - * @param sender The person/console to send the message to. - * @param messages The messages to send. - * @param ignoreCooldown If true these messages will always be sent. Useful for things like menus - * @return true if the message was sent, false if not. + * {@inheritDoc} */ + @Override public boolean sendMessages(CommandSender sender, Collection messages, boolean ignoreCooldown) { return this.sendMessages(sender, messages.toArray(new String[0]), ignoreCooldown); } @@ -98,9 +84,9 @@ public class MVMessaging { } /** - * Gets the message-cooldown. - * @return The message-cooldown. + * {@inheritDoc} */ + @Override public int getCooldown() { return cooldown; } 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/PurgeWorlds.java b/src/main/java/com/onarandombox/MultiverseCore/utils/PurgeWorlds.java index f43a6231..e7d32820 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/PurgeWorlds.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/PurgeWorlds.java @@ -9,6 +9,7 @@ package com.onarandombox.MultiverseCore.utils; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MultiverseWorld; + import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.entity.Animals; @@ -25,7 +26,10 @@ import java.util.logging.Level; /** * Utility class that removes animals from worlds that don't belong there. + * + * @deprecated Use instead: {@link WorldPurger} and {@link SimpleWorldPurger}. */ +@Deprecated public class PurgeWorlds { private MultiverseCore plugin; diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java b/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java index e33bb0a9..130abbaa 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/SafeTTeleporter.java @@ -8,9 +8,11 @@ package com.onarandombox.MultiverseCore.utils; import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.BlockSafety; 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; @@ -26,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; @@ -34,7 +39,7 @@ public class SafeTTeleporter { public SafeTTeleporter(MultiverseCore plugin) { this.plugin = plugin; - this.bs = new BlockSafety(); + this.bs = plugin.getBlockSafety(); } private static final int DEFAULT_TOLERANCE = 6; @@ -63,7 +68,7 @@ public class SafeTTeleporter { 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: " + LocationManipulation.strCoordsRaw(safe)); + 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!"); } @@ -77,7 +82,7 @@ public class SafeTTeleporter { } // We want half of it, so we can go up and down tolerance /= 2; - this.plugin.log(Level.FINER, "Given Location of: " + LocationManipulation.strCoordsRaw(l)); + 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. diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleBlockSafety.java b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleBlockSafety.java new file mode 100644 index 00000000..e1ed80df --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleBlockSafety.java @@ -0,0 +1,254 @@ +/****************************************************************************** + * 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.Core; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.entity.Minecart; +import org.bukkit.entity.Vehicle; + +import java.util.logging.Level; + +/** + * The default-implementation of {@link BlockSafety}. + */ +public class SimpleBlockSafety implements BlockSafety { + private final Core plugin; + + public SimpleBlockSafety(Core plugin) { + this.plugin = plugin; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isBlockAboveAir(Location l) { + Location downOne = l.clone(); + downOne.setY(downOne.getY() - 1); + return (downOne.getBlock().getType() == Material.AIR); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean playerCanSpawnHereSafely(World world, double x, double y, double z) { + Location l = new Location(world, x, y, z); + return playerCanSpawnHereSafely(l); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean playerCanSpawnHereSafely(Location l) { + if (l == null) { + // Can't safely spawn at a null location! + return false; + } + + World world = l.getWorld(); + Location actual = l.clone(); + Location upOne = l.clone(); + Location downOne = l.clone(); + upOne.setY(upOne.getY() + 1); + downOne.setY(downOne.getY() - 1); + + if (this.isSolidBlock(world.getBlockAt(actual).getType()) + || this.isSolidBlock(upOne.getBlock().getType())) { + MultiverseCore.staticLog(Level.FINER, "Error Here (Actual)? (" + + actual.getBlock().getType() + ")[" + this.isSolidBlock(actual.getBlock().getType()) + "]"); + MultiverseCore.staticLog(Level.FINER, "Error Here (upOne)? (" + + upOne.getBlock().getType() + ")[" + this.isSolidBlock(upOne.getBlock().getType()) + "]"); + return false; + } + + if (downOne.getBlock().getType() == Material.LAVA || downOne.getBlock().getType() == Material.STATIONARY_LAVA) { + MultiverseCore.staticLog(Level.FINER, "Error Here (downOne)? (" + + downOne.getBlock().getType() + ")[" + this.isSolidBlock(downOne.getBlock().getType()) + "]"); + return false; + } + + if (downOne.getBlock().getType() == Material.FIRE) { + MultiverseCore.staticLog(Level.FINER, "There's fire below! (" + + actual.getBlock().getType() + ")[" + this.isSolidBlock(actual.getBlock().getType()) + "]"); + return false; + } + + if (isBlockAboveAir(actual)) { + MultiverseCore.staticLog(Level.FINER, "Is block above air [" + isBlockAboveAir(actual) + "]"); + MultiverseCore.staticLog(Level.FINER, "Has 2 blocks of water below [" + this.hasTwoBlocksofWaterBelow(actual) + "]"); + return this.hasTwoBlocksofWaterBelow(actual); + } + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public Location getTopBlock(Location l) { + Location check = l.clone(); + check.setY(127); // SUPPRESS CHECKSTYLE: MagicNumberCheck + while (check.getY() > 0) { + if (this.playerCanSpawnHereSafely(check)) { + return check; + } + check.setY(check.getY() - 1); + } + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public Location getBottomBlock(Location l) { + Location check = l.clone(); + check.setY(0); + while (check.getY() < 127) { // SUPPRESS CHECKSTYLE: MagicNumberCheck + if (this.playerCanSpawnHereSafely(check)) { + return check; + } + check.setY(check.getY() + 1); + } + return null; + } + + /* + * If someone has a better way of this... Please either tell us, or submit a pull request! + */ + private boolean isSolidBlock(Material type) { + switch (type) { + case AIR: + return false; + case SNOW: + return false; + case TRAP_DOOR: + return false; + case TORCH: + return false; + case YELLOW_FLOWER: + return false; + case RED_ROSE: + return false; + case RED_MUSHROOM: + return false; + case BROWN_MUSHROOM: + return false; + case REDSTONE: + return false; + case REDSTONE_WIRE: + return false; + case RAILS: + return false; + case POWERED_RAIL: + return false; + case REDSTONE_TORCH_ON: + return false; + case REDSTONE_TORCH_OFF: + return false; + case DEAD_BUSH: + return false; + case SAPLING: + return false; + case STONE_BUTTON: + return false; + case LEVER: + return false; + case LONG_GRASS: + return false; + case PORTAL: + return false; + case STONE_PLATE: + return false; + case WOOD_PLATE: + return false; + case SEEDS: + return false; + case SUGAR_CANE_BLOCK: + return false; + case WALL_SIGN: + return false; + case SIGN_POST: + return false; + case WOODEN_DOOR: + return false; + case STATIONARY_WATER: + return false; + case WATER: + return false; + default: + return true; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isEntitiyOnTrack(Location l) { + Material currentBlock = l.getBlock().getType(); + return (currentBlock == Material.POWERED_RAIL || currentBlock == Material.DETECTOR_RAIL || currentBlock == Material.RAILS); + } + + /** + * Checks recursively below a {@link Location} for 2 blocks of water. + * + * @param l The {@link Location} + * @return Whether there are 2 blocks of water + */ + private boolean hasTwoBlocksofWaterBelow(Location l) { + if (l.getBlockY() < 0) { + return false; + } + Location oneBelow = l.clone(); + oneBelow.subtract(0, 1, 0); + if (oneBelow.getBlock().getType() == Material.WATER || oneBelow.getBlock().getType() == Material.STATIONARY_WATER) { + Location twoBelow = oneBelow.clone(); + twoBelow.subtract(0, 1, 0); + return (oneBelow.getBlock().getType() == Material.WATER || oneBelow.getBlock().getType() == Material.STATIONARY_WATER); + } + if (oneBelow.getBlock().getType() != Material.AIR) { + return false; + } + return hasTwoBlocksofWaterBelow(oneBelow); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean canSpawnCartSafely(Minecart cart) { + if (this.isBlockAboveAir(cart.getLocation())) { + return true; + } + if (this.isEntitiyOnTrack(plugin.getLocationManipulation().getNextBlock(cart))) { + return true; + } + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean canSpawnVehicleSafely(Vehicle vehicle) { + if (this.isBlockAboveAir(vehicle.getLocation())) { + return true; + } + return false; + } + +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleLocationManipulation.java b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleLocationManipulation.java new file mode 100644 index 00000000..3d0436b1 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleLocationManipulation.java @@ -0,0 +1,251 @@ +/****************************************************************************** + * 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 org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Vehicle; +import org.bukkit.util.Vector; + +import com.onarandombox.MultiverseCore.api.LocationManipulation; + +import java.text.DecimalFormat; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * The default-implementation of {@link LocationManipulation}. + */ +public class SimpleLocationManipulation implements LocationManipulation { + private static final Map ORIENTATION_INTS; + + static { + Map orientationInts = new HashMap(); + // BEGIN CHECKSTYLE-SUPPRESSION: MagicNumberCheck + orientationInts.put("n", 180); + orientationInts.put("ne", 225); + orientationInts.put("e", 270); + orientationInts.put("se", 315); + orientationInts.put("s", 0); + orientationInts.put("sw", 45); + orientationInts.put("w", 90); + orientationInts.put("nw", 135); + + // "freeze" the map: + ORIENTATION_INTS = Collections.unmodifiableMap(orientationInts); + // END CHECKSTYLE-SUPPRESSION: MagicNumberCheck + } + + /** + * {@inheritDoc} + */ + @Override + public String locationToString(Location location) { + if (location == null) { + return ""; + } + return String.format("%s:%.2f,%.2f,%.2f:%.2f:%.2f", location.getWorld().getName(), + location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + } + + /** + * {@inheritDoc} + */ + @Override + public Location getBlockLocation(Location l) { + l.setX(l.getBlockX()); + l.setY(l.getBlockY()); + l.setZ(l.getBlockZ()); + return l; + } + + /** + * {@inheritDoc} + */ + @Override + public Location stringToLocation(String locationString) { + //format: + //world:x,y,z:pitch:yaw + if (locationString == null) { + return null; + } + + // Split the whole string, format is: + // {'world', 'x,y,z'[, 'pitch', 'yaw']} + String[] split = locationString.split(":"); + if (split.length < 2 || split.length > 4) { // SUPPRESS CHECKSTYLE: MagicNumberCheck + return null; + } + // Split the xyz string, format is: + // {'x', 'y', 'z'} + String[] xyzsplit = split[1].split(","); + if (xyzsplit.length != 3) { + return null; + } + + // Verify the world is valid + World w = Bukkit.getWorld(split[0]); + if (w == null) { + return null; + } + + try { + float pitch = 0; + float yaw = 0; + if (split.length >= 3) { + yaw = (float) Double.parseDouble(split[2]); + } + if (split.length == 4) { // SUPPRESS CHECKSTYLE: MagicNumberCheck + pitch = (float) Double.parseDouble(split[3]); + } + return new Location(w, Double.parseDouble(xyzsplit[0]), Double.parseDouble(xyzsplit[1]), Double.parseDouble(xyzsplit[2]), yaw, pitch); + } catch (NumberFormatException e) { + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + public String strCoords(Location l) { + String result = ""; + DecimalFormat df = new DecimalFormat(); + df.setMinimumFractionDigits(0); + df.setMaximumFractionDigits(2); + result += ChatColor.WHITE + "X: " + ChatColor.AQUA + df.format(l.getX()) + " "; + result += ChatColor.WHITE + "Y: " + ChatColor.AQUA + df.format(l.getY()) + " "; + result += ChatColor.WHITE + "Z: " + ChatColor.AQUA + df.format(l.getZ()) + " "; + result += ChatColor.WHITE + "P: " + ChatColor.GOLD + df.format(l.getPitch()) + " "; + result += ChatColor.WHITE + "Y: " + ChatColor.GOLD + df.format(l.getYaw()) + " "; + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public String strCoordsRaw(Location l) { + if (l == null) { + return "null"; + } + String result = ""; + DecimalFormat df = new DecimalFormat(); + df.setMinimumFractionDigits(0); + df.setMaximumFractionDigits(2); + result += "X: " + df.format(l.getX()) + " "; + result += "Y: " + df.format(l.getY()) + " "; + result += "Z: " + df.format(l.getZ()) + " "; + result += "P: " + df.format(l.getPitch()) + " "; + result += "Y: " + df.format(l.getYaw()) + " "; + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public String getDirection(Location location) { + // BEGIN CHECKSTYLE-SUPPRESSION: MagicNumberCheck + double r = (location.getYaw() % 360) + 180; + // Remember, these numbers are every 45 degrees with a 22.5 offset, to detect boundaries. + String dir; + if (r < 22.5) + dir = "n"; + else if (r < 67.5) + dir = "ne"; + else if (r < 112.5) + dir = "e"; + else if (r < 157.5) + dir = "se"; + else if (r < 202.5) + dir = "s"; + else if (r < 247.5) + dir = "sw"; + else if (r < 292.5) + dir = "w"; + else if (r < 337.5) + dir = "nw"; + else + dir = "n"; + // END CHECKSTYLE-SUPPRESSION: MagicNumberCheck + + return dir; + } + + /** + * {@inheritDoc} + */ + @Override + public float getYaw(String orientation) { + if (orientation == null) { + return 0; + } + if (ORIENTATION_INTS.containsKey(orientation.toLowerCase())) { + return ORIENTATION_INTS.get(orientation.toLowerCase()); + } + return 0; + } + + /** + * {@inheritDoc} + */ + @Override + public float getSpeed(Vector v) { + return (float) Math.sqrt(v.getX() * v.getX() + v.getZ() * v.getZ()); + } + + // X, Y, Z + // -W/+E,0, -N/+S + + /** + * {@inheritDoc} + */ + @Override + public Vector getTranslatedVector(Vector v, String direction) { + if (direction == null) { + return v; + } + float speed = getSpeed(v); + float halfSpeed = (float) (speed / 2.0); + // TODO: Mathmatacize this: + if (direction.equalsIgnoreCase("n")) { + return new Vector(0, 0, -1 * speed); + } else if (direction.equalsIgnoreCase("ne")) { + return new Vector(halfSpeed, 0, -1 * halfSpeed); + } else if (direction.equalsIgnoreCase("e")) { + return new Vector(speed, 0, 0); + } else if (direction.equalsIgnoreCase("se")) { + return new Vector(halfSpeed, 0, halfSpeed); + } else if (direction.equalsIgnoreCase("s")) { + return new Vector(0, 0, speed); + } else if (direction.equalsIgnoreCase("sw")) { + return new Vector(-1 * halfSpeed, 0, halfSpeed); + } else if (direction.equalsIgnoreCase("w")) { + return new Vector(-1 * speed, 0, 0); + } else if (direction.equalsIgnoreCase("nw")) { + return new Vector(-1 * halfSpeed, 0, -1 * halfSpeed); + } + return v; + } + + /** + * {@inheritDoc} + */ + @Override + public Location getNextBlock(Vehicle v) { + Vector vector = v.getVelocity(); + Location location = v.getLocation(); + int x = vector.getX() < 0 ? vector.getX() == 0 ? 0 : -1 : 1; + int z = vector.getZ() < 0 ? vector.getZ() == 0 ? 0 : -1 : 1; + return location.add(x, 0, z); + } +} 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..f68b39fe --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleSafeTTeleporter.java @@ -0,0 +1,334 @@ +/****************************************************************************** + * 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.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; + + public SimpleSafeTTeleporter(MultiverseCore plugin) { + this.plugin = plugin; + } + + 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 (plugin.getBlockSafety().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 (plugin.getBlockSafety().playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + + // Then down adjustedCircle *2 + for (int i = 0; i < adjustedCircle * 2; i++) { + checkLoc.add(-1, 0, 0); + if (plugin.getBlockSafety().playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + + // Then left adjustedCircle *2 + for (int i = 0; i < adjustedCircle * 2; i++) { + checkLoc.add(0, 0, -1); + if (plugin.getBlockSafety().playerCanSpawnHereSafely(checkLoc)) { + return true; + } + } + + // Then up Then left adjustedCircle *2 + for (int i = 0; i < adjustedCircle * 2; i++) { + checkLoc.add(1, 0, 0); + if (plugin.getBlockSafety().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 (plugin.getBlockSafety().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 (plugin.getBlockSafety().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 (!plugin.getBlockSafety().canSpawnCartSafely(m)) { + return null; + } + } else if (e instanceof Vehicle) { + Vehicle v = (Vehicle) e; + if (!plugin.getBlockSafety().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 && !plugin.getBlockSafety().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/SimpleWorldPurger.java b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleWorldPurger.java new file mode 100644 index 00000000..7f6bddb7 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/SimpleWorldPurger.java @@ -0,0 +1,153 @@ +/****************************************************************************** + * 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.MultiverseWorld; +import com.onarandombox.MultiverseCore.api.WorldPurger; + +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Animals; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Ghast; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Slime; +import org.bukkit.entity.Squid; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +/** + * Utility class that removes animals from worlds that don't belong there. + */ +public class SimpleWorldPurger implements WorldPurger { + + private MultiverseCore plugin; + + public SimpleWorldPurger(MultiverseCore plugin) { + this.plugin = plugin; + } + + /** + * {@inheritDoc} + */ + @Override + public void purgeWorlds(List worlds) { + if (worlds == null || worlds.isEmpty()) { + return; + } + for (MultiverseWorld world : worlds) { + this.purgeWorld(world); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void purgeWorld(MultiverseWorld world) { + if (world == null) { + return; + } + ArrayList allMobs = new ArrayList(world.getAnimalList()); + allMobs.addAll(world.getMonsterList()); + purgeWorld(world, allMobs, !world.canAnimalsSpawn(), !world.canMonstersSpawn()); + } + + /** + * {@inheritDoc} + */ + @Override + public void purgeWorld(MultiverseWorld mvworld, List thingsToKill, + boolean negateAnimals, boolean negateMonsters, CommandSender sender) { + if (mvworld == null) { + return; + } + World world = this.plugin.getServer().getWorld(mvworld.getName()); + if (world == null) { + return; + } + int entitiesKilled = 0; + for (Entity e : world.getEntities()) { + this.plugin.log(Level.FINEST, "Entity list (aval for purge) from WORLD < " + mvworld.getName() + " >: " + e.toString()); + + // Check against Monsters + if (killMonster(mvworld, e, thingsToKill, negateMonsters)) { + entitiesKilled++; + continue; + } + // Check against Animals + if (this.killCreature(mvworld, e, thingsToKill, negateAnimals)) { + entitiesKilled++; + } + } + if (sender != null) { + sender.sendMessage(entitiesKilled + " entities purged from the world '" + world.getName() + "'"); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void purgeWorld(MultiverseWorld mvworld, List thingsToKill, boolean negateAnimals, boolean negateMonsters) { + purgeWorld(mvworld, thingsToKill, negateAnimals, negateMonsters, null); + } + + private boolean killCreature(MultiverseWorld mvworld, Entity e, List creaturesToKill, boolean negate) { + String entityName = e.toString().replaceAll("Craft", "").toUpperCase(); + if (e instanceof Squid || e instanceof Animals) { + if (creaturesToKill.contains(entityName) || creaturesToKill.contains("ALL") || creaturesToKill.contains("ANIMALS")) { + if (!negate) { + e.remove(); + return true; + } + } else { + if (negate) { + e.remove(); + return true; + } + } + } + return false; + } + + /* + * Will kill the monster if it's in the list UNLESS the NEGATE boolean is set, then it will kill it if it's NOT. + */ + private boolean killMonster(MultiverseWorld mvworld, Entity e, List creaturesToKill, boolean negate) { + String entityName = ""; + //TODO: Fixme once either Rigby puts his awesome thing in OR Enderdragon gets a toString, OR both. + if (e instanceof EnderDragon) { + entityName = "ENDERDRAGON"; + } else { + entityName = e.toString().replaceAll("Craft", "").toUpperCase(); + } + if (e instanceof Slime || e instanceof Monster || e instanceof Ghast || e instanceof EnderDragon) { + this.plugin.log(Level.FINER, "Looking at a monster: " + e); + if (creaturesToKill.contains(entityName) || creaturesToKill.contains("ALL") || creaturesToKill.contains("MONSTERS")) { + if (!negate) { + this.plugin.log(Level.FINEST, "Removing a monster: " + e); + e.remove(); + return true; + } + } else { + if (negate) { + this.plugin.log(Level.FINEST, "Removing a monster: " + e); + e.remove(); + return true; + } + } + } + return false; + } + +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java index b8bc41fb..8d376248 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java @@ -11,6 +11,8 @@ 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.api.WorldPurger; import com.onarandombox.MultiverseCore.commands.EnvironmentCommand; import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent; import org.bukkit.World; @@ -41,7 +43,7 @@ import java.util.logging.Level; */ public class WorldManager implements MVWorldManager { private MultiverseCore plugin; - private PurgeWorlds worldPurger; + private WorldPurger worldPurger; private Map worlds; private List unloadedWorlds; private FileConfiguration configWorlds = null; @@ -52,7 +54,7 @@ public class WorldManager implements MVWorldManager { this.plugin = core; this.worlds = new HashMap(); this.unloadedWorlds = new ArrayList(); - this.worldPurger = new PurgeWorlds(this.plugin); + this.worldPurger = new SimpleWorldPurger(plugin); } /** @@ -139,7 +141,7 @@ public class WorldManager implements MVWorldManager { MultiverseWorld mvworld = new MVWorld(world, this.configWorlds, this.plugin, this.plugin.getServer().getWorld(name).getSeed(), generator, useSpawnAdjust); - this.worldPurger.purgeWorld(null, mvworld); + this.worldPurger.purgeWorld(mvworld); this.worlds.put(name, mvworld); if (this.unloadedWorlds.contains(name)) { this.unloadedWorlds.remove(name); @@ -371,7 +373,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); @@ -575,10 +577,20 @@ public class WorldManager implements MVWorldManager { /** * {@inheritDoc} + * @deprecated This is deprecated! */ @Override + @Deprecated public PurgeWorlds getWorldPurger() { - return this.worldPurger; + return new PurgeWorlds(plugin); + } + + /** + * {@inheritDoc} + */ + @Override + public WorldPurger getTheWorldPurger() { + return worldPurger; } /**