diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 6c3a7c60..00000000 --- a/.gitmodules +++ /dev/null @@ -1,7 +0,0 @@ -[submodule "lib/allpay"] - path = lib/allpay - url = git://github.com/FernFerret/AllPay.git -[submodule "lib/commandhandler"] - path = lib/commandhandler - url = git://github.com/PneumatiCraft/CommandHandler.git - branch = notrie diff --git a/README.md b/README.md index d1c7b96d..41d090ee 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@ Building ======== -Update the submodules after you clone and before you build with maven. +Simply build the source with maven: -``` -$ git submodule update --init --recursive -$ mvn install -``` + $ mvn install More details are available on the [build instructions wiki page](https://github.com/Multiverse/Multiverse-Core/wiki/Building). diff --git a/config/mv_checks.xml b/config/mv_checks.xml index 30f45212..73be9841 100644 --- a/config/mv_checks.xml +++ b/config/mv_checks.xml @@ -13,9 +13,7 @@ - - - + diff --git a/lib/allpay b/lib/allpay deleted file mode 160000 index 7abba1f0..00000000 --- a/lib/allpay +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7abba1f0040862e9fabdafb3d44c6cf0b914cc7c diff --git a/lib/commandhandler b/lib/commandhandler deleted file mode 160000 index 46a3ab6e..00000000 --- a/lib/commandhandler +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 46a3ab6e4e444cd84f836aa6d36ed02cf6347454 diff --git a/pom.xml b/pom.xml index 47364a2d..a4ef10c4 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,10 @@ onarandombox http://repo.onarandombox.com/content/groups/public + + Bukkit Official + http://repo.bukkit.org/content/repositories/public + @@ -63,28 +67,6 @@ 1.6 - - - org.codehaus.mojo - build-helper-maven-plugin - 1.7 - - - add-wsdl-source - generate-sources - - add-source - - - - ${project.basedir}/lib/allpay/src/main/java - ${project.basedir}/lib/commandhandler/src - ${project.basedir}/lib/commandhandler/lib/ShellParser/src - - - - - com.google.code.maven-replacer-plugin maven-replacer-plugin @@ -154,6 +136,42 @@ ${project.basedir}/config/mv_checks.xml + + org.apache.maven.plugins + maven-shade-plugin + 1.5 + + + package + + shade + + + + + me.main__.util:SerializationConfig + com.fernferret.allpay:AllPay + com.pneumaticraft.commandhandler:CommandHandler + + + + + com.fernferret.allpay + com.fernferret.allpay.multiverse + + + me.main__.util + me.main__.util.multiverse + + + com.pneumaticraft.commandhandler + com.pneumaticraft.commandhandler.multiverse + + + + + + @@ -162,7 +180,7 @@ org.bukkit bukkit - 1.1-R1-SNAPSHOT + 1.1-R3 jar compile @@ -174,69 +192,33 @@ dev-SNAPSHOT - + - cosine.boseconomy - BOSEconomy - 0.6.2 + me.main__.util + SerializationConfig + 1.1 jar compile - + + - fr.crafter.tickleman.RealShop - RealShop - 0.63 + com.fernferret.allpay + AllPay + 6 jar compile - + + - com.iCo6 - iConomy - 6.0 + com.pneumaticraft.commandhandler + CommandHandler + 6 jar compile - - - com.iConomy - iConomy - 5.0 - jar - compile - - - - com.nijiko.coelho.iConomy - iConomy - 4.65 - jar - compile - - - - com.earth2me.essentials - Essentials - 2.4.2 - jar - compile - - - me.ashtheking.currency - MultiCurrency - 0.09 - jar - compile - - - ca.agnate - EconXP - 1.0.0 - jar - compile - - + junit diff --git a/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java b/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java index a7806c34..ab81d4e0 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MVWorld.java @@ -7,16 +7,16 @@ 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; import com.onarandombox.MultiverseCore.configuration.MVConfigProperty; +import com.onarandombox.MultiverseCore.enums.AllowedPortalType; 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 +33,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; @@ -158,6 +157,8 @@ public class MVWorld implements MultiverseWorld { this.propertyList.put("adjustspawn", fac.getNewProperty("adjustspawn", true, "Sorry, 'adjustspawn' must either be:" + ChatColor.GREEN + " true " + ChatColor.WHITE + "or" + ChatColor.RED + " false" + ChatColor.WHITE + ".")); + this.propertyList.put("portalform", fac.getNewProperty("portalform", AllowedPortalType.ALL, + "Allow portal forming must be NONE, ALL, NETHER or END.")); if (!fixSpawn) { this.setAdjustSpawn(false); } @@ -433,7 +434,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); } /** @@ -513,6 +514,7 @@ public class MVWorld implements MultiverseWorld { return (MVConfigProperty) this.propertyList.get(this.propertyAliases.get(name)); } } catch (ClassCastException e) { + return null; } return null; } @@ -558,6 +560,7 @@ public class MVWorld implements MultiverseWorld { try { if (property.getMethod() == null) { // This property did not have a method. + this.saveConfig(); return true; } Method method = this.getClass().getMethod(property.getMethod()); @@ -572,6 +575,8 @@ public class MVWorld implements MultiverseWorld { return true; } } catch (Exception e) { + // TODO: I don't care about 3 catches, + // TODO: I hate pokemon errors :/ - FernFerret e.printStackTrace(); return false; } @@ -986,8 +991,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 +1004,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 +1013,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 +1023,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!!!"); } @@ -1160,6 +1166,22 @@ public class MVWorld implements MultiverseWorld { return this.type; } + /** + * {@inheritDoc} + */ + @Override + public void allowPortalMaking(AllowedPortalType type) { + this.setKnownProperty("portalform", type.toString(), null); + } + + /** + * {@inheritDoc} + */ + @Override + public AllowedPortalType getAllowedPortals() { + return this.getKnownProperty("portalform", AllowedPortalType.class).getValue(); + } + /** * Used by the active time-property to set the "actual" property. * @return True if the property was successfully set. diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java index 73ecc74e..e9424141 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java @@ -9,10 +9,15 @@ 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.MultiverseCoreConfig; +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; @@ -28,17 +33,14 @@ import com.onarandombox.MultiverseCore.listeners.MVPluginListener; import com.onarandombox.MultiverseCore.listeners.MVWeatherListener; import com.onarandombox.MultiverseCore.localization.MessageProvider; import com.onarandombox.MultiverseCore.localization.MessageProviding; +import com.onarandombox.MultiverseCore.listeners.MVPortalListener; +import com.onarandombox.MultiverseCore.utils.*; import com.onarandombox.MultiverseCore.localization.MultiverseMessage; import com.onarandombox.MultiverseCore.localization.SimpleMessageProvider; -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.pneumaticraft.commandhandler.CommandHandler; + +import me.main__.util.SerializationConfig.SerializationConfig; + import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.command.Command; @@ -66,22 +68,15 @@ import java.util.logging.Logger; * The implementation of the Multiverse-{@link Core}. */ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, MessageProviding { - private static final int PROTOCOL = 12; - // Global Multiverse config variable, states whether or not - // Multiverse should stop other plugins from teleporting players - // to worlds. - // TODO This is REALLY bad style! We have to change this! - // No, I'm NOT going to suppress these warnings because we HAVE TO CHANGE THIS! - public static boolean EnforceAccess; - public static boolean PrefixChat; - public static boolean DisplayPermErrors; - public static boolean TeleportIntercept; - public static boolean FirstSpawnOverride; - public static Map teleportQueue = new HashMap(); - public static int GlobalDebug = 0; + private static final int PROTOCOL = 13; + // TODO: Investigate if this one is really needed to be static. + // Doubt it. -- FernFerret + private static Map teleportQueue = new HashMap(); private AnchorManager anchorManager = new AnchorManager(this); private MessageProvider messageProvider = new SimpleMessageProvider(this); + // TODO please let's make this non-static + private static MultiverseCoreConfiguration config; /** * This method is used to find out who is teleporting a player. @@ -162,8 +157,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag private MVEntityListener entityListener = new MVEntityListener(this); private MVPluginListener pluginListener = new MVPluginListener(this); private MVWeatherListener weatherListener = new MVWeatherListener(this); - - //public UpdateChecker updateCheck; + private MVPortalListener portalListener = new MVPortalListener(this); // HashMap to contain information relating to the Players. private HashMap playerSessions; @@ -172,24 +166,35 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag private int pluginCount; private DestinationFactory destFactory; 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")); @Override public void onLoad() { + // Register our config + SerializationConfig.registerAll(MultiverseCoreConfiguration.class); // Create our DataFolder 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); } /** * {@inheritDoc} + * @deprecated This is deprecated. */ @Override + @Deprecated public FileConfiguration getMVConfiguration() { return this.multiverseConfig; } @@ -207,12 +212,6 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag */ @Override public void onEnable() { - //this.worldManager = new WorldManager(this); - // Perform initial checks for AllPay - if (!this.validateAllpay() || !this.validateCH()) { - this.getServer().getPluginManager().disablePlugin(this); - return; - } this.messaging = new MVMessaging(); this.banker = new AllPay(this, LOG_TAG + " "); // Output a little snippet to show it's enabled. @@ -260,12 +259,9 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag this.anchorManager.loadAnchors(); // Now set the firstspawnworld (after the worlds are loaded): - // Default as the server.props world. - this.worldManager.setFirstSpawnWorld(this.multiverseConfig.getString("firstspawnworld", getDefaultWorldName())); - // We have to set this one here, if it's not present, we don't know the name of the default world. - // and this one won't be in the defaults yml file. + this.worldManager.setFirstSpawnWorld(config.getFirstSpawnWorld()); try { - this.multiverseConfig.set("firstspawnworld", this.worldManager.getFirstSpawnWorld().getName()); + config.setFirstSpawnWorld(this.worldManager.getFirstSpawnWorld().getName()); } catch (NullPointerException e) { // A test that had no worlds loaded was being run. This should never happen in production } @@ -277,42 +273,6 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag } } - private boolean validateAllpay() { - try { - this.banker = new AllPay(this, "Verify"); - if (this.banker.getVersion() >= ALLPAY_VERSION) { - return true; - } - } catch (Throwable t) { - //TODO: Deal with this. It's bad. - } - LOGGER.info(String.format("%s - Version %s was NOT ENABLED!!!", LOG_TAG, this.getDescription().getVersion())); - LOGGER.info(String.format("%s A plugin that has loaded before %s has an incompatible version of AllPay (an internal library)!", - LOG_TAG, this.getDescription().getName())); - LOGGER.info(String.format("%s The Following Plugins MAY out of date: %s", LOG_TAG, AllPay.pluginsThatUseUs.toString())); - LOGGER.info(String.format("%s This plugin needs AllPay v%f or higher and another plugin has loaded v%f!", - LOG_TAG, ALLPAY_VERSION, this.banker.getVersion())); - return false; - } - - private boolean validateCH() { - try { - this.commandHandler = new CommandHandler(this, null); - if (this.commandHandler.getVersion() >= CH_VERSION) { - return true; - } - } catch (Throwable t) { - //TODO: Deal with this. It's bad. - } - LOGGER.info(String.format("%s - Version %s was NOT ENABLED!!!", LOG_TAG, this.getDescription().getVersion())); - LOGGER.info(String.format("%s A plugin that has loaded before %s has an incompatible version of CommandHandler (an internal library)!", - LOG_TAG, this.getDescription().getName())); - LOGGER.info(String.format("%s Please contact this plugin author!!!", LOG_TAG)); - LOGGER.info(String.format("%s This plugin needs CommandHandler v%f or higher and another plugin has loaded v%f!", - LOG_TAG, CH_VERSION, this.commandHandler.getVersion())); - return false; - } - private void initializeDestinationFactory() { this.destFactory = new DestinationFactory(this); this.destFactory.registerDestinationType(WorldDestination.class, ""); @@ -333,6 +293,8 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag pm.registerEvents(this.entityListener, this); pm.registerEvents(this.pluginListener, this); pm.registerEvents(this.weatherListener, this); + pm.registerEvents(this.portalListener, this); + } /** @@ -344,53 +306,87 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag this.multiverseConfig = YamlConfiguration.loadConfiguration(new File(getDataFolder(), "config.yml")); Configuration coreDefaults = YamlConfiguration.loadConfiguration(this.getClass().getResourceAsStream("/defaults/config.yml")); this.multiverseConfig.setDefaults(coreDefaults); - this.multiverseConfig.options().copyDefaults(true); - this.saveMVConfig(); - this.multiverseConfig = YamlConfiguration.loadConfiguration(new File(getDataFolder(), "config.yml")); + this.multiverseConfig.options().copyDefaults(false); + this.multiverseConfig.options().copyHeader(true); this.worldManager.loadWorldConfig(new File(getDataFolder(), "worlds.yml")); - // Setup the Debug option, we'll default to false because this option will not be in the default config. - GlobalDebug = this.multiverseConfig.getInt("debug", 0); - // Lets cache these values due to the fact that they will be accessed many times. - EnforceAccess = this.multiverseConfig.getBoolean("enforceaccess", false); - PrefixChat = this.multiverseConfig.getBoolean("worldnameprefix", true); - // Should MV Intercept teleports by other plugins? - TeleportIntercept = this.multiverseConfig.getBoolean("teleportintercept", true); - // Should MV do the first spawn stuff? - FirstSpawnOverride = this.multiverseConfig.getBoolean("firstspawnoverride", true); - // Should permissions errors display to users? - DisplayPermErrors = this.multiverseConfig.getBoolean("displaypermerrors", true); + MultiverseCoreConfiguration wantedConfig = null; + try { + wantedConfig = (MultiverseCoreConfiguration) multiverseConfig.get("multiverse-configuration"); + } catch (Exception e) { + // We're just thinking "no risk no fun" and therefore have to catch and forget this exception + } finally { + config = ((wantedConfig == null) ? new MultiverseCoreConfiguration() : wantedConfig); + } - this.messaging.setCooldown(this.multiverseConfig.getInt("messagecooldown", 5000)); // SUPPRESS CHECKSTYLE: MagicNumberCheck - // Update the version of the config! - this.multiverseConfig.set("version", coreDefaults.get("version")); + this.messaging.setCooldown(config.getMessageCooldown()); // Remove old values. this.multiverseConfig.set("enforcegamemodes", null); this.multiverseConfig.set("bedrespawn", null); this.multiverseConfig.set("opfallback", null); + // Old Config Format + this.migrate22Values(); this.saveMVConfigs(); } /** - * Safely return a world name. - * (The tests call this with no worlds loaded) - * - * @return The default world name. + * Thes are the MV config 2.0-2.2 values, + * they should be migrated to the new format. */ - private String getDefaultWorldName() { - if (this.getServer().getWorlds().size() > 0) { - return this.getServer().getWorlds().get(0).getName(); + private void migrate22Values() { + if (this.multiverseConfig.isSet("worldnameprefix")) { + this.log(Level.INFO, "Migrating 'worldnameprefix'..."); + this.config.setPrefixChat(this.multiverseConfig.getBoolean("worldnameprefix")); + this.multiverseConfig.set("worldnameprefix", null); + } + if (this.multiverseConfig.isSet("firstspawnworld")) { + this.log(Level.INFO, "Migrating 'firstspawnworld'..."); + this.config.setFirstSpawnWorld(this.multiverseConfig.getString("firstspawnworld")); + this.multiverseConfig.set("firstspawnworld", null); + } + if (this.multiverseConfig.isSet("enforceaccess")) { + this.log(Level.INFO, "Migrating 'enforceaccess'..."); + this.config.setEnforceAccess(this.multiverseConfig.getBoolean("enforceaccess")); + this.multiverseConfig.set("enforceaccess", null); + } + if (this.multiverseConfig.isSet("displaypermerrors")) { + this.log(Level.INFO, "Migrating 'displaypermerrors'..."); + this.config.setDisplayPermErrors(this.multiverseConfig.getBoolean("displaypermerrors")); + this.multiverseConfig.set("displaypermerrors", null); + } + if (this.multiverseConfig.isSet("teleportintercept")) { + this.log(Level.INFO, "Migrating 'teleportintercept'..."); + this.config.setTeleportIntercept(this.multiverseConfig.getBoolean("teleportintercept")); + this.multiverseConfig.set("teleportintercept", null); + } + if (this.multiverseConfig.isSet("firstspawnoverride")) { + this.log(Level.INFO, "Migrating 'firstspawnoverride'..."); + this.config.setFirstSpawnOverride(this.multiverseConfig.getBoolean("firstspawnoverride")); + this.multiverseConfig.set("firstspawnoverride", null); + } + if (this.multiverseConfig.isSet("messagecooldown")) { + this.log(Level.INFO, "Migrating 'messagecooldown'..."); + this.config.setMessageCooldown(this.multiverseConfig.getInt("messagecooldown")); + this.multiverseConfig.set("messagecooldown", null); + } + if (this.multiverseConfig.isSet("debug")) { + this.log(Level.INFO, "Migrating 'debug'..."); + this.config.setGlobalDebug(this.multiverseConfig.getInt("debug")); + this.multiverseConfig.set("debug", null); + } + if (this.multiverseConfig.isSet("version")) { + this.log(Level.INFO, "Migrating 'version'..."); + this.multiverseConfig.set("version", null); } - return ""; } /** * {@inheritDoc} */ @Override - public MVMessaging getMessaging() { + public MultiverseMessaging getMessaging() { return this.messaging; } @@ -453,17 +449,20 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag if (this.playerSessions.containsKey(player.getName())) { return this.playerSessions.get(player.getName()); } else { - this.playerSessions.put(player.getName(), new MVPlayerSession(player, this.multiverseConfig, this)); + this.playerSessions.put(player.getName(), new MVPlayerSession(player, config)); return this.playerSessions.get(player.getName()); } } /** * {@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); } /** @@ -485,7 +484,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag } ArrayList allArgs = new ArrayList(Arrays.asList(args)); allArgs.add(0, command.getName()); - return this.commandHandler.locateAndRunCommand(sender, allArgs, DisplayPermErrors); + return this.commandHandler.locateAndRunCommand(sender, allArgs, config.getDisplayPermErrors()); } /** @@ -503,13 +502,13 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag * @param msg The message to log. */ public static void staticLog(Level level, String msg) { - if (level == Level.FINE && GlobalDebug >= 1) { + if (level == Level.FINE && config.getGlobalDebug() >= 1) { staticDebugLog(Level.INFO, msg); return; - } else if (level == Level.FINER && GlobalDebug >= 2) { + } else if (level == Level.FINER && config.getGlobalDebug() >= 2) { staticDebugLog(Level.INFO, msg); return; - } else if (level == Level.FINEST && GlobalDebug >= 3) { + } else if (level == Level.FINEST && config.getGlobalDebug() >= 3) { staticDebugLog(Level.INFO, msg); return; } else if (level != Level.FINE && level != Level.FINER && level != Level.FINEST) { @@ -652,7 +651,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag */ 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); } /** @@ -735,6 +734,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag */ public boolean saveMVConfig() { try { + this.multiverseConfig.set("multiverse-configuration", config); this.multiverseConfig.save(new File(getDataFolder(), "config.yml")); return true; } catch (IOException e) { @@ -794,7 +794,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag } 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 +832,69 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core, Messag messageProvider = provider; } + /** + * {@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; + } + + /** + * {@inheritDoc} + */ + @Override + public MultiverseCoreConfig getMVConfig() { + return config; + } + + /** + * This method is currently used by other plugins. + * It will be removed in 2.4 + * @return + */ + @Deprecated + public static MultiverseCoreConfiguration getStaticConfig() { + return config; + } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCoreConfiguration.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCoreConfiguration.java new file mode 100644 index 00000000..6446ba3d --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCoreConfiguration.java @@ -0,0 +1,222 @@ +package com.onarandombox.MultiverseCore; + +import java.util.Map; + +import com.onarandombox.MultiverseCore.api.MultiverseCoreConfig; + +import me.main__.util.SerializationConfig.Property; +import me.main__.util.SerializationConfig.SerializationConfig; + +/** + * Our configuration. + */ +public class MultiverseCoreConfiguration extends SerializationConfig implements MultiverseCoreConfig { + @Property + private boolean enforceaccess; + @Property + private boolean prefixchat; + @Property + private boolean teleportintercept; + @Property + private boolean firstspawnoverride; + @Property + private boolean displaypermerrors; + @Property + private int globaldebug; + @Property + private int messagecooldown; + @Property + private double version; + @Property + private String firstspawnworld; + @Property + private int teleportcooldown; + + public MultiverseCoreConfiguration() { + super(); + } + + public MultiverseCoreConfiguration(Map values) { + super(values); + } + + /** + * {@inheritDoc} + */ + @Override + public void setDefaults() { + // BEGIN CHECKSTYLE-SUPPRESSION: MagicNumberCheck + enforceaccess = false; + prefixchat = true; + teleportintercept = true; + firstspawnoverride = true; + displaypermerrors = true; + globaldebug = 0; + messagecooldown = 5000; + teleportcooldown = 1000; + this.version = 2.9; + // END CHECKSTYLE-SUPPRESSION: MagicNumberCheck + } + + // And here we go: + + /** + * {@inheritDoc} + */ + @Override + public boolean getEnforceAccess() { + return this.enforceaccess; + } + + /** + * {@inheritDoc} + */ + @Override + public void setEnforceAccess(boolean enforceAccess) { + this.enforceaccess = enforceAccess; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean getPrefixChat() { + return this.prefixchat; + } + + /** + * {@inheritDoc} + */ + @Override + public void setPrefixChat(boolean prefixChat) { + this.prefixchat = prefixChat; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean getTeleportIntercept() { + return this.teleportintercept; + } + + /** + * {@inheritDoc} + */ + @Override + public void setTeleportIntercept(boolean teleportIntercept) { + this.teleportintercept = teleportIntercept; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean getFirstSpawnOverride() { + return this.firstspawnoverride; + } + + /** + * {@inheritDoc} + */ + @Override + public void setFirstSpawnOverride(boolean firstSpawnOverride) { + this.firstspawnoverride = firstSpawnOverride; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean getDisplayPermErrors() { + return this.displaypermerrors; + } + + /** + * {@inheritDoc} + */ + @Override + public void setDisplayPermErrors(boolean displayPermErrors) { + this.displaypermerrors = displayPermErrors; + } + + /** + * {@inheritDoc} + */ + @Override + public int getGlobalDebug() { + return this.globaldebug; + } + + /** + * {@inheritDoc} + */ + @Override + public void setGlobalDebug(int globalDebug) { + this.globaldebug = globalDebug; + } + + /** + * {@inheritDoc} + */ + @Override + public int getMessageCooldown() { + return this.messagecooldown; + } + + /** + * {@inheritDoc} + */ + @Override + public void setMessageCooldown(int messageCooldown) { + this.messagecooldown = messageCooldown; + } + + /** + * {@inheritDoc} + */ + @Override + public double getVersion() { + return this.version; + } + + /** + * {@inheritDoc} + */ + @Override + public void setVersion(int version) { + this.version = version; + } + + /** + * {@inheritDoc} + */ + @Override + public String getFirstSpawnWorld() { + return this.firstspawnworld; + } + + /** + * {@inheritDoc} + */ + @Override + public void setFirstSpawnWorld(String firstSpawnWorld) { + this.firstspawnworld = firstSpawnWorld; + } + + /** + * {@inheritDoc} + */ + @Override + public int getTeleportCooldown() { + return this.teleportcooldown; + } + + /** + * {@inheritDoc} + */ + @Override + public void setTeleportCooldown(int teleportCooldown) { + this.teleportcooldown = teleportCooldown; + } +} 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..01c684d0 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java @@ -26,7 +26,9 @@ public interface Core { * Gets the Multiverse config file. * * @return The Multiverse config file. + * @deprecated Don't modify the config-file manually! */ + @Deprecated FileConfiguration getMVConfiguration(); /** @@ -46,9 +48,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 +68,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 +168,58 @@ 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); + + /** + * Gets the {@link MultiverseCoreConfig}. + * @return The configuration. + */ + MultiverseCoreConfig getMVConfig(); } 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..e246c8da --- /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); +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java index 40300ef0..5492b77d 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; @@ -28,31 +30,35 @@ public interface MVWorldManager { /** * Add a new World to the Multiverse Setup. * - * @param name World Name - * @param env Environment Type - * @param seedString The seed in the form of a string. - * If the seed is a Long, - * it will be interpreted as such. - * @param type The Type of the world to be made. - * @param generator The Custom generator plugin to use. + * @param name World Name + * @param env Environment Type + * @param seedString The seed in the form of a string. + * If the seed is a Long, + * it will be interpreted as such. + * @param type The Type of the world to be made. + * @param generateStructures If true, this world will get NPC villages. + * @param generator The Custom generator plugin to use. * @return True if the world is added, false if not. */ - boolean addWorld(String name, Environment env, String seedString, WorldType type, String generator); + boolean addWorld(String name, Environment env, String seedString, WorldType type, boolean generateStructures, + String generator); /** * Add a new World to the Multiverse Setup. * - * @param name World Name - * @param env Environment Type - * @param seedString The seed in the form of a string. - * If the seed is a Long, - * it will be interpreted as such. - * @param type The Type of the world to be made. - * @param generator The Custom generator plugin to use. + * @param name World Name + * @param env Environment Type + * @param seedString The seed in the form of a string. + * If the seed is a Long, + * it will be interpreted as such. + * @param type The Type of the world to be made. + * @param generateStructures If true, this world will get NPC villages. + * @param generator The Custom generator plugin to use. * @param useSpawnAdjust If true, multiverse will search for a safe spawn. If not, It will not modify the level.dat. * @return True if the world is added, false if not. */ - boolean addWorld(String name, Environment env, String seedString, WorldType type, String generator, boolean useSpawnAdjust); + boolean addWorld(String name, Environment env, String seedString, WorldType type, boolean generateStructures, + String generator, boolean useSpawnAdjust); /** * Remove the world from the Multiverse list, from the @@ -168,9 +174,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/MultiverseCoreConfig.java b/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseCoreConfig.java new file mode 100644 index 00000000..25f6fad4 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseCoreConfig.java @@ -0,0 +1,136 @@ +package com.onarandombox.MultiverseCore.api; + +import org.bukkit.configuration.serialization.ConfigurationSerializable; + +/** + * The configuration of MultiverseCore. + */ +public interface MultiverseCoreConfig extends ConfigurationSerializable { + /** + * Sets a property using a {@link String}. + * @param property The name of the property. + * @param value The value. + * @return True on success, false if the operation failed. + */ + boolean setProperty(String property, String value); + + /** + * Sets portalCooldown. + * @param portalCooldown The new value. + */ + void setTeleportCooldown(int portalCooldown); + + /** + * Gets portalCooldown. + * @return portalCooldown. + */ + int getTeleportCooldown(); + + /** + * Sets firstSpawnWorld. + * @param firstSpawnWorld The new value. + */ + void setFirstSpawnWorld(String firstSpawnWorld); + + /** + * Gets firstSpawnWorld. + * @return firstSpawnWorld. + */ + String getFirstSpawnWorld(); + + /** + * Sets version. + * @param version The new value. + */ + void setVersion(int version); + + /** + * Gets version. + * @return version. + */ + double getVersion(); + + /** + * Sets messageCooldown. + * @param messageCooldown The new value. + */ + void setMessageCooldown(int messageCooldown); + + /** + * Gets messageCooldown. + * @return messageCooldown. + */ + int getMessageCooldown(); + + /** + * Sets globalDebug. + * @param globalDebug The new value. + */ + void setGlobalDebug(int globalDebug); + + /** + * Gets globalDebug. + * @return globalDebug. + */ + int getGlobalDebug(); + + /** + * Sets displayPermErrors. + * @param displayPermErrors The new value. + */ + void setDisplayPermErrors(boolean displayPermErrors); + + /** + * Gets displayPermErrors. + * @return displayPermErrors. + */ + boolean getDisplayPermErrors(); + + /** + * Sets firstSpawnOverride. + * @param firstSpawnOverride The new value. + */ + void setFirstSpawnOverride(boolean firstSpawnOverride); + + /** + * Gets firstSpawnOverride. + * @return firstSpawnOverride. + */ + boolean getFirstSpawnOverride(); + + /** + * Sets teleportIntercept. + * @param teleportIntercept The new value. + */ + void setTeleportIntercept(boolean teleportIntercept); + + /** + * Gets teleportIntercept. + * @return teleportIntercept. + */ + boolean getTeleportIntercept(); + + /** + * Sets prefixChat. + * @param prefixChat The new value. + */ + void setPrefixChat(boolean prefixChat); + + /** + * Gets prefixChat. + * @return prefixChat. + */ + boolean getPrefixChat(); + + /** + * Sets enforceAccess. + * @param enforceAccess The new value. + */ + void setEnforceAccess(boolean enforceAccess); + + /** + * Gets enforceAccess. + * @return enforceAccess. + */ + boolean getEnforceAccess(); +} 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/MultiverseWorld.java b/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseWorld.java index fb473ce8..5bd1eb11 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseWorld.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MultiverseWorld.java @@ -8,6 +8,7 @@ package com.onarandombox.MultiverseCore.api; import com.onarandombox.MultiverseCore.configuration.MVConfigProperty; +import com.onarandombox.MultiverseCore.enums.AllowedPortalType; import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException; import org.bukkit.ChatColor; @@ -573,4 +574,18 @@ public interface MultiverseWorld { * @return The Type of this world. */ WorldType getWorldType(); + + /** + * Sets The types of portals that are allowed in this world. + * + * @param type The type of portals allowed in this world. + */ + void allowPortalMaking(AllowedPortalType type); + + /** + * Gets which type(s) of portals are allowed to be constructed in this world. + * + * @return The type of portals that are allowed. + */ + AllowedPortalType getAllowedPortals(); } 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/AnchorCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/AnchorCommand.java index 232aabc0..731e6f95 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/AnchorCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/AnchorCommand.java @@ -85,6 +85,8 @@ public class AnchorCommand extends PaginatedCoreCommand { if (filterObject.getPage() > totalPages) { filterObject.setPage(totalPages); + } else if (filterObject.getPage() < 1) { + filterObject.setPage(1); } sender.sendMessage(ChatColor.AQUA + " Page " + filterObject.getPage() + " of " + totalPages); @@ -98,7 +100,11 @@ public class AnchorCommand extends PaginatedCoreCommand { this.showList(sender, args); return; } - if (args.size() == 2) { + if (args.size() == 1 && (this.getPageAndFilter(args).getPage() != 1 || args.get(0).equals("1"))) { + this.showList(sender, args); + return; + } + if (args.size() == 2 && args.get(1).equalsIgnoreCase("-d")) { if (this.plugin.getAnchorManager().deleteAnchor(args.get(0))) { sender.sendMessage("Anchor '" + args.get(0) + "' was successfully " + ChatColor.RED + "deleted!"); } else { @@ -111,6 +117,7 @@ public class AnchorCommand extends PaginatedCoreCommand { sender.sendMessage("You must be a player to create Anchors."); return; } + Player player = (Player) sender; if (this.plugin.getAnchorManager().saveAnchorLocation(args.get(0), player.getLocation())) { sender.sendMessage("Anchor '" + args.get(0) + "' was successfully " + ChatColor.GREEN + "created!"); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java index 3b48e1ce..6290183a 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ConfigCommand.java @@ -8,12 +8,12 @@ package com.onarandombox.MultiverseCore.commands; import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.enums.ConfigProperty; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.permissions.PermissionDefault; import java.util.List; +import java.util.Map; /** * Allows you to set Global MV Variables. @@ -28,7 +28,6 @@ public class ConfigCommand extends MultiverseCommand { this.addKey("mvconfig"); this.addKey("mv conf"); this.addKey("mvconf"); - this.addCommandExample("All values: " + ConfigProperty.getAllValues()); this.addCommandExample("/mv config show"); this.addCommandExample("/mv config " + ChatColor.GREEN + "debug" + ChatColor.AQUA + " 3"); this.addCommandExample("/mv config " + ChatColor.GREEN + "enforceaccess" + ChatColor.AQUA + " false"); @@ -38,55 +37,31 @@ public class ConfigCommand extends MultiverseCommand { @Override public void runCommand(CommandSender sender, List args) { if (args.size() <= 1) { - String[] allProps = ConfigProperty.getAllValues().split(" "); - String currentvals = ""; - for (String prop : allProps) { - currentvals += ChatColor.GREEN; - currentvals += prop; - currentvals += ChatColor.WHITE; - currentvals += " = "; - currentvals += ChatColor.GOLD; - currentvals += this.plugin.getMVConfiguration().get(prop, "NOT SET"); - currentvals += ChatColor.WHITE; - currentvals += ", "; + StringBuilder builder = new StringBuilder(); + Map serializedConfig = this.plugin.getMVConfig().serialize(); + for (Map.Entry entry : serializedConfig.entrySet()) { + builder.append(ChatColor.GREEN); + builder.append(entry.getKey()); + builder.append(ChatColor.WHITE).append(" = ").append(ChatColor.GOLD); + builder.append(entry.getValue().toString()); + builder.append(ChatColor.WHITE).append(", "); } - sender.sendMessage(currentvals.substring(0, currentvals.length() - 2)); + String message = builder.toString(); + message = message.substring(0, message.length() - 2); + sender.sendMessage(message); return; } + if (!this.plugin.getMVConfig().setProperty(args.get(0).toLowerCase(), args.get(1))) { + sender.sendMessage(String.format("%sSetting '%s' to '%s' failed!", ChatColor.RED, args.get(0).toLowerCase(), args.get(1))); + return; + } + + // special rule if (args.get(0).equalsIgnoreCase("firstspawnworld")) { - this.plugin.getMVConfiguration().set(args.get(0).toLowerCase(), args.get(1)); // Don't forget to set the world! this.plugin.getMVWorldManager().setFirstSpawnWorld(args.get(1)); - } else if (args.get(0).equalsIgnoreCase("messagecooldown") || args.get(0).equalsIgnoreCase("teleportcooldown") - || args.get(0).equalsIgnoreCase("debug")) { - try { - this.plugin.getMVConfiguration().set(args.get(0).toLowerCase(), Integer.parseInt(args.get(1))); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Sorry, " + ChatColor.AQUA + args.get(0) + ChatColor.WHITE + " must be an integer!"); - return; - } - } else { - ConfigProperty property = null; - try { - property = ConfigProperty.valueOf(args.get(0).toLowerCase()); - } catch (IllegalArgumentException e) { - sender.sendMessage(ChatColor.RED + "Sorry, " + ChatColor.AQUA - + args.get(0) + ChatColor.WHITE + " you can't set " + ChatColor.AQUA + args.get(0)); - sender.sendMessage(ChatColor.GREEN + "Valid values are:"); - sender.sendMessage(ConfigProperty.getAllValues()); - return; - } - - if (property != null) { - try { - this.plugin.getMVConfiguration().set(args.get(0).toLowerCase(), Boolean.parseBoolean(args.get(1))); - } catch (Exception e) { - sender.sendMessage(ChatColor.RED + "Sorry, " + ChatColor.AQUA + args.get(0) + ChatColor.WHITE + " must be true or false!"); - return; - } - - } } + if (this.plugin.saveMVConfigs()) { sender.sendMessage(ChatColor.GREEN + "SUCCESS!" + ChatColor.WHITE + " Values were updated successfully!"); this.plugin.loadConfigs(); 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/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java index ffc3533d..d820626b 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java @@ -29,8 +29,9 @@ public class CreateCommand extends MultiverseCommand { public CreateCommand(MultiverseCore plugin) { super(plugin); this.setName("Create World"); - this.setCommandUsage("/mv create" + ChatColor.GREEN + " {NAME} {ENV}" + ChatColor.GOLD + " -s [SEED] -g [GENERATOR[:ID]] -t [WORLDTYPE] [-n]"); - this.setArgRange(2, 9); // SUPPRESS CHECKSTYLE: MagicNumberCheck + this.setCommandUsage(String.format("/mv create %s{NAME} {ENV} %s-s [SEED] -g [GENERATOR[:ID]] -t [WORLDTYPE] [-n] -a [true|false]", + ChatColor.GREEN, ChatColor.GOLD)); + this.setArgRange(2, 11); // SUPPRESS CHECKSTYLE: MagicNumberCheck this.addKey("mvcreate"); this.addKey("mvc"); this.addKey("mv create"); @@ -51,6 +52,11 @@ public class CreateCommand extends MultiverseCommand { String env = args.get(1); String seed = CommandHandler.getFlag("-s", args); String generator = CommandHandler.getFlag("-g", args); + boolean allowStructures = true; + String structureString = CommandHandler.getFlag("-a", args); + if (structureString != null) { + allowStructures = Boolean.parseBoolean(structureString); + } String typeString = CommandHandler.getFlag("-t", args); boolean useSpawnAdjust = true; for (String s : args) { @@ -58,6 +64,7 @@ public class CreateCommand extends MultiverseCommand { useSpawnAdjust = false; } } + if (worldFile.exists() || this.worldManager.isMVWorld(worldName)) { sender.sendMessage(ChatColor.RED + "A Folder/World already exists with this name!"); sender.sendMessage(ChatColor.RED + "If you are confident it is a world you can import with /mvimport"); @@ -84,7 +91,7 @@ public class CreateCommand extends MultiverseCommand { Command.broadcastCommandMessage(sender, "Starting creation of world '" + worldName + "'..."); - if (this.worldManager.addWorld(worldName, environment, seed, type, generator, useSpawnAdjust)) { + if (this.worldManager.addWorld(worldName, environment, seed, type, allowStructures, generator, useSpawnAdjust)) { Command.broadcastCommandMessage(sender, "Complete!"); } else { Command.broadcastCommandMessage(sender, "FAILED."); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/DebugCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/DebugCommand.java index 83f7cdd5..53fc01b5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/DebugCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/DebugCommand.java @@ -36,14 +36,14 @@ public class DebugCommand extends MultiverseCommand { public void runCommand(CommandSender sender, List args) { if (args.size() == 1) { if (args.get(0).equalsIgnoreCase("off")) { - MultiverseCore.GlobalDebug = 0; + plugin.getMVConfig().setGlobalDebug(0); } else { try { int debugLevel = Integer.parseInt(args.get(0)); if (debugLevel > 3 || debugLevel < 0) { throw new NumberFormatException(); } - MultiverseCore.GlobalDebug = debugLevel; + plugin.getMVConfig().setGlobalDebug(debugLevel); } catch (NumberFormatException e) { sender.sendMessage(ChatColor.RED + "Error" + ChatColor.WHITE + " setting debug level. Please use a number 0-3 " + ChatColor.AQUA + "(3 being many many messages!)"); @@ -55,10 +55,10 @@ public class DebugCommand extends MultiverseCommand { } private void displayDebugMode(CommandSender sender) { - if (MultiverseCore.GlobalDebug == 0) { + if (plugin.getMVConfig().getGlobalDebug() == 0) { sender.sendMessage("Multiverse Debug mode is " + ChatColor.RED + "OFF"); } else { - sender.sendMessage("Multiverse Debug mode is " + ChatColor.GREEN + MultiverseCore.GlobalDebug); + sender.sendMessage("Multiverse Debug mode is " + ChatColor.GREEN + plugin.getMVConfig().getGlobalDebug()); this.plugin.log(Level.FINE, "Multiverse Debug ENABLED"); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/EnvironmentCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/EnvironmentCommand.java index 4531b39e..6be7f7fe 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/EnvironmentCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/EnvironmentCommand.java @@ -91,6 +91,7 @@ public class EnvironmentCommand extends MultiverseCommand { * @return The environment as {@link org.bukkit.World.Environment} */ public static World.Environment getEnvFromString(String env) { + env = env.toUpperCase(); // Don't reference the enum directly as there aren't that many, and we can be more forgiving to users this way if (env.equalsIgnoreCase("HELL") || env.equalsIgnoreCase("NETHER")) env = "NETHER"; diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java index bbb1edbc..90084e71 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java @@ -33,8 +33,8 @@ public class ImportCommand extends MultiverseCommand { public ImportCommand(MultiverseCore plugin) { super(plugin); this.setName("Import World"); - this.setCommandUsage("/mv import" + ChatColor.GREEN + " {NAME} {ENV} " + ChatColor.GOLD + " -g [GENERATOR[:ID]] [-n] -t [TYPE]"); - this.setArgRange(2, 5); // SUPPRESS CHECKSTYLE: MagicNumberCheck + this.setCommandUsage("/mv import" + ChatColor.GREEN + " {NAME} {ENV} " + ChatColor.GOLD + " -g [GENERATOR[:ID]] [-n] -t [TYPE] -a [true|false]"); + this.setArgRange(1, 9); // SUPPRESS CHECKSTYLE: MagicNumberCheck this.addKey("mvimport"); this.addKey("mvim"); this.addKey("mv import"); @@ -129,6 +129,11 @@ public class ImportCommand extends MultiverseCommand { String generator = CommandHandler.getFlag("-g", args); String typeString = CommandHandler.getFlag("-t", args); + boolean allowStructures = true; + String structureString = CommandHandler.getFlag("-a", args); + if (structureString != null) { + allowStructures = Boolean.parseBoolean(structureString); + } boolean useSpawnAdjust = true; for (String s : args) { if (s.equalsIgnoreCase("-n")) { @@ -157,7 +162,7 @@ public class ImportCommand extends MultiverseCommand { if (worldFile.exists() && env != null) { Command.broadcastCommandMessage(sender, String.format("Starting import of world '%s'...", worldName)); - if (this.worldManager.addWorld(worldName, environment, null, type, generator, useSpawnAdjust)) + if (this.worldManager.addWorld(worldName, environment, null, type, allowStructures, generator, useSpawnAdjust)) Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Complete!"); else Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed!"); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/InfoCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/InfoCommand.java index dffbd882..e7ad09bf 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; @@ -62,9 +61,13 @@ public class InfoCommand extends MultiverseCommand { return; } } else if (args.size() == 1) { - if (this.worldManager.getMVWorld(args.get(0)) != null) { + if (this.worldManager.isMVWorld(args.get(0))) { // then we have a world! worldName = args.get(0); + } else if(this.worldManager.getUnloadedWorlds().contains(args.get(0))){ + sender.sendMessage("That world exists, but it is unloaded!"); + sender.sendMessage(String.format("You can load it with: %s/mv load %s", ChatColor.AQUA, args.get(0))); + return; } else { if (sender instanceof Player) { Player p = (Player) sender; @@ -94,8 +97,11 @@ public class InfoCommand extends MultiverseCommand { p = (Player) sender; } showPage(pageNum, sender, this.buildEntireCommand(this.worldManager.getMVWorld(worldName), p)); + } else if (this.worldManager.getUnloadedWorlds().contains(worldName)) { + sender.sendMessage("That world exists, but it is unloaded!"); + sender.sendMessage(String.format("You can load it with: %s/mv load %s", ChatColor.AQUA, worldName)); } else if (this.plugin.getServer().getWorld(worldName) != null) { - sender.sendMessage("That world exists, but multiverse does not know about it!"); + sender.sendMessage("That world exists, but Multiverse does not know about it!"); sender.sendMessage("You can import it with" + ChatColor.AQUA + "/mv import " + ChatColor.GREEN + worldName + ChatColor.LIGHT_PURPLE + "{ENV}"); sender.sendMessage("For available environments type " + ChatColor.GREEN + "/mv env"); } @@ -110,10 +116,11 @@ public class InfoCommand extends MultiverseCommand { message.add(new FancyMessage("World Name: ", world.getName(), colors)); message.add(new FancyMessage("World Alias: ", world.getColoredWorldString(), colors)); message.add(new FancyMessage("Game Mode: ", world.getGameMode().toString(), colors)); - message.add(new FancyMessage("World Type: ", world.getWorldType().toString(), colors)); + message.add(new FancyMessage("Difficulty: ", world.getDifficulty().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: ", @@ -136,7 +143,8 @@ public class InfoCommand extends MultiverseCommand { // Page 2 message = new ArrayList(); message.add(new FancyHeader("More World Settings", colors)); - message.add(new FancyMessage("Difficulty: ", world.getDifficulty().toString(), colors)); + message.add(new FancyMessage("World Type: ", world.getWorldType().toString(), colors)); + message.add(new FancyMessage("Structures: ", world.getCBWorld().canGenerateStructures() + "", colors)); message.add(new FancyMessage("Weather: ", world.isWeatherEnabled() + "", colors)); message.add(new FancyMessage("Players will get hungry: ", world.getHunger() + "", colors)); message.add(new FancyMessage("Keep spawn in memory: ", world.isKeepingSpawnInMemory() + "", colors)); diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java index 5c822fb9..0c584d19 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ListCommand.java @@ -57,14 +57,16 @@ public class ListCommand extends PaginatedCoreCommand { } else if (env == Environment.THE_END) { color = ChatColor.AQUA; } - String outputCache = world.getColoredWorldString() + ChatColor.WHITE + " - " + color + world.getEnvironment(); + StringBuilder builder = new StringBuilder(); + builder.append(world.getColoredWorldString()).append(ChatColor.WHITE); + builder.append(" - ").append(color).append(world.getEnvironment()); if (world.isHidden()) { - if (p == null || p.hasPermission("multiverse.core.modify")) { + if (p == null || this.plugin.getMVPerms().hasPermission(p, "multiverse.core.modify", true)) { // Prefix hidden worlds with an "[H]" - worldList.add(ChatColor.GRAY + "[H]" + outputCache); + worldList.add(ChatColor.GRAY + "[H]" + builder.toString()); } } else { - worldList.add(outputCache); + worldList.add(builder.toString()); } } for (String name : this.plugin.getMVWorldManager().getUnloadedWorlds()) { 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..b20f7e73 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); } @@ -111,7 +110,7 @@ public class TeleportCommand extends MultiverseCommand { return; } - if (MultiverseCore.EnforceAccess && teleporter != null && !this.plugin.getMVPerms().canEnterDestination(teleporter, d)) { + if (plugin.getMVConfig().getEnforceAccess() && teleporter != null && !this.plugin.getMVPerms().canEnterDestination(teleporter, d)) { if (teleportee.equals(teleporter)) { teleporter.sendMessage("Doesn't look like you're allowed to go " + ChatColor.RED + "there..."); } else { @@ -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/commands/VersionCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/VersionCommand.java index db878b80..28fb318f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/VersionCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/VersionCommand.java @@ -53,16 +53,16 @@ public class VersionCommand extends MultiverseCommand { buffer.append("[Multiverse-Core] Economy being used: ").append(this.plugin.getBank().getEconUsed()).append('\n'); buffer.append("[Multiverse-Core] Permissions Plugin: ").append(this.plugin.getMVPerms().getType()).append('\n'); buffer.append("[Multiverse-Core] Dumping Config Values: (version ") - .append(this.plugin.getMVConfiguration().getDouble("version", -1)).append(")").append('\n'); - buffer.append("[Multiverse-Core] messagecooldown: ").append(this.plugin.getMessaging().getCooldown()).append('\n'); - buffer.append("[Multiverse-Core] teleportcooldown: ").append("Not yet IMPLEMENTED").append('\n'); - buffer.append("[Multiverse-Core] worldnameprefix: ").append(MultiverseCore.PrefixChat).append('\n'); - buffer.append("[Multiverse-Core] enforceaccess: ").append(MultiverseCore.EnforceAccess).append('\n'); - buffer.append("[Multiverse-Core] displaypermerrors: ").append(MultiverseCore.DisplayPermErrors).append('\n'); - buffer.append("[Multiverse-Core] teleportintercept: ").append(MultiverseCore.TeleportIntercept).append('\n'); - buffer.append("[Multiverse-Core] firstspawnoverride: ").append(MultiverseCore.FirstSpawnOverride).append('\n'); - buffer.append("[Multiverse-Core] firstspawnworld: ").append(this.plugin.getMVConfiguration().getString("firstspawnworld", "NOT SET")).append('\n'); - buffer.append("[Multiverse-Core] debug: ").append(MultiverseCore.GlobalDebug).append('\n'); + .append(this.plugin.getMVConfig().getVersion()).append(")").append('\n'); + buffer.append("[Multiverse-Core] messagecooldown: ").append(plugin.getMessaging().getCooldown()).append('\n'); + buffer.append("[Multiverse-Core] teleportcooldown: ").append(plugin.getMVConfig().getTeleportCooldown()).append('\n'); + buffer.append("[Multiverse-Core] worldnameprefix: ").append(plugin.getMVConfig().getPrefixChat()).append('\n'); + buffer.append("[Multiverse-Core] enforceaccess: ").append(plugin.getMVConfig().getEnforceAccess()).append('\n'); + buffer.append("[Multiverse-Core] displaypermerrors: ").append(plugin.getMVConfig().getDisplayPermErrors()).append('\n'); + buffer.append("[Multiverse-Core] teleportintercept: ").append(plugin.getMVConfig().getTeleportIntercept()).append('\n'); + buffer.append("[Multiverse-Core] firstspawnoverride: ").append(plugin.getMVConfig().getFirstSpawnOverride()).append('\n'); + buffer.append("[Multiverse-Core] firstspawnworld: ").append(plugin.getMVConfig().getFirstSpawnWorld()).append('\n'); + buffer.append("[Multiverse-Core] debug: ").append(plugin.getMVConfig().getGlobalDebug()).append('\n'); buffer.append("[Multiverse-Core] Special Code: FRN002").append('\n'); MVVersionEvent versionEvent = new MVVersionEvent(buffer.toString()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/configuration/ConfigPropertyFactory.java b/src/main/java/com/onarandombox/MultiverseCore/configuration/ConfigPropertyFactory.java index 76d22efd..cb409484 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/configuration/ConfigPropertyFactory.java +++ b/src/main/java/com/onarandombox/MultiverseCore/configuration/ConfigPropertyFactory.java @@ -7,6 +7,7 @@ package com.onarandombox.MultiverseCore.configuration; +import com.onarandombox.MultiverseCore.enums.AllowedPortalType; import com.onarandombox.MultiverseCore.enums.EnglishChatColor; import org.bukkit.Difficulty; import org.bukkit.GameMode; @@ -233,9 +234,9 @@ public class ConfigPropertyFactory { return new GameModeConfigProperty(this.section, name, defaultValue, node, help); } - // GameMode + // Location /** - * Constructs a new ConfigProperty. + * Constructs a new LocationConfigProperty. * * @param name The name of this ConfigProperty. * @param defaultValue The default-value. @@ -273,6 +274,19 @@ public class ConfigPropertyFactory { return new LocationConfigProperty(this.section, name, defaultValue, node, help, method); } + // GameMode + /** + * Constructs a new ConfigProperty. + * + * @param name The name of this ConfigProperty. + * @param defaultValue The default-value. + * @param help The text that's displayed when a user failed to set the property. + * @return The ConfigProperty. + */ + public PortalTypeConfigProperty getNewProperty(String name, AllowedPortalType defaultValue, String help) { + return new PortalTypeConfigProperty(this.section, name, defaultValue, help); + } + /** * Constructs a new ActiveStringConfigProperty * 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/configuration/PortalTypeConfigProperty.java b/src/main/java/com/onarandombox/MultiverseCore/configuration/PortalTypeConfigProperty.java new file mode 100644 index 00000000..685a8101 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/configuration/PortalTypeConfigProperty.java @@ -0,0 +1,97 @@ +/****************************************************************************** + * Multiverse 2 Copyright (c) the Multiverse Team 2012. * + * 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.configuration; + +import com.onarandombox.MultiverseCore.enums.AllowedPortalType; +import org.bukkit.configuration.ConfigurationSection; + +/** + * A {@link AllowedPortalType} config-property. + */ +public class PortalTypeConfigProperty implements MVConfigProperty { + private String name; + private AllowedPortalType value; + private String configNode; + private ConfigurationSection section; + private String help; + + public PortalTypeConfigProperty(ConfigurationSection section, String name, AllowedPortalType defaultValue, String help) { + this(section, name, defaultValue, name, help); + } + + public PortalTypeConfigProperty(ConfigurationSection section, String name, AllowedPortalType defaultValue, String configNode, String help) { + this.name = name; + this.configNode = configNode; + this.section = section; + this.help = help; + this.value = defaultValue; + this.parseValue(this.section.getString(this.configNode, defaultValue.toString())); + } + + /** + * {@inheritDoc} + */ + @Override + public String getName() { + return this.name; + } + + /** + * {@inheritDoc} + */ + @Override + public AllowedPortalType getValue() { + return this.value; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean setValue(AllowedPortalType value) { + if (value == null) { + return false; + } + this.value = value; + this.section.set(configNode, this.value.toString()); + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean parseValue(String value) { + try { + return this.setValue(AllowedPortalType.valueOf(value.toUpperCase())); + } catch (Exception e) { + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public String getConfigNode() { + return this.configNode; + } + + /** + * {@inheritDoc} + */ + @Override + public String getHelp() { + return this.help; + } + + @Override + public String toString() { + return value.toString(); + } +} 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/enums/AllowedPortalType.java b/src/main/java/com/onarandombox/MultiverseCore/enums/AllowedPortalType.java new file mode 100644 index 00000000..cadfb1bd --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/enums/AllowedPortalType.java @@ -0,0 +1,46 @@ +/****************************************************************************** + * Multiverse 2 Copyright (c) the Multiverse Team 2012. * + * 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.enums; + +import org.bukkit.PortalType; + +/** + * Custom enum that adds all/none for allowing portal creation. + */ +public enum AllowedPortalType { + /** + * No portals are allowed. + */ + NONE(PortalType.CUSTOM), + /** + * All portal types are allowed. + */ + ALL(PortalType.CUSTOM), + /** + * Only Nether style portals are allowed. + */ + NETHER(PortalType.NETHER), + /** + * Only Ender style portals are allowed. + */ + END(PortalType.ENDER); + + private PortalType type; + + AllowedPortalType(PortalType type) { + this.type = type; + } + + /** + * Gets the text. + * @return The text. + */ + public PortalType getActualPortalType() { + return this.type; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/enums/ConfigProperty.java b/src/main/java/com/onarandombox/MultiverseCore/enums/ConfigProperty.java deleted file mode 100644 index 6d11c9ab..00000000 --- a/src/main/java/com/onarandombox/MultiverseCore/enums/ConfigProperty.java +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * 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.enums; - -/** - * An enum containing all config-properties that can be set. - */ -public enum ConfigProperty { - /** - * How long to leave in between sending a message to the player. (NOT YET IMPLEMENTED) - */ - messagecooldown, - /** - * How fast are people allowed to use /MVTP (NOT YET IMPLEMENTED). - */ - teleportcooldown, - /** - * Prefix chat-messages with world-names. - */ - worldnameprefix, - /** - * If value is set to false, Multiverse will NOT enforce world access permissions. - */ - enforceaccess, - /** - * Whether users should get detailed information about the permissions they would need. - */ - displaypermerrors, - /** - * Debug-information. - */ - debug, - /** - * The world new users will spawn in. - */ - firstspawnworld, - /** - * Whether Multiverse should intercept teleports. - */ - teleportintercept, - /** - * Whether Multiverse should override the first spawn. - */ - firstspawnoverride; - - /** - * Constructs a string containing all values in this enum. - * - * @return That {@link String}. - */ - public static String getAllValues() { - String buffer = ""; - for (ConfigProperty c : ConfigProperty.values()) { - // All values will NOT Contain spaces. - buffer += c.toString() + " "; - } - return buffer; - } -} diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVConfigReloadEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVConfigReloadEvent.java index 55763ffc..c878c4a5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVConfigReloadEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVConfigReloadEvent.java @@ -8,6 +8,7 @@ package com.onarandombox.MultiverseCore.event; import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; import java.util.List; @@ -23,6 +24,24 @@ public class MVConfigReloadEvent extends Event { this.configsLoaded = configsLoaded; } + private static final HandlerList HANDLERS = new HandlerList(); + + /** + * {@inheritDoc} + */ + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + /** + * Gets the handler list. This is required by the event system. + * @return A list of HANDLERS. + */ + public static HandlerList getHandlerList() { + return HANDLERS; + } + /** * Adds a config to this event. * @param config The config to add. diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVPlayerTouchedPortalEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVPlayerTouchedPortalEvent.java index 0e293ee7..32cb6421 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVPlayerTouchedPortalEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVPlayerTouchedPortalEvent.java @@ -11,6 +11,7 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; /** * This event is thrown when a portal is touched. @@ -26,6 +27,24 @@ public class MVPlayerTouchedPortalEvent extends Event implements Cancellable { this.l = l; } + private static final HandlerList HANDLERS = new HandlerList(); + + /** + * {@inheritDoc} + */ + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + /** + * Gets the handler list. This is required by the event system. + * @return A list of HANDLERS. + */ + public static HandlerList getHandlerList() { + return HANDLERS; + } + /** * Gets the {@link Location} of the portal-block that was touched. * @return The {@link Location} of the portal-block that was touched. diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVRespawnEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVRespawnEvent.java index fba5c8d2..c94f4828 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVRespawnEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVRespawnEvent.java @@ -10,6 +10,7 @@ package com.onarandombox.MultiverseCore.event; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; /** * Called when a player is respawning. @@ -27,6 +28,24 @@ public class MVRespawnEvent extends Event { this.respawnMethod = respawnMethod; } + private static final HandlerList HANDLERS = new HandlerList(); + + /** + * {@inheritDoc} + */ + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + /** + * Gets the handler list. This is required by the event system. + * @return A list of HANDLERS. + */ + public static HandlerList getHandlerList() { + return HANDLERS; + } + /** * Gets the {@link Player} that's respawning. * @return The {@link Player} that's respawning. diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java index 0de2f7b8..3728c7d0 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java @@ -8,12 +8,14 @@ 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; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; /** * Event that gets called when a player use the /mvtp command. @@ -33,6 +35,24 @@ public class MVTeleportEvent extends Event implements Cancellable { this.useSafeTeleport = safeTeleport; } + private static final HandlerList HANDLERS = new HandlerList(); + + /** + * {@inheritDoc} + */ + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + /** + * Gets the handler list. This is required by the event system. + * @return A list of HANDLERS. + */ + public static HandlerList getHandlerList() { + return HANDLERS; + } + /** * Returns the player who will be teleported by this event. * diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java index 6580dafc..cb4698f1 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java @@ -1,6 +1,7 @@ package com.onarandombox.MultiverseCore.event; import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; /** * Called when somebody requests version information about Multiverse. @@ -14,6 +15,24 @@ public class MVVersionEvent extends Event { versionInfoBuilder = new StringBuilder(versionInfo); } + private static final HandlerList HANDLERS = new HandlerList(); + + /** + * {@inheritDoc} + */ + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + /** + * Gets the handler list. This is required by the event system. + * @return A list of HANDLERS. + */ + public static HandlerList getHandlerList() { + return HANDLERS; + } + /** * Gets the version-info currently saved in this event. * @return The version-info. diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionRequestEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionRequestEvent.java deleted file mode 100644 index da06601b..00000000 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionRequestEvent.java +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * 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.event; - -import org.bukkit.event.Event; - -/** - * Called when somebody requests version information about Multiverse. - * @deprecated Use {@link MVVersionEvent} instead. - */ -@Deprecated -public class MVVersionRequestEvent extends Event { - - private String pasteBinBuffer; - - public MVVersionRequestEvent(String pasteBinBuffer) { - super("MVVersion"); - this.pasteBinBuffer = pasteBinBuffer; - } - - /** - * Gets the pasteBinBuffer. - * @return The pasteBinBuffer. - * @deprecated Use {@link MVVersionEvent} instead. - */ - @Deprecated - public String getPasteBinBuffer() { - return this.pasteBinBuffer; - } - - /** - * Sets the pasteBinBuffer. - * @param buffer The new pasteBinBuffer. - * @deprecated Use {@link MVVersionEvent} instead. - */ - @Deprecated - public void setPasteBinBuffer(String buffer) { - this.pasteBinBuffer = buffer; - } -} diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldDeleteEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldDeleteEvent.java index e24b3b71..38bf215d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldDeleteEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldDeleteEvent.java @@ -4,6 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import org.bukkit.event.HandlerList; /** * Called when a world is about to be deleted by Multiverse. @@ -24,6 +25,24 @@ public class MVWorldDeleteEvent extends Event implements Cancellable { this.removeFromConfig = removeFromConfig; } + private static final HandlerList HANDLERS = new HandlerList(); + + /** + * {@inheritDoc} + */ + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + /** + * Gets the handler list. This is required by the event system. + * @return A list of HANDLERS. + */ + public static HandlerList getHandlerList() { + return HANDLERS; + } + /** * {@inheritDoc} */ diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldPropertyChangeEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldPropertyChangeEvent.java index 06b4e0a4..8d74d471 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldPropertyChangeEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVWorldPropertyChangeEvent.java @@ -11,6 +11,7 @@ import com.onarandombox.MultiverseCore.api.MultiverseWorld; import org.bukkit.command.CommandSender; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; /** * This event is fired *before* the property is actually changed. @@ -27,7 +28,6 @@ public class MVWorldPropertyChangeEvent extends Event implements Cancellable { private String value; private String name; - public MVWorldPropertyChangeEvent(MultiverseWorld world, CommandSender changer, String name, String value) { super("MVWorldPropertyChange"); this.world = world; @@ -36,6 +36,24 @@ public class MVWorldPropertyChangeEvent extends Event implements Cancellable { this.value = value; } + private static final HandlerList HANDLERS = new HandlerList(); + + /** + * {@inheritDoc} + */ + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + /** + * Gets the handler list. This is required by the event system. + * @return A list of handlers. + */ + public static HandlerList getHandlerList() { + return HANDLERS; + } + /** * Gets the changed world property's name. * @return The changed world property's name. diff --git a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVEntityListener.java b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVEntityListener.java index 95ff0008..873a885d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVEntityListener.java +++ b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVEntityListener.java @@ -85,9 +85,8 @@ public class MVEntityListener implements Listener { */ @EventHandler public void creatureSpawn(CreatureSpawnEvent event) { - // Check to see if the Creature is spawned by a plugin, we don't want to prevent this behaviour. - if (event.getSpawnReason() == SpawnReason.CUSTOM) { + if (event.getSpawnReason() == SpawnReason.CUSTOM || event.getSpawnReason() == SpawnReason.EGG) { return; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java index ad62c4d4..2af2670d 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; @@ -56,7 +55,7 @@ public class MVPlayerListener implements Listener { } // Check whether the Server is set to prefix the chat with the World name. // If not we do nothing, if so we need to check if the World has an Alias. - if (MultiverseCore.PrefixChat) { + if (plugin.getMVConfig().getPrefixChat()) { String world = event.getPlayer().getWorld().getName(); String prefix = ""; // If we're not a MV world, don't do anything @@ -128,7 +127,7 @@ public class MVPlayerListener implements Listener { Player p = event.getPlayer(); if (!p.hasPlayedBefore()) { this.plugin.log(Level.FINE, "Player joined first!"); - if (MultiverseCore.FirstSpawnOverride) { + if (plugin.getMVConfig().getFirstSpawnOverride()) { this.plugin.log(Level.FINE, "Moving NEW player to(firstspawnoverride): " + worldManager.getFirstSpawnWorld().getSpawnLocation()); this.spawnNewPlayer(p); } @@ -198,7 +197,7 @@ public class MVPlayerListener implements Listener { teleportee.getName(), event.getTo().getWorld().getName(), teleporter.getName())); return; } - if (MultiverseCore.EnforceAccess) { + if (plugin.getMVConfig().getEnforceAccess()) { event.setCancelled(!pt.playerCanGoFromTo(fromWorld, toWorld, teleporter, teleportee)); if (event.isCancelled() && teleporter != null) { this.plugin.log(Level.FINE, String.format("Player '%s' was DENIED ACCESS to '%s' because '%s' don't have: multiverse.access.%s", @@ -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) { @@ -263,7 +262,7 @@ public class MVPlayerListener implements Listener { event.getPlayer().getName(), event.getTo().getWorld().getName())); return; } - if (MultiverseCore.EnforceAccess) { + if (plugin.getMVConfig().getEnforceAccess()) { event.setCancelled(!pt.playerCanGoFromTo(fromWorld, toWorld, event.getPlayer(), event.getPlayer())); if (event.isCancelled()) { this.plugin.log(Level.FINE, String.format("Player '%s' was DENIED ACCESS to '%s' because they don't have: multiverse.access.%s", @@ -309,7 +308,7 @@ public class MVPlayerListener implements Listener { public void run() { // Check that the player is in the new world and they haven't been teleported elsewhere or the event cancelled. if (player.getWorld() == world.getCBWorld()) { - MultiverseCore.staticLog(Level.FINE, "Handeling gamemode for player: " + player.getName() + ", " + world.getGameMode().toString()); + MultiverseCore.staticLog(Level.FINE, "Handling gamemode for player: " + player.getName() + ", " + world.getGameMode().toString()); MultiverseCore.staticLog(Level.FINE, "PWorld: " + player.getWorld()); MultiverseCore.staticLog(Level.FINE, "AWorld: " + world); player.setGameMode(world.getGameMode()); diff --git a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPluginListener.java b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPluginListener.java index 567429e4..001a490f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPluginListener.java +++ b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPluginListener.java @@ -36,7 +36,7 @@ public class MVPluginListener implements Listener { @EventHandler(priority = EventPriority.MONITOR) public void pluginEnable(PluginEnableEvent event) { // Let AllPay handle all econ plugin loadings, only go for econ plugins we support - if (Arrays.asList(AllPay.validEconPlugins).contains(event.getPlugin().getDescription().getName())) { + if (Arrays.asList(AllPay.getValidEconPlugins()).contains(event.getPlugin().getDescription().getName())) { this.plugin.setBank(this.plugin.getBanker().loadEconPlugin()); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPortalListener.java b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPortalListener.java new file mode 100644 index 00000000..6f124b41 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPortalListener.java @@ -0,0 +1,78 @@ +/****************************************************************************** + * Multiverse 2 Copyright (c) the Multiverse Team 2012. * + * 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.listeners; + +import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import com.onarandombox.MultiverseCore.enums.AllowedPortalType; +import org.bukkit.Material; +import org.bukkit.PortalType; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityCreatePortalEvent; +import org.bukkit.event.world.PortalCreateEvent; + +/** + * A custom listener for portal related events. + */ +public class MVPortalListener implements Listener { + + private MultiverseCore plugin; + + public MVPortalListener(MultiverseCore core) { + this.plugin = core; + } + + /** + * This is called when an entity creates a portal. + * + * @param event The event where an entity created a portal. + */ + @EventHandler + public void entityPortalCreate(EntityCreatePortalEvent event) { + if (event.isCancelled() || event.getBlocks().size() == 0) { + return; + } + MultiverseWorld world = this.plugin.getMVWorldManager().getMVWorld(event.getBlocks().get(0).getWorld()); + event.setCancelled(this.cancelPortalEvent(world, event.getPortalType())); + } + + /** + * This is called when a portal is created as the result of another world being linked. + * @param event The event where a portal was formed due to a world link + */ + @EventHandler + public void portalForm(PortalCreateEvent event) { + if (event.isCancelled() || event.getBlocks().size() == 0) { + return; + } + // There's no type attribute (as of 1.1-R1), so we have to iterate. + for (Block b : event.getBlocks()) { + if (b.getType() == Material.PORTAL) { + MultiverseWorld world = this.plugin.getMVWorldManager().getMVWorld(b.getWorld()); + event.setCancelled(this.cancelPortalEvent(world, PortalType.NETHER)); + return; + } + } + // If We're here, then the Portal was an Ender type: + MultiverseWorld world = this.plugin.getMVWorldManager().getMVWorld(event.getBlocks().get(0).getWorld()); + event.setCancelled(this.cancelPortalEvent(world, PortalType.ENDER)); + } + + private boolean cancelPortalEvent(MultiverseWorld world, PortalType type) { + if (world.getAllowedPortals() == AllowedPortalType.NONE) { + return true; + } else if (world.getAllowedPortals() != AllowedPortalType.ALL) { + if (type != world.getAllowedPortals().getActualPortalType()) { + return true; + } + } + return false; + } +} 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/MVPermissions.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVPermissions.java index a66c0d9b..980febeb 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVPermissions.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVPermissions.java @@ -98,7 +98,8 @@ public class MVPermissions implements PermissionsInterface { */ public boolean canEnterWorld(Player p, MultiverseWorld w) { // If we're not enforcing access, anyone can enter. - if (!MultiverseCore.EnforceAccess) { + if (!plugin.getMVConfig().getEnforceAccess()) { + this.plugin.log(Level.FINEST, "EnforceAccess is OFF. Player was allowed in " + w.getAlias()); return true; } return this.hasPermission(p, "multiverse.access." + w.getName(), false); @@ -169,9 +170,9 @@ public class MVPermissions implements PermissionsInterface { // plugin reloads, when MV asks the API if a player has a perm, it reports that they do NOT. // For the moment, we're going to check all of this node's parents to see if the user has those. It stops // when if finds a true or there are no more parents. --FF - if (!hasPermission) { - hasPermission = this.hasAnyParentPermission(sender, node); - } +// if (!hasPermission) { +// hasPermission = this.hasAnyParentPermission(sender, node); +// } return hasPermission; } @@ -179,10 +180,12 @@ public class MVPermissions implements PermissionsInterface { // TODO: Better player checks, most likely not needed, but safer. private boolean checkActualPermission(CommandSender sender, String node) { Player player = (Player) sender; - this.plugin.log(Level.FINEST, "Checking to see if player [" + player.getName() + "] has permission [" + node + "]"); + boolean hasPermission = sender.hasPermission(node); if (hasPermission) { - this.plugin.log(Level.FINER, "Player [" + player.getName() + "] HAS PERMISSION [" + node + "]!"); + this.plugin.log(Level.FINEST, "Checking to see if player [" + player.getName() + "] has permission [" + node + "]... YES"); + } else { + this.plugin.log(Level.FINEST, "Checking to see if player [" + player.getName() + "] has permission [" + node + "]... NO"); } return hasPermission; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVPlayerSession.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVPlayerSession.java index 90e8796c..5b772f9e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVPlayerSession.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/MVPlayerSession.java @@ -7,8 +7,9 @@ package com.onarandombox.MultiverseCore.utils; -import com.onarandombox.MultiverseCore.MultiverseCore; -import org.bukkit.configuration.Configuration; +import com.onarandombox.MultiverseCore.MultiverseCoreConfiguration; + +import com.onarandombox.MultiverseCore.api.MultiverseCoreConfig; import org.bukkit.entity.Player; import java.util.Date; @@ -23,9 +24,9 @@ public class MVPlayerSession { private long teleportLast = 0L; // Timestamp for the Players last Portal Teleportation. private long messageLast = 0L; // Timestamp for the Players last Alert Message. - private Configuration config; // Configuration file to find out Cooldown Timers. + private MultiverseCoreConfig config; // Configuration file to find out Cooldown Timers. - public MVPlayerSession(Player player, Configuration config, MultiverseCore multiVerseCore) { + public MVPlayerSession(Player player, MultiverseCoreConfig config) { this.player = player; this.config = config; // this.bedSpawn = null; @@ -42,6 +43,6 @@ public class MVPlayerSession { */ public boolean getTeleportable() { long time = (new Date()).getTime(); - return ((time - this.teleportLast) > this.config.getInt("portalcooldown", 5000)); // SUPPRESS CHECKSTYLE: MagicNumberCheck + return ((time - this.teleportLast) > this.config.getTeleportCooldown()); } } 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/PermissionTools.java b/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionTools.java index 2be0c287..bcb98377 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionTools.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionTools.java @@ -100,7 +100,7 @@ public class PermissionTools { */ public boolean playerHasMoneyToEnter(MultiverseWorld fromWorld, MultiverseWorld toWorld, CommandSender teleporter, Player teleportee, boolean pay) { Player teleporterPlayer; - if (MultiverseCore.TeleportIntercept) { + if (plugin.getMVConfig().getTeleportIntercept()) { if (teleporter instanceof ConsoleCommandSender) { return true; } @@ -171,7 +171,7 @@ public class PermissionTools { this.plugin.log(Level.FINEST, "Checking '" + teleporter + "' can send '" + teleportee + "' somewhere"); Player teleporterPlayer; - if (MultiverseCore.TeleportIntercept) { + if (plugin.getMVConfig().getTeleportIntercept()) { // The console can send anyone anywhere if (teleporter instanceof ConsoleCommandSender) { return true; 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..8c9764b9 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); } /** @@ -82,15 +84,17 @@ public class WorldManager implements MVWorldManager { * {@inheritDoc} */ @Override - public boolean addWorld(String name, Environment env, String seedString, WorldType type, String generator) { - return this.addWorld(name, env, seedString, type, generator, true); + public boolean addWorld(String name, Environment env, String seedString, WorldType type, boolean generateStructures, + String generator) { + return this.addWorld(name, env, seedString, type, generateStructures, generator, true); } /** * {@inheritDoc} */ @Override - public boolean addWorld(String name, Environment env, String seedString, WorldType type, String generator, boolean useSpawnAdjust) { + public boolean addWorld(String name, Environment env, String seedString, WorldType type, boolean generateStructures, + String generator, boolean useSpawnAdjust) { plugin.log(Level.FINE, "Adding world with: " + name + ", " + env.toString() + ", " + seedString + ", " + type.toString() + ", " + generator); Long seed = null; WorldCreator c = new WorldCreator(name); @@ -109,6 +113,7 @@ public class WorldManager implements MVWorldManager { } c.environment(env); c.type(type); + c.generateStructures(generateStructures); World world; StringBuilder builder = new StringBuilder(); @@ -139,7 +144,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); @@ -205,7 +210,7 @@ public class WorldManager implements MVWorldManager { */ @Override public void setFirstSpawnWorld(String world) { - if (world == null) { + if ((world == null) && (this.plugin.getServer().getWorlds().size() > 0)) { this.firstSpawn = this.plugin.getServer().getWorlds().get(0).getName(); } else { this.firstSpawn = world; @@ -279,9 +284,10 @@ public class WorldManager implements MVWorldManager { String type = this.configWorlds.getString("worlds." + name + ".type", "NORMAL"); String seedString = this.configWorlds.getString("worlds." + name + ".seed", ""); String generatorString = this.configWorlds.getString("worlds." + name + ".generator"); + boolean generateStructures = this.configWorlds.getBoolean("worlds." + name + ".generatestructures", true); - addWorld(name, EnvironmentCommand.getEnvFromString(environment), seedString, - EnvironmentCommand.getWorldTypeFromString(type), generatorString); + this.addWorld(name, EnvironmentCommand.getEnvFromString(environment), seedString, + EnvironmentCommand.getWorldTypeFromString(type), generateStructures, generatorString); if (this.unloadedWorlds.contains(name)) { this.unloadedWorlds.remove(name); } @@ -371,7 +377,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); @@ -467,9 +473,11 @@ public class WorldManager implements MVWorldManager { String name = w.getName(); if (!worldStrings.contains(name)) { if (this.defaultGens.containsKey(name)) { - this.addWorld(name, w.getEnvironment(), w.getSeed() + "", w.getWorldType(), this.defaultGens.get(name)); + this.addWorld(name, w.getEnvironment(), w.getSeed() + "", w.getWorldType(), + w.canGenerateStructures(), this.defaultGens.get(name)); } else { - this.addWorld(name, w.getEnvironment(), w.getSeed() + "", w.getWorldType(), null); + this.addWorld(name, w.getEnvironment(), w.getSeed() + "", w.getWorldType(), + w.canGenerateStructures(), null); } } @@ -543,6 +551,7 @@ public class WorldManager implements MVWorldManager { String environment = this.configWorlds.getString("worlds." + worldKey + ".environment", "NORMAL"); String type = this.configWorlds.getString("worlds." + worldKey + ".type", "NORMAL"); String seedString = this.configWorlds.getString("worlds." + worldKey + ".seed", null); + boolean generateStructures = this.configWorlds.getBoolean("worlds." + worldKey + ".generatestructures", true); if (seedString == null) { seedString = this.configWorlds.getLong("worlds." + worldKey + ".seed") + ""; } @@ -552,9 +561,8 @@ public class WorldManager implements MVWorldManager { this.plugin.log(Level.WARNING, "Found SKYLANDS world. Not importing automatically, as it won't work atm :("); continue; } - // TODO: UNCOMMENT BEFORE RELEASE addWorld(worldKey, EnvironmentCommand.getEnvFromString(environment), seedString, - EnvironmentCommand.getWorldTypeFromString(type), generatorString); + EnvironmentCommand.getWorldTypeFromString(type), generateStructures, generatorString); // Increment the world count count++; @@ -575,10 +583,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; } /** diff --git a/src/main/resources/defaults/config.yml b/src/main/resources/defaults/config.yml index 2b8204de..3bf24ebc 100644 --- a/src/main/resources/defaults/config.yml +++ b/src/main/resources/defaults/config.yml @@ -1,14 +1,16 @@ -# This is the MV2 Config. If you mess it up, copy the values out -# delete it, and it will be regenerated. Then use the ingame interface -# to add your values back via the "/mv conf" command. -# When in-game, simply type: "/mv conf ?" for help. -# A config with explanations can be found here: -# https://github.com/Multiverse/Multiverse-Core/wiki/config.yml - -worldnameprefix: true -enforceaccess: true -displaypermerrors: true -teleportintercept: true -firstspawnoverride: true -locale: en -version: 2.7 +# ------------------------------------------------------------------------- # +# This is the MV2 Config. If you mess it up, copy the values out # +# delete it, and it will be regenerated. Then use the ingame interface # +# to add your values back via the "/mv conf" command. # +# When in-game, simply type: "/mv conf ?" for help. # +# A config with explanations can be found here: # +# https://github.com/Multiverse/Multiverse-Core/wiki/config.yml # +# # +# # +# IMPORTANT !! IMPORTANT !! IMPORTANT !! IMPORTANT !! IMPORTANT !!IMPORTANT # +# # +# Do NOT delete this line from your config!!!! # +# ==: com.onarandombox.MultiverseCore.MultiverseCoreConfiguration # +# # +# IMPORTANT !! IMPORTANT !! IMPORTANT !! IMPORTANT !! IMPORTANT !!IMPORTANT # +# ------------------------------------------------------------------------- # diff --git a/src/test/java/com/onarandombox/MultiverseCore/test/TestDebugMode.java b/src/test/java/com/onarandombox/MultiverseCore/test/TestDebugMode.java index 34815c6c..64d9b1fd 100644 --- a/src/test/java/com/onarandombox/MultiverseCore/test/TestDebugMode.java +++ b/src/test/java/com/onarandombox/MultiverseCore/test/TestDebugMode.java @@ -22,12 +22,14 @@ import org.bukkit.command.CommandSender; import org.bukkit.plugin.Plugin; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.Core; import com.onarandombox.MultiverseCore.test.utils.TestInstanceCreator; @RunWith(PowerMockRunner.class) @@ -54,6 +56,7 @@ public class TestDebugMode { public void testEnableDebugMode() { // Pull a core instance from the server. Plugin plugin = mockServer.getPluginManager().getPlugin("Multiverse-Core"); + Core core = (Core) plugin; // Make sure Core is not null assertNotNull(plugin); @@ -70,12 +73,12 @@ public class TestDebugMode { when(mockCommand.getName()).thenReturn("mv"); // Assert debug mode is off - Assert.assertEquals(0, MultiverseCore.GlobalDebug); + Assert.assertEquals(0, core.getMVConfig().getGlobalDebug()); // Send the debug command. String[] debugArgs = new String[] { "debug", "3" }; plugin.onCommand(mockCommandSender, mockCommand, "", debugArgs); - Assert.assertEquals(3, MultiverseCore.GlobalDebug); + Assert.assertEquals(3, core.getMVConfig().getGlobalDebug()); } } diff --git a/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldProperties.java b/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldProperties.java index 4bbd221a..b53ffeaa 100644 --- a/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldProperties.java +++ b/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldProperties.java @@ -8,6 +8,8 @@ package com.onarandombox.MultiverseCore.test; import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.*; import org.bukkit.Bukkit; @@ -15,17 +17,24 @@ import org.bukkit.ChatColor; import org.bukkit.Difficulty; import org.bukkit.GameMode; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; +import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.weather.ThunderChangeEvent; import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.permissions.Permission; import org.bukkit.plugin.PluginManager; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.internal.verification.VerificationModeFactory; @@ -42,13 +51,31 @@ import com.onarandombox.MultiverseCore.utils.WorldManager; @RunWith(PowerMockRunner.class) @PrepareForTest({ PluginManager.class, MultiverseCore.class, Permission.class, Bukkit.class, WeatherChangeEvent.class, ThunderChangeEvent.class, PlayerChatEvent.class, - PlayerJoinEvent.class, WorldManager.class }) + PlayerJoinEvent.class, PlayerRespawnEvent.class, EntityRegainHealthEvent.class, + FoodLevelChangeEvent.class, WorldManager.class }) public class TestWorldProperties { private TestInstanceCreator creator; private MultiverseCore core; private CommandSender mockCommandSender; + // Events + private WeatherChangeEvent weatherChangeOffEvent; + private WeatherChangeEvent weatherChangeOnEvent; + private ThunderChangeEvent thunderChangeOffEvent; + private ThunderChangeEvent thunderChangeOnEvent; + private Player mockPlayer; + private PlayerChatEvent playerChatEvent; + private Player mockNewPlayer; + private PlayerJoinEvent playerNewJoinEvent; + private PlayerJoinEvent playerJoinEvent; + private PlayerRespawnEvent playerRespawnBed; + private PlayerRespawnEvent playerRespawnNormal; + private Entity mockEntity; + private EntityRegainHealthEvent entityRegainHealthEvent; + private FoodLevelChangeEvent entityFoodLevelChangeEvent; + private FoodLevelChangeEvent entityFoodLevelRiseEvent; + @Before public void setUp() throws Exception { creator = new TestInstanceCreator(); @@ -78,7 +105,8 @@ public class TestWorldProperties { String[] netherArgs = new String[] { "import", "world_nether", "nether" }; core.onCommand(mockCommandSender, mockCommand, "", netherArgs); verify(mockCommandSender).sendMessage("Starting import of world 'world_nether'..."); - verify(mockCommandSender, VerificationModeFactory.times(2)).sendMessage(ChatColor.GREEN + "Complete!"); + verify(mockCommandSender, VerificationModeFactory.times(2)).sendMessage( + ChatColor.GREEN + "Complete!"); // //////////////////////////////////////////////// // let's set some world-properties @@ -87,13 +115,15 @@ public class TestWorldProperties { assertNotNull(worldManager); MultiverseWorld mvWorld = worldManager.getMVWorld("world"); + MultiverseWorld netherWorld = worldManager.getMVWorld("world_nether"); assertNotNull(mvWorld); + assertNotNull(netherWorld); assertSame(mvWorld, worldManager.getFirstSpawnWorld()); assertSame(mvWorld, worldManager.getSpawnWorld()); - /* ****************************************** * - * Check defaults - * ****************************************** */ + /* ***************************** * + * Check defaults + * ***************************** */ assertFalse(mvWorld.isHidden()); assertEquals(mvWorld.getName(), mvWorld.getAlias()); assertEquals(ChatColor.WHITE, mvWorld.getColor()); @@ -102,7 +132,9 @@ public class TestWorldProperties { // assertEquals(Object,Object) instead of assertEquals(double,double) assertNull(mvWorld.getRespawnToWorld()); assertTrue(mvWorld.isWeatherEnabled()); - // assertEquals(Difficulty.EASY, mvWorld.getDifficulty()); + World cbWorld = mvWorld.getCBWorld(); + when(cbWorld.getDifficulty()).thenReturn(Difficulty.NORMAL); + assertEquals(Difficulty.NORMAL, mvWorld.getDifficulty()); assertTrue(mvWorld.canAnimalsSpawn()); assertTrue(mvWorld.canMonstersSpawn()); assertEquals(-1, mvWorld.getCurrency()); @@ -119,26 +151,7 @@ public class TestWorldProperties { /* ****************************************** * * Call some events and verify behavior * ****************************************** */ - // weather change - WeatherChangeEvent weatherChangeOffEvent = new WeatherChangeEvent(mvWorld.getCBWorld(), false); - WeatherChangeEvent weatherChangeOnEvent = new WeatherChangeEvent(mvWorld.getCBWorld(), true); - // thunder change - ThunderChangeEvent thunderChangeOffEvent = new ThunderChangeEvent(mvWorld.getCBWorld(), false); - ThunderChangeEvent thunderChangeOnEvent = new ThunderChangeEvent(mvWorld.getCBWorld(), true); - // player chat - Player mockPlayer = mock(Player.class); - when(mockPlayer.getWorld()).thenReturn(mvWorld.getCBWorld()); - when(mockPlayer.hasPlayedBefore()).thenReturn(true); - PlayerChatEvent playerChatEvent = PowerMockito.mock(PlayerChatEvent.class); - PowerMockito.when(playerChatEvent.getPlayer()).thenReturn(mockPlayer); - PowerMockito.when(playerChatEvent.getFormat()).thenReturn("format"); - // player join - Player mockNewPlayer = mock(Player.class); - when(mockNewPlayer.hasPlayedBefore()).thenReturn(false); - PlayerJoinEvent playerJoinEvent = PowerMockito.mock(PlayerJoinEvent.class); - when(playerJoinEvent.getPlayer()).thenReturn(mockPlayer); - PlayerJoinEvent playerNewJoinEvent = PowerMockito.mock(PlayerJoinEvent.class); - when(playerNewJoinEvent.getPlayer()).thenReturn(mockNewPlayer); + createEvents(mvWorld); // call both weather change events core.getWeatherListener().weatherChange(weatherChangeOffEvent); @@ -153,8 +166,12 @@ public class TestWorldProperties { assertFalse(thunderChangeOnEvent.isCancelled()); // call player chat event + core.getMVConfig().setPrefixChat(true); core.getPlayerListener().playerChat(playerChatEvent); verify(playerChatEvent).setFormat("[" + mvWorld.getColoredWorldString() + "]" + "format"); + core.getMVConfig().setPrefixChat(false); + core.getPlayerListener().playerChat(playerChatEvent); + verify(playerChatEvent, times(1)).setFormat(anyString()); // only ONE TIME (not the 2nd time!) // call player join events core.getPlayerListener().playerJoin(playerJoinEvent); @@ -162,9 +179,22 @@ public class TestWorldProperties { core.getPlayerListener().playerJoin(playerNewJoinEvent); verify(mockNewPlayer).teleport(worldManager.getFirstSpawnWorld().getSpawnLocation()); - /* ****************************************** * - * Modify & Verify - * ****************************************** */ + // call player respawn events + core.getPlayerListener().playerRespawn(playerRespawnBed); + // bedrespawn is on so nothing should happen + verify(playerRespawnBed, never()).setRespawnLocation(any(Location.class)); + core.getPlayerListener().playerRespawn(playerRespawnNormal); + verify(playerRespawnNormal).setRespawnLocation(mvWorld.getSpawnLocation()); + + // call entity regain health event + core.getEntityListener().entityRegainHealth(entityRegainHealthEvent); + // autoheal is on so nothing should happen + verify(entityRegainHealthEvent, never()).setCancelled(true); + + + /* ************************ * + * Modify & Verify + * ************************ */ mvWorld.setHidden(true); assertEquals(true, mvWorld.isHidden()); mvWorld.setAlias("alias"); @@ -173,13 +203,15 @@ public class TestWorldProperties { ChatColor oldColor = mvWorld.getColor(); assertFalse(mvWorld.setColor("INVALID COLOR")); assertEquals(oldColor, mvWorld.getColor()); + assertEquals(oldColor.toString() + "alias" + ChatColor.WHITE.toString(), mvWorld.getColoredWorldString()); mvWorld.setPVPMode(false); assertEquals(false, mvWorld.isPVPEnabled()); assertTrue(mvWorld.setScaling(2D)); assertEquals((Object) 2D, (Object) mvWorld.getScaling()); assertFalse(mvWorld.setRespawnToWorld("INVALID WORLD")); assertTrue(mvWorld.setRespawnToWorld("world_nether")); - assertSame(worldManager.getMVWorld("world_nether").getCBWorld(), mvWorld.getRespawnToWorld()); + assertSame(worldManager.getMVWorld("world_nether").getCBWorld(), + mvWorld.getRespawnToWorld()); mvWorld.setEnableWeather(false); assertEquals(false, mvWorld.isWeatherEnabled()); assertTrue(mvWorld.setDifficulty("PEACEFUL")); @@ -216,6 +248,9 @@ public class TestWorldProperties { /* ****************************************** * * Call some events and verify behavior * ****************************************** */ + // We have to recreate the events and the mock-objects + createEvents(mvWorld); + // call both weather change events core.getWeatherListener().weatherChange(weatherChangeOffEvent); assertFalse(weatherChangeOffEvent.isCancelled()); @@ -227,6 +262,84 @@ public class TestWorldProperties { assertFalse(thunderChangeOffEvent.isCancelled()); core.getWeatherListener().thunderChange(thunderChangeOnEvent); assertTrue(thunderChangeOnEvent.isCancelled()); + + // call player chat event + core.getMVConfig().setPrefixChat(true); + core.getPlayerListener().playerChat(playerChatEvent); + // never because it's hidden! + verify(playerChatEvent, never()).setFormat( + "[" + mvWorld.getColoredWorldString() + "]" + "format"); + mvWorld.setHidden(false); + core.getPlayerListener().playerChat(playerChatEvent); + verify(playerChatEvent).setFormat("[" + mvWorld.getColoredWorldString() + "]" + "format"); + core.getMVConfig().setPrefixChat(false); + core.getPlayerListener().playerChat(playerChatEvent); + verify(playerChatEvent, times(1)).setFormat(anyString()); // only ONE TIME (not the 2nd time!) + + // call player join events + core.getPlayerListener().playerJoin(playerJoinEvent); + verify(mockPlayer, never()).teleport(any(Location.class)); + core.getPlayerListener().playerJoin(playerNewJoinEvent); + verify(mockNewPlayer).teleport(new Location(mvWorld.getCBWorld(), 1, 1, 1)); + + // call player respawn events + core.getPlayerListener().playerRespawn(playerRespawnBed); + // bedrespawn is off so something should happen (and we've set respawn to nether...) + verify(playerRespawnBed).setRespawnLocation(netherWorld.getSpawnLocation()); + core.getPlayerListener().playerRespawn(playerRespawnNormal); + verify(playerRespawnNormal).setRespawnLocation(netherWorld.getSpawnLocation()); + + // call entity regain health event + core.getEntityListener().entityRegainHealth(entityRegainHealthEvent); + // autoheal is off so something should happen + verify(entityRegainHealthEvent).setCancelled(true); } + public void createEvents(MultiverseWorld mvWorld) { + //// Weather events + // weather change + weatherChangeOffEvent = new WeatherChangeEvent(mvWorld.getCBWorld(), false); + weatherChangeOnEvent = new WeatherChangeEvent(mvWorld.getCBWorld(), true); + // thunder change + thunderChangeOffEvent = new ThunderChangeEvent(mvWorld.getCBWorld(), false); + thunderChangeOnEvent = new ThunderChangeEvent(mvWorld.getCBWorld(), true); + //// Player events + // player chat + mockPlayer = mock(Player.class); + when(mockPlayer.getWorld()).thenReturn(mvWorld.getCBWorld()); + when(mockPlayer.hasPlayedBefore()).thenReturn(true); + playerChatEvent = PowerMockito.mock(PlayerChatEvent.class); + when(playerChatEvent.getPlayer()).thenReturn(mockPlayer); + when(playerChatEvent.getFormat()).thenReturn("format"); + // player join + mockNewPlayer = mock(Player.class); + when(mockNewPlayer.hasPlayedBefore()).thenReturn(false); + playerJoinEvent = PowerMockito.mock(PlayerJoinEvent.class); + when(playerJoinEvent.getPlayer()).thenReturn(mockPlayer); + playerNewJoinEvent = PowerMockito.mock(PlayerJoinEvent.class); + when(playerNewJoinEvent.getPlayer()).thenReturn(mockNewPlayer); + // player respawn + playerRespawnBed = PowerMockito.mock(PlayerRespawnEvent.class); + when(playerRespawnBed.getPlayer()).thenReturn(mockPlayer); + when(playerRespawnBed.isBedSpawn()).thenReturn(true); + playerRespawnNormal = PowerMockito.mock(PlayerRespawnEvent.class); + when(playerRespawnNormal.getPlayer()).thenReturn(mockPlayer); + when(playerRespawnNormal.isBedSpawn()).thenReturn(false); + //// Entity events + mockEntity = mock(Entity.class); + // entity regain health + entityRegainHealthEvent = PowerMockito.mock(EntityRegainHealthEvent.class); + when(entityRegainHealthEvent.getRegainReason()).thenReturn(RegainReason.REGEN); + when(mockEntity.getLocation()).thenReturn(new Location(mvWorld.getCBWorld(), 0, 0, 0)); + when(entityRegainHealthEvent.getEntity()).thenReturn(mockEntity); + // entity food level change event + entityFoodLevelChangeEvent = PowerMockito.mock(FoodLevelChangeEvent.class); + // this won't do anything since we're not mocking a player, + // but the plugin should be able to handle this! + when(entityFoodLevelChangeEvent.getEntity()).thenReturn(mockEntity); + entityFoodLevelRiseEvent = PowerMockito.mock(FoodLevelChangeEvent.class); + when(mockPlayer.getFoodLevel()).thenReturn(2); + when(entityFoodLevelRiseEvent.getEntity()).thenReturn(mockPlayer); + when(entityFoodLevelRiseEvent.getFoodLevel()).thenReturn(3); + } } diff --git a/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldStuff.java b/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldStuff.java index a2117a61..894cf2f2 100644 --- a/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldStuff.java +++ b/src/test/java/com/onarandombox/MultiverseCore/test/TestWorldStuff.java @@ -202,6 +202,7 @@ public class TestWorldStuff { } @Test + // TODO Migrate this to TestWorldProperties public void testModifyGameMode() { // Pull a core instance from the server. Plugin plugin = mockServer.getPluginManager().getPlugin("Multiverse-Core");