package com.intellectualcrafters.plot; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.bukkit.Bukkit; import com.intellectualcrafters.configuration.file.YamlConfiguration; import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.Configuration; import com.intellectualcrafters.plot.config.Settings; import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.database.Database; import com.intellectualcrafters.plot.database.MySQL; import com.intellectualcrafters.plot.database.SQLManager; import com.intellectualcrafters.plot.database.SQLite; import com.intellectualcrafters.plot.flag.AbstractFlag; import com.intellectualcrafters.plot.flag.FlagManager; import com.intellectualcrafters.plot.flag.FlagValue; import com.intellectualcrafters.plot.generator.AugmentedPopulator; import com.intellectualcrafters.plot.generator.ClassicPlotWorld; import com.intellectualcrafters.plot.generator.HybridGen; import com.intellectualcrafters.plot.generator.HybridPlotWorld; import com.intellectualcrafters.plot.generator.HybridUtils; import com.intellectualcrafters.plot.generator.SquarePlotManager; import com.intellectualcrafters.plot.generator.SquarePlotWorld; import com.intellectualcrafters.plot.listeners.APlotListener; import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotAnalysis; import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotCluster; import com.intellectualcrafters.plot.object.PlotGenerator; import com.intellectualcrafters.plot.object.PlotHandler; import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotWorld; import com.intellectualcrafters.plot.object.comment.CommentManager; import com.intellectualcrafters.plot.util.BlockManager; import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ClusterManager; import com.intellectualcrafters.plot.util.EconHandler; import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.ExpireManager; import com.intellectualcrafters.plot.util.InventoryUtil; import com.intellectualcrafters.plot.util.Logger; import com.intellectualcrafters.plot.util.Logger.LogLevel; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.PlayerManager; import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.bukkit.UUIDHandler; import com.sk89q.worldedit.bukkit.WorldEditPlugin; /** * An implementation of the core, * with a static getter for easy access * * @author Sauilitired | Citymonstret * @author boy0001 | Empire92 */ public class PS { // protected static: protected static PS instance; // private final: private final HashMap plotworlds = new HashMap<>(); private final HashMap plotmanagers = new HashMap<>(); // public: public WorldEditPlugin worldEdit = null; public File configFile; public File translationFile; public YamlConfiguration style; public YamlConfiguration config; public YamlConfiguration storage; public IPlotMain IMP = null; public TaskManager TASK; public URL update; // private: private File styleFile; private File storageFile; private File FILE = null; // This file private String VERSION = null; private String LAST_VERSION; private boolean LOADING_WORLD = false; private LinkedHashMap> plots; private Database database; private Connection connection; /** * Initialize PlotSquared with the desired Implementation class * @param imp_class */ protected PS(final IPlotMain imp_class) { instance = this; SetupUtils.generators = new HashMap<>(); IMP = imp_class; try { FILE = new File(PS.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); } catch (Exception e) { log("Could not determine file path"); } VERSION = IMP.getVersion(); EconHandler.manager = IMP.getEconomyHandler(); if (getJavaVersion() < 1.7) { log(C.PREFIX.s() + "&cYour java version is outdated. Please update to at least 1.7."); // Didn't know of any other link :D log(C.PREFIX.s() + "&cURL: &6https://java.com/en/download/index.jsp"); IMP.disable(); return; } if (getJavaVersion() < 1.8) { log(C.PREFIX.s() + "&cIt's really recommended to run Java 1.8, as it increases performance"); } this.TASK = IMP.getTaskManager(); if (C.ENABLED.s().length() > 0) { log(C.ENABLED.s()); } setupConfigs(); this.translationFile = new File(IMP.getDirectory() + File.separator + "translations" + File.separator + "PlotSquared.use_THIS.yml"); C.load(translationFile); setupDefaultFlags(); setupDatabase(); CommentManager.registerDefaultInboxes(); // Tasks if (Settings.KILL_ROAD_MOBS) { IMP.runEntityTask(); } // Events IMP.registerCommands(); IMP.registerPlayerEvents(); IMP.registerInventoryEvents(); IMP.registerPlotPlusEvents(); IMP.registerForceFieldEvents(); IMP.registerWorldEditEvents(); IMP.registerWorldEvents(); if (Settings.TNT_LISTENER) { IMP.registerTNTListener(); } if (Settings.CHUNK_PROCESSOR) { IMP.registerChunkProcessor(); } // create UUIDWrapper UUIDHandler.uuidWrapper = IMP.initUUIDHandler(); // create event util class EventUtil.manager = IMP.initEventUtil(); // create Hybrid utility class HybridUtils.manager = IMP.initHybridUtils(); // Inventory utility class InventoryUtil.manager = IMP.initInventoryUtil(); // create setup util class SetupUtils.manager = IMP.initSetupUtils(); // Set block BlockManager.manager = IMP.initBlockManager(); // Set chunk ChunkManager.manager = IMP.initChunkManager(); // Plot listener APlotListener.manager = IMP.initPlotListener(); // Player manager PlayerManager.manager = IMP.initPlayerManager(); // Check for updates TaskManager.runTaskAsync(new Runnable() { @Override public void run() { URL url = getUpdate(); if (url != null) { update = url; log("&6You are running an older version of PlotSquared..."); log("&8 - &3Use: &7/plot update"); log("&8 - &3Or: &7" + url); } else if (LAST_VERSION != null && !VERSION.equals(LAST_VERSION)) { log("&aThanks for updating from: " + LAST_VERSION + " to " + VERSION); } } }); // PlotMe if (Settings.CONVERT_PLOTME || Settings.CACHE_PLOTME) { TaskManager.runTaskLater(new Runnable() { public void run() { if (IMP.initPlotMeConverter()) { log("&c=== IMPORTANT ==="); log("&cTHIS MESSAGE MAY BE EXTREMELY HELPFUL IF YOU HAVE TROUBLE CONVERTING PLOTME!"); log("&c - Make sure 'UUID.read-from-disk' is disabled (false)!"); log("&c - Sometimes the database can be locked, deleting PlotMe.jar beforehand will fix the issue!"); log("&c - After the conversion is finished, please set 'plotme-convert.enabled' to false in the 'settings.yml'"); } } }, 200); } if (Settings.AUTO_CLEAR) { ExpireManager.runTask(); } // Copy files copyFile("town.template", "templates"); copyFile("skyblock.template", "templates"); copyFile("german.yml", "translations"); copyFile("s_chinese_unescaped.yml", "translations"); copyFile("s_chinese.yml", "translations"); copyFile("italian.yml", "translations"); showDebug(); } /** * Get the instance of PlotSquared * * @return the instance created by IPlotMain */ public static PS get() { return instance; } /** * Get the last PlotSquared version * @return last version in config or null */ public String getLastVersion() { return LAST_VERSION; } /** * Get the current PlotSquared version * @return current version in config or null */ public String getVersion() { return VERSION; } /** * Log a message to the IPlotMain logger * * @param message Message to log * @see IPlotMain#log(String) */ public static void log(final String message) { get().IMP.log(message); } /** * Get the database object * * @return Database object * @see #getConnection() Get the database connection */ public Database getDatabase() { return database; } /** * Update the global reference * to a plot object * * @param plot Plot Object to update */ public void updatePlot(final Plot plot) { final String world = plot.world; if (!plots.containsKey(world)) { plots.put(world, new HashMap()); } plot.hasChanged = true; plots.get(world).put(plot.id, plot); } /** * Get the plot world based on the * name identifier * * @param world World Name * @return plot world | null if not existing * @see #getPlotWorldsString() Get all plot world names */ public PlotWorld getPlotWorld(final String world) { if (plotworlds.containsKey(world)) { return plotworlds.get(world); } return null; } /** * Add a global reference to a plot world * * @param world World Name * @param plotworld PlotWorld Instance * @param manager PlotManager * @see #removePlotWorld(String) To remove the reference */ public void addPlotWorld(final String world, final PlotWorld plotworld, final PlotManager manager) { plotworlds.put(world, plotworld); plotmanagers.put(world, manager); if (!plots.containsKey(world)) { plots.put(world, new HashMap()); } } /** * Remove a plot world reference * * @param world World name * @see #addPlotWorld(String, PlotWorld, PlotManager) To add a reference */ public void removePlotWorld(final String world) { plots.remove(world); plotmanagers.remove(world); plotworlds.remove(world); } /** * @param world World Name */ public void removePlotWorldAbs(final String world) { plotmanagers.remove(world); plotworlds.remove(world); } /** * Get all plots as raw objects * * @see #getPlots() To get the plot objects * @see #getPlotsRaw() To get the plot objects * * @return HashMap containing the world name, and another map with the plot id and the plot object */ public HashMap> getAllPlotsRaw() { return plots; } /** * Set all the plots as a raw object * @see #getAllPlotsRaw() to get the raw plot object * @param plots */ public void setAllPlotsRaw(final LinkedHashMap> plots) { this.plots = plots; } /** * Get all the plots in a single set * @return Set of Plot */ public Set getPlots() { final ArrayList newplots = new ArrayList<>(); for (final Entry> entry : plots.entrySet()) { if (isPlotWorld(entry.getKey())) { newplots.addAll(entry.getValue().values()); } } return new LinkedHashSet<>(newplots); } /** * Get the raw plot object * @return set of plot * @see #setAllPlotsRaw(LinkedHashMap) to set the raw plot object */ public Set getPlotsRaw() { final ArrayList newplots = new ArrayList<>(); for (final Entry> entry : plots.entrySet()) { newplots.addAll(entry.getValue().values()); } return new LinkedHashSet<>(newplots); } /** * Sort a collection of plots by the hashcode * @param plots * @return ArrayList of plot */ public ArrayList sortPlots(Collection plots) { ArrayList newPlots = new ArrayList<>(); newPlots.addAll(plots); Collections.sort(newPlots, new Comparator() { public int compare(Plot p1, Plot p2) { int h1 = p1.hashCode(); int h2 = p2.hashCode(); if (h1 < 0) { h1 = -h1*2 - 1; } else { h1*=2; } if (h2 < 0) { h2 = -h2*2 - 1; } else { h2*=2; } return h1-h2; } }); return newPlots; } /** * Sort a collection of plots by world (with a priority world), then by hashcode * @param plots * @param priorityWorld * @see #sortPlotsByWorld(Collection) to sort plots by world, then by hashcode * @see #sortPlots(Collection) to sort plots just by hashcode * @return ArrayList of plot */ public ArrayList sortPlots(Collection plots, final String priorityWorld) { ArrayList newPlots = new ArrayList<>(); HashMap worldPlots = this.plots.get(priorityWorld); if (worldPlots != null) { for (Plot plot : sortPlots(worldPlots.values())) { if (plots.contains(plot)) { newPlots.add(plot); } } } ArrayList worlds = new ArrayList<>(this.plots.keySet()); Collections.sort(worlds); for (String world : worlds) { if (!world.equals(priorityWorld)) { for (Plot plot : this.plots.get(world).values()) { if (plots.contains(plot)) { newPlots.add(plot); } } } } return newPlots; } /** * Sort a collection of plots by world, then by hashcode * @param plots * @see #sortPlots(Collection, String) to sort with a specific priority world * @see #sortPlots(Collection) to sort plots just by hashcode * @return ArrayList of plot */ public ArrayList sortPlotsByWorld(Collection plots) { ArrayList newPlots = new ArrayList<>(); ArrayList worlds = new ArrayList<>(this.plots.keySet()); Collections.sort(worlds); for (String world : worlds) { for (Plot plot : this.plots.get(world).values()) { if (plots.contains(plot)) { newPlots.add(plot); } } } return newPlots; } /** * Get all the plots owned by a player name * @param world * @param player * @return Set of Plot */ public Set getPlots(final String world, final String player) { final UUID uuid = UUIDHandler.getUUID(player); return getPlots(world, uuid); } /** * Get all plots by a PlotPlayer * @param world * @param player * @return Set of plot */ public Set getPlots(final String world, final PlotPlayer player) { final UUID uuid = player.getUUID(); return getPlots(world, uuid); } /** * Get all plots by a UUID in a world * @param world * @param uuid * @return Set of plot */ public Set getPlots(final String world, final UUID uuid) { final ArrayList myplots = new ArrayList<>(); for (final Plot plot : getPlots(world).values()) { if (plot.hasOwner()) { if (PlotHandler.isOwner(plot, uuid)) { myplots.add(plot); } } } return new HashSet<>(myplots); } /** * Check if a plot world * @param world * @see #getPlotWorld(String) to get the PlotWorld object * @return if a plot world is registered */ public boolean isPlotWorld(final String world) { return (plotworlds.containsKey(world)); } /** * Get the plot manager for a world * @param world * @return the PlotManager object, or null if no registered PlotManager */ public PlotManager getPlotManager(final String world) { if (plotmanagers.containsKey(world)) { return plotmanagers.get(world); } return null; } /** * Get a list of the plot worlds * @return A String array of the plot world names */ public String[] getPlotWorldsString() { final Set strings = plots.keySet(); return strings.toArray(new String[strings.size()]); } /** * Get a map of the plots for a world * @param world * @return HashMap of PlotId to Plot */ public HashMap getPlots(final String world) { if (plots.containsKey(world)) { return plots.get(world); } return new HashMap<>(); } /** * Get the plots for a PlotPlayer * @param player * @return Set of Plot */ public Set getPlots(final PlotPlayer player) { return getPlots(player.getUUID()); } /** * Get the plots for a UUID * @param uuid * @return Set of Plot */ public Set getPlots(final UUID uuid) { final ArrayList myplots = new ArrayList<>(); for (final String world : plots.keySet()) { if (isPlotWorld(world)) { for (final Plot plot : plots.get(world).values()) { if (plot.hasOwner()) { if (PlotHandler.isOwner(plot, uuid)) { myplots.add(plot); } } } } } return new HashSet<>(myplots); } /** * Unregister a plot from local memory (does not call DB) * @param world * @param id * @param callEvent If to call an event about the plot being removed * @return true if plot existed | false if it didn't */ public boolean removePlot(final String world, final PlotId id, final boolean callEvent) { if (callEvent) { EventUtil.manager.callDelete(world, id); } HashMap allPlots = plots.get(world); if (allPlots == null) { return false; } Plot plot = allPlots.remove(id); if (MainUtil.lastPlot.containsKey(world)) { final PlotId last = MainUtil.lastPlot.get(world); final int last_max = Math.max(last.x, last.y); final int this_max = Math.max(id.x, id.y); if (this_max < last_max) { MainUtil.lastPlot.put(world, id); } } return plot != null; } /** * This method is called by the PlotGenerator class normally
* - Initializes the PlotWorld and PlotManager classes
* - Registers the PlotWorld and PlotManager classes
* - Loads (and/or generates) the PlotWorld configuration
* - Sets up the world border if configured
* If loading an augmented plot world:
* - Creates the AugmentedPopulator classes
* - Injects the AugmentedPopulator classes if required * @param world The world to load * @param generator The generator for that world, or null if no generator */ public void loadWorld(final String world, PlotGenerator generator) { PlotWorld plotWorld = getPlotWorld(world); if (plotWorld != null) { if (generator != null) { generator.init(plotWorld); } return; } final Set worlds = (config.contains("worlds") ? config.getConfigurationSection("worlds").getKeys(false) : new HashSet()); final PlotGenerator plotGenerator; final PlotManager plotManager; final String path = "worlds." + world; if (!LOADING_WORLD && (generator != null)) { plotGenerator = generator; plotWorld = plotGenerator.getNewPlotWorld(world); plotManager = plotGenerator.getPlotManager(); if (!world.equals("CheckingPlotSquaredGenerator")) { log(C.PREFIX.s() + "&aDetected world load for '" + world + "'"); log(C.PREFIX.s() + "&3 - generator: &7" + plotGenerator.getClass().getName()); log(C.PREFIX.s() + "&3 - plotworld: &7" + plotWorld.getClass().getName()); log(C.PREFIX.s() + "&3 - manager: &7" + plotManager.getClass().getName()); } if (!config.contains(path)) { config.createSection(path); } plotWorld.saveConfiguration(config.getConfigurationSection(path)); plotWorld.loadDefaultConfiguration(config.getConfigurationSection(path)); try { config.save(configFile); } catch (final IOException e) { e.printStackTrace(); } // Now add it addPlotWorld(world, plotWorld, plotManager); generator.init(plotWorld); MainUtil.setupBorder(world); } else { if (!worlds.contains(world)) { return; } if (!LOADING_WORLD) { LOADING_WORLD = true; try { final String gen_string = config.getString("worlds." + world + "." + "generator.plugin"); if (gen_string == null) { generator = new HybridGen(world); } else { generator = (PlotGenerator) IMP.getGenerator(world, gen_string); } loadWorld(world, generator); } catch (final Exception e) { log("&d=== Oh no! Please set the generator for the " + world + " ==="); e.printStackTrace(); LOADING_WORLD = false; removePlotWorld(world); } finally { LOADING_WORLD = false; } } else { final PlotGenerator gen_class = generator; plotWorld = gen_class.getNewPlotWorld(world); plotManager = gen_class.getPlotManager(); if (!config.contains(path)) { config.createSection(path); } plotWorld.TYPE = generator instanceof PlotGenerator ? 0 : 2; plotWorld.TERRAIN = 0; plotWorld.saveConfiguration(config.getConfigurationSection(path)); plotWorld.loadDefaultConfiguration(config.getConfigurationSection(path)); try { config.save(configFile); } catch (final IOException e) { e.printStackTrace(); } if (((plotWorld.TYPE == 2) && !Settings.ENABLE_CLUSTERS) || !(plotManager instanceof SquarePlotManager)) { log("&c[ERROR] World '" + world + "' in settings.yml is not using PlotSquared generator! Please set the generator correctly or delete the world from the 'settings.yml'!"); return; } log(C.PREFIX.s() + "&aDetected world load for '" + world + "'"); log(C.PREFIX.s() + "&3 - generator: &7" + gen_class.getClass().getName()); log(C.PREFIX.s() + "&3 - plotworld: &7" + plotWorld.getClass().getName()); log(C.PREFIX.s() + "&3 - manager: &7" + plotManager.getClass().getName()); log(C.PREFIX.s() + "&3 - | terrain: &7" + plotWorld.TERRAIN); log(C.PREFIX.s() + "&3 - | type: &7" + plotWorld.TYPE); addPlotWorld(world, plotWorld, plotManager); if (plotWorld.TYPE == 2) { if (ClusterManager.getClusters(world).size() > 0) { for (final PlotCluster cluster : ClusterManager.getClusters(world)) { log(C.PREFIX.s() + "&3 - &7| cluster: " + cluster); new AugmentedPopulator(world, gen_class, cluster, plotWorld.TERRAIN == 2, plotWorld.TERRAIN != 2); } } } else if (plotWorld.TYPE == 1) { new AugmentedPopulator(world, gen_class, null, plotWorld.TERRAIN == 2, plotWorld.TERRAIN != 2); } gen_class.init(plotWorld); } } } /** * Setup the configuration for a plot world based on world arguments
* e.g. /mv create normal -g PlotSquared: * @param world The name of the world * @param args The arguments * @return boolean | if valid arguments were provided */ public boolean setupPlotWorld(final String world, final String args) { if ((args != null) && (args.length() > 0)) { // save configuration final String[] split = args.split(","); final HybridPlotWorld plotworld = new HybridPlotWorld(world); final int width = SquarePlotWorld.PLOT_WIDTH_DEFAULT; final int gap = SquarePlotWorld.ROAD_WIDTH_DEFAULT; final int height = ClassicPlotWorld.PLOT_HEIGHT_DEFAULT; final PlotBlock[] floor = ClassicPlotWorld.TOP_BLOCK_DEFAULT; final PlotBlock[] main = ClassicPlotWorld.MAIN_BLOCK_DEFAULT; final PlotBlock wall = ClassicPlotWorld.WALL_FILLING_DEFAULT; final PlotBlock border = ClassicPlotWorld.WALL_BLOCK_DEFAULT; for (final String element : split) { final String[] pair = element.split("="); if (pair.length != 2) { log("&cNo value provided for: &7" + element); return false; } final String key = pair[0].toLowerCase(); final String value = pair[1]; try { switch (key) { case "s": case "size": { SquarePlotWorld.PLOT_WIDTH_DEFAULT = Configuration.INTEGER.parseString(value).shortValue(); break; } case "g": case "gap": { SquarePlotWorld.ROAD_WIDTH_DEFAULT = Configuration.INTEGER.parseString(value).shortValue(); break; } case "h": case "height": { ClassicPlotWorld.PLOT_HEIGHT_DEFAULT = Configuration.INTEGER.parseString(value); ClassicPlotWorld.ROAD_HEIGHT_DEFAULT = Configuration.INTEGER.parseString(value); ClassicPlotWorld.WALL_HEIGHT_DEFAULT = Configuration.INTEGER.parseString(value); break; } case "f": case "floor": { ClassicPlotWorld.TOP_BLOCK_DEFAULT = Configuration.BLOCKLIST.parseString(value); break; } case "m": case "main": { ClassicPlotWorld.MAIN_BLOCK_DEFAULT = Configuration.BLOCKLIST.parseString(value); break; } case "w": case "wall": { ClassicPlotWorld.WALL_FILLING_DEFAULT = Configuration.BLOCK.parseString(value); break; } case "b": case "border": { ClassicPlotWorld.WALL_BLOCK_DEFAULT = Configuration.BLOCK.parseString(value); break; } default: { log("&cKey not found: &7" + element); return false; } } } catch (final Exception e) { e.printStackTrace(); log("&cInvalid value: &7" + value + " in arg " + element); return false; } } try { final String root = "worlds." + world; if (!config.contains(root)) { config.createSection(root); } plotworld.saveConfiguration(config.getConfigurationSection(root)); ClassicPlotWorld.PLOT_HEIGHT_DEFAULT = height; ClassicPlotWorld.ROAD_HEIGHT_DEFAULT = height; ClassicPlotWorld.WALL_HEIGHT_DEFAULT = height; ClassicPlotWorld.TOP_BLOCK_DEFAULT = floor; ClassicPlotWorld.MAIN_BLOCK_DEFAULT = main; ClassicPlotWorld.WALL_BLOCK_DEFAULT = border; ClassicPlotWorld.WALL_FILLING_DEFAULT = wall; SquarePlotWorld.PLOT_WIDTH_DEFAULT = width; SquarePlotWorld.ROAD_WIDTH_DEFAULT = gap; } catch (final Exception e) { e.printStackTrace(); } } return true; } public boolean canUpdate(String current, String other) { String s1 = normalisedVersion(current); String s2 = normalisedVersion(other); int cmp = s1.compareTo(s2); return cmp < 0; } public String normalisedVersion(String version) { return normalisedVersion(version, ".", 4); } public String normalisedVersion(String version, String sep, int maxWidth) { String[] split = Pattern.compile(sep, Pattern.LITERAL).split(version); StringBuilder sb = new StringBuilder(); for (String s : split) { sb.append(String.format("%" + maxWidth + 's', s)); } return sb.toString(); } /** * Gets the default update URL, or null if the plugin is up to date * @return */ public URL getUpdate() { String resource = "plotsquared.1177"; String url = "https://www.spigotmc.org/resources/" + resource + "/history"; String download = ""; try { URL history = new URL(url); URLConnection con = history.openConnection(); con.addRequestProperty("User-Agent", "Mozilla/4.0"); InputStream stream = con.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(stream)); String l; URL link = null; String cur_ver = config.getString("version"); String new_ver = null; while ((l = in.readLine()) != null) { if (l.length() > version.length() && l.startsWith(version)) { new_ver = l.substring(version.length(), l.length() - 5); break; } if (link == null && l.length() > download.length() && l.startsWith(download)) { String subString = l.substring(download.length()); link = new URL("https://www.spigotmc.org/resources/" + resource + "/download?version=" + subString.substring(0, subString.indexOf("\""))); continue; } } stream.close(); in.close(); if (new_ver == null || !canUpdate(cur_ver, new_ver)) { PS.log("&7PlotSquared is already up to date!"); return null; } if (link == null) { PS.log("&dCould not check for updates"); PS.log("&7 - Manually check for updates: " + url); return null; } return link; } catch (Exception e) { PS.log("&dCould not check for updates"); PS.log("&7 - Manually check for updates: " + url); return null; } } public boolean update(URL url) { if (url == null) { return false; } try { File jar = PS.get().IMP.getFile(); File newJar = new File("plugins/update/PlotSquared.jar"); PS.log("&6Downloading from provided URL: &7" + url); PS.log("&7 - User-Agent: " + "Mozilla/4.0"); URLConnection con = url.openConnection(); con.addRequestProperty("User-Agent", "Mozilla/4.0"); InputStream stream = con.getInputStream(); File parent = newJar.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } PS.log("&7 - Output: " + newJar); newJar.delete(); Files.copy(stream, newJar.toPath()); stream.close(); PS.log("&6Disabling PlotSquared"); PS.get().IMP.disable(); System.out.println("Deleting file: " + jar); jar.delete(); System.out.println("Copying: " + jar + " >> " + newJar); try { Files.move(newJar.toPath(), jar.toPath(), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { System.out.println("Failed to reload PlotSquared"); System.out.println(" - Restart the server manually"); System.out.println("============ Stacktrace ============"); e.printStackTrace(); System.out.println("===================================="); return false; } Bukkit.reload(); return true; } catch (Exception e) { System.out.println("Failed to update PlotSquared"); System.out.println(" - Please update manually"); System.out.println("============ Stacktrace ============"); e.printStackTrace(); System.out.println("===================================="); } return false; } /** * Get the database connection * @return The database connection */ public Connection getConnection() { return connection; } /** * Copy a file from inside the jar to a location * @param file Name of the file inside PlotSquared.jar * @param folder The output location relative to /plugins/PlotSquared/ */ public void copyFile(String file, String folder) { try { byte[] buffer = new byte[2048]; File output = IMP.getDirectory(); if (!output.exists()) { output.mkdirs(); } File newFile = new File((output + File.separator + folder + File.separator + file)); if (newFile.exists()) { return; } ZipInputStream zis = new ZipInputStream(new FileInputStream(FILE)); ZipEntry ze = zis.getNextEntry(); while (ze != null) { String name = ze.getName(); if (name.equals(file)) { new File(newFile.getParent()).mkdirs(); FileOutputStream fos = new FileOutputStream(newFile); int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } fos.close(); ze = null; } else { ze = zis.getNextEntry(); } } zis.closeEntry(); zis.close(); } catch (Exception e) { e.printStackTrace(); log("&cCould not save " + file); } } /** * Close the database connection */ public void disable() { try { database.closeConnection(); } catch (NullPointerException | SQLException e) { log("&cCould not close database connection!"); } } /** * Setup the database connection */ public void setupDatabase() { if (Settings.DB.USE_MYSQL) { try { database = new MySQL(Settings.DB.HOST_NAME, Settings.DB.PORT, Settings.DB.DATABASE, Settings.DB.USER, Settings.DB.PASSWORD); connection = database.openConnection(); { if (DBFunc.dbManager == null) { DBFunc.dbManager = new SQLManager(connection, Settings.DB.PREFIX); } DBFunc.createTables("mysql"); } } catch (final Exception e) { log("&c[Plots] MySQL is not setup correctly. The plugin will disable itself."); if ((config == null) || config.getBoolean("debug")) { log("&d==== Here is an ugly stacktrace if you are interested in those things ===="); e.printStackTrace(); log("&d==== End of stacktrace ===="); log("&6Please go to the PlotSquared 'storage.yml' and configure MySQL correctly."); } IMP.disable(); return; } plots = DBFunc.getPlots(); if (Settings.ENABLE_CLUSTERS) { ClusterManager.clusters = DBFunc.getClusters(); } } else if (Settings.DB.USE_MONGO) { // DBFunc.dbManager = new MongoManager(); log(C.PREFIX.s() + "MongoDB is not yet implemented"); } else if (Settings.DB.USE_SQLITE) { try { this.database = new SQLite(IMP.getDirectory() + File.separator + Settings.DB.SQLITE_DB + ".db"); connection = this.database.openConnection(); { DBFunc.dbManager = new SQLManager(connection, Settings.DB.PREFIX); final DatabaseMetaData meta = connection.getMetaData(); meta.getTables(null, null, Settings.DB.PREFIX + "plot", null); DBFunc.createTables("sqlite"); } } catch (final Exception e) { log(C.PREFIX.s() + "&cFailed to open SQLite connection. The plugin will disable itself."); log("&9==== Here is an ugly stacktrace, if you are interested in those things ==="); e.printStackTrace(); IMP.disable(); return; } plots = DBFunc.getPlots(); if (Settings.ENABLE_CLUSTERS) { ClusterManager.clusters = DBFunc.getClusters(); } } else { log(C.PREFIX + "&cNo storage type is set!"); IMP.disable(); } } /** * Setup the default flags for PlotSquared
* - Create the flags * - Register with FlagManager and parse raw flag values */ public void setupDefaultFlags() { final List booleanFlags = Arrays.asList("notify-enter", "notify-leave", "item-drop", "invincible", "instabreak", "drop-protection", "forcefield", "titles", "pve", "pvp", "no-worldedit", "redstone", "keep"); final List intervalFlags = Arrays.asList("feed", "heal"); final List stringFlags = Arrays.asList("greeting", "farewell"); final List intFlags = Arrays.asList("entity-cap", "mob-cap", "animal-cap", "hostile-cap", "vehicle-cap", "music"); for (final String flag : stringFlags) { FlagManager.addFlag(new AbstractFlag(flag)); } for (final String flag : intervalFlags) { FlagManager.addFlag(new AbstractFlag(flag, new FlagValue.IntervalValue())); } for (final String flag : booleanFlags) { FlagManager.addFlag(new AbstractFlag(flag, new FlagValue.BooleanValue())); } for (final String flag : intFlags) { FlagManager.addFlag(new AbstractFlag(flag, new FlagValue.UnsignedIntegerValue())); } FlagManager.addFlag(new AbstractFlag("modified-blocks", new FlagValue.IntegerValue()), true); FlagManager.addFlag(new AbstractFlag("analysis", new FlagValue.DoubleListValue()), true); FlagManager.addFlag(new AbstractFlag("disable-physics", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("fly", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("explosion", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("mob-place", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("hostile-interact", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("hostile-attack", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("animal-interact", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("animal-attack", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("tamed-interact", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("tamed-attack", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("misc-interact", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("misc-place", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("misc-break", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("hanging-interact", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("hanging-place", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("hanging-break", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("vehicle-use", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("vehicle-place", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("vehicle-break", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("device-interact", new FlagValue.BooleanValue())); FlagManager.addFlag(new AbstractFlag("place", new FlagValue.PlotBlockListValue())); FlagManager.addFlag(new AbstractFlag("break", new FlagValue.PlotBlockListValue())); FlagManager.addFlag(new AbstractFlag("use", new FlagValue.PlotBlockListValue())); FlagManager.addFlag(new AbstractFlag("gamemode") { public String parseValueRaw(final String value) { switch (value) { case "creative": case "c": case "1": return "creative"; case "survival": case "s": case "0": return "survival"; case "adventure": case "a": case "2": return "adventure"; default: return null; } } public String getValueDesc() { return "Flag value must be a gamemode: 'creative' , 'survival' or 'adventure'"; } }); FlagManager.addFlag(new AbstractFlag("price", new FlagValue.UnsignedDoubleValue())); FlagManager.addFlag(new AbstractFlag("time", new FlagValue.LongValue())); FlagManager.addFlag(new AbstractFlag("weather") { public String parseValueRaw(final String value) { switch (value) { case "rain": case "storm": case "on": return "rain"; case "lightning": case "thunder": return "thunder"; case "clear": case "off": case "sun": return "clear"; default: return null; } } public String getValueDesc() { return "Flag value must be weather type: 'clear' or 'rain'"; } }); } /** * Setup the default configuration (settings.yml) */ public void setupConfig() { LAST_VERSION = config.getString("version"); config.set("version", VERSION); final Map options = new HashMap<>(); // Command confirmation options.put("confirmation.clear", Settings.CONFIRM_CLEAR); options.put("confirmation.delete", Settings.CONFIRM_DELETE); options.put("confirmation.unlink", Settings.CONFIRM_UNLINK); // Protection options.put("protection.redstone.disable-offline", Settings.REDSTONE_DISABLER); options.put("protection.tnt-listener.enabled", Settings.TNT_LISTENER); options.put("protection.piston.falling-blocks", Settings.PISTON_FALLING_BLOCK_CHECK); // Clusters options.put("clusters.enabled", Settings.ENABLE_CLUSTERS); // PlotMe options.put("plotme-alias", Settings.USE_PLOTME_ALIAS); options.put("plotme-convert.enabled", Settings.CONVERT_PLOTME); options.put("plotme-convert.cache-uuids", Settings.CACHE_PLOTME); // UUID options.put("UUID.offline", Settings.OFFLINE_MODE); options.put("UUID.force-lowercase", Settings.UUID_LOWERCASE); options.put("uuid.read-from-disk", Settings.UUID_FROM_DISK); // Mob stuff options.put("kill_road_mobs", Settings.KILL_ROAD_MOBS_DEFAULT); options.put("mob_pathfinding", Settings.MOB_PATHFINDING_DEFAULT); // Clearing + Expiry options.put("clear.fastmode", Settings.ENABLE_CLUSTERS); options.put("clear.on.ban", false); options.put("clear.auto.enabled", false); options.put("clear.auto.days", 365); options.put("clear.auto.clear-interval-seconds", Settings.CLEAR_INTERVAL); options.put("clear.auto.calibration.changes", 64); options.put("clear.auto.calibration.faces", 32); options.put("clear.auto.calibration.data", 1); options.put("clear.auto.calibration.air", 32); options.put("clear.auto.calibration.variety", 1); options.put("clear.auto.calibration.changes_sd", 64); options.put("clear.auto.calibration.faces_sd", 32); options.put("clear.auto.calibration.data_sd", 1); options.put("clear.auto.calibration.air_sd", 32); options.put("clear.auto.calibration.variety_sd", 1); options.put("clear.auto.threshold-percent", Settings.CLEAR_THRESHOLD); options.put("clear.ignore-if-modified", Settings.MIN_BLOCKS_CHANGED_IGNORED); // Schematics options.put("schematics.save_path", Settings.SCHEMATIC_SAVE_PATH); // Web options.put("web.url", Settings.WEB_URL); options.put("web.server-ip", Settings.WEB_IP); // Caching options.put("cache.permissions", Settings.PERMISSION_CACHING); options.put("cache.ratings", Settings.CACHE_RATINGS); // Titles options.put("titles", Settings.TITLES); // Teleportation options.put("teleport.on_login", Settings.TELEPORT_ON_LOGIN); options.put("teleport.delay", 0); // WorldEdit options.put("worldedit.require-selection-in-mask", Settings.REQUIRE_SELECTION); options.put("worldedit.enable-for-helpers", Settings.WE_ALLOW_HELPER); options.put("worldedit.max-volume", Settings.WE_MAX_VOLUME); options.put("worldedit.max-iterations", Settings.WE_MAX_ITERATIONS); options.put("worldedit.blacklist", Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks")); // Chunk processor options.put("chunk-processor.enabled", Settings.CHUNK_PROCESSOR); options.put("chunk-processor.max-blockstates", Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES); options.put("chunk-processor.max-entities", Settings.CHUNK_PROCESSOR_MAX_ENTITIES); // Comments options.put("comments.notifications.enabled", Settings.COMMENT_NOTIFICATIONS); // Plot limits options.put("global_limit", Settings.GLOBAL_LIMIT); options.put("max_plots", Settings.MAX_PLOTS); options.put("claim.max-auto-area", Settings.MAX_AUTO_SIZE); // Misc options.put("console.color", Settings.CONSOLE_COLOR); options.put("chat.fancy", Settings.FANCY_CHAT); options.put("metrics", true); options.put("debug", true); options.put("auto_update", false); for (final Entry node : options.entrySet()) { if (!config.contains(node.getKey())) { config.set(node.getKey(), node.getValue()); } } // Command confirmation Settings.CONFIRM_CLEAR = config.getBoolean("confirmation.clear"); Settings.CONFIRM_DELETE = config.getBoolean("confirmation.delete"); Settings.CONFIRM_UNLINK = config.getBoolean("confirmation.unlink"); // Protection Settings.REDSTONE_DISABLER = config.getBoolean("protection.redstone.disable-offline"); Settings.TNT_LISTENER = config.getBoolean("protection.tnt-listener.enabled"); Settings.PISTON_FALLING_BLOCK_CHECK = config.getBoolean("protection.piston.falling-blocks"); // Clusters Settings.ENABLE_CLUSTERS = config.getBoolean("clusters.enabled"); // PlotMe Settings.USE_PLOTME_ALIAS = config.getBoolean("plotme-alias"); Settings.CONVERT_PLOTME = config.getBoolean("plotme-convert.enabled"); Settings.CACHE_PLOTME = config.getBoolean("plotme-convert.cache-uuids"); // UUID Settings.OFFLINE_MODE = config.getBoolean("UUID.offline"); Settings.UUID_LOWERCASE = Settings.OFFLINE_MODE && config.getBoolean("UUID.force-lowercase"); Settings.UUID_FROM_DISK = config.getBoolean("uuid.read-from-disk"); // Mob stuff Settings.KILL_ROAD_MOBS = config.getBoolean("kill_road_mobs"); Settings.MOB_PATHFINDING = config.getBoolean("mob_pathfinding"); // Clearing + Expiry Settings.FAST_CLEAR = config.getBoolean("clear.fastmode"); Settings.DELETE_PLOTS_ON_BAN = config.getBoolean("clear.on.ban"); Settings.MIN_BLOCKS_CHANGED_IGNORED = config.getInt("clear.ignore-if-modified"); Settings.AUTO_CLEAR_DAYS = config.getInt("clear.auto.days"); Settings.CLEAR_THRESHOLD = config.getInt("clear.auto.threshold-percent"); Settings.AUTO_CLEAR = config.getBoolean("clear.auto.enabled"); Settings.CLEAR_INTERVAL = config.getInt("clear.auto.clear-interval-seconds"); // Clearing modifiers PlotAnalysis.MODIFIERS.changes = config.getInt("clear.auto.calibration.changes"); PlotAnalysis.MODIFIERS.faces = config.getInt("clear.auto.calibration.faces"); PlotAnalysis.MODIFIERS.data = config.getInt("clear.auto.calibration.data"); PlotAnalysis.MODIFIERS.air = config.getInt("clear.auto.calibration.air"); PlotAnalysis.MODIFIERS.variety = config.getInt("clear.auto.calibration.variety"); PlotAnalysis.MODIFIERS.changes_sd = config.getInt("clear.auto.calibration.changes_sd"); PlotAnalysis.MODIFIERS.faces_sd = config.getInt("clear.auto.calibration.faces_sd"); PlotAnalysis.MODIFIERS.data_sd = config.getInt("clear.auto.calibration.data_sd"); PlotAnalysis.MODIFIERS.air_sd = config.getInt("clear.auto.calibration.air_sd"); PlotAnalysis.MODIFIERS.variety_sd = config.getInt("clear.auto.calibration.variety_sd"); // Schematics Settings.SCHEMATIC_SAVE_PATH = config.getString("schematics.save_path"); // Web Settings.WEB_URL = config.getString("web.url"); Settings.WEB_IP = config.getString("web.server-ip"); // Caching Settings.PERMISSION_CACHING = config.getBoolean("cache.permissions"); Settings.CACHE_RATINGS = config.getBoolean("cache.ratings"); // Rating system Settings.RATING_CATEGORIES = config.getStringList("ratings.categories"); // Titles Settings.TITLES = config.getBoolean("titles"); // Teleportation Settings.TELEPORT_DELAY = config.getInt("teleport.delay"); Settings.TELEPORT_ON_LOGIN = config.getBoolean("teleport.on_login"); // WorldEdit Settings.REQUIRE_SELECTION = config.getBoolean("worldedit.require-selection-in-mask"); Settings.WE_ALLOW_HELPER = config.getBoolean("worldedit.enable-for-helpers"); Settings.WE_MAX_VOLUME = config.getLong("worldedit.max-volume"); Settings.WE_MAX_ITERATIONS = config.getLong("worldedit.max-iterations"); Settings.WE_BLACKLIST = config.getStringList("worldedit.blacklist"); // Chunk processor Settings.CHUNK_PROCESSOR = config.getBoolean("chunk-processor.enabled"); Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES = config.getInt("chunk-processor.max-blockstates"); Settings.CHUNK_PROCESSOR_MAX_ENTITIES= config.getInt("chunk-processor.max-entities"); // Comments Settings.COMMENT_NOTIFICATIONS = config.getBoolean("comments.notifications.enabled"); // Plot limits Settings.MAX_AUTO_SIZE = config.getInt("claim.max-auto-area"); Settings.MAX_PLOTS = config.getInt("max_plots"); if (Settings.MAX_PLOTS > 32767) { log("&c`max_plots` Is set too high! This is a per player setting and does not need to be very large."); Settings.MAX_PLOTS = 32767; } Settings.GLOBAL_LIMIT = config.getBoolean("global_limit"); // Misc Settings.DEBUG = config.getBoolean("debug"); if (Settings.DEBUG) { log(C.PREFIX.s() + "&6Debug Mode Enabled (Default). Edit the config to turn this off."); } Settings.CONSOLE_COLOR = config.getBoolean("console.color"); if (!config.getBoolean("chat.fancy") || !IMP.checkVersion(1, 8, 0)) { Settings.FANCY_CHAT = false; } Settings.METRICS = config.getBoolean("metrics"); } /** * Setup all configuration files
* - Config: settings.yml
* - Storage: storage.yml
* - Translation: PlotSquared.use_THIS.yml, style.yml
*/ public void setupConfigs() { final File folder = new File(IMP.getDirectory() + File.separator + "config"); if (!folder.exists() && !folder.mkdirs()) { log(C.PREFIX.s() + "&cFailed to create the /plugins/config folder. Please create it manually."); } try { styleFile = new File(IMP.getDirectory() + File.separator + "translations" + File.separator + "style.yml"); if (!styleFile.exists()) { if (!styleFile.getParentFile().exists()) { styleFile.getParentFile().mkdirs(); } if (!styleFile.createNewFile()) { log("Could not create the style file, please create \"translations/style.yml\" manually"); } } style = YamlConfiguration.loadConfiguration(styleFile); setupStyle(); } catch (final Exception err) { err.printStackTrace(); Logger.add(LogLevel.DANGER, "Failed to save style.yml"); log("failed to save style.yml"); } try { configFile = new File(IMP.getDirectory() + File.separator + "config" + File.separator + "settings.yml"); if (!configFile.exists()) { if (!configFile.createNewFile()) { log("Could not create the settings file, please create \"settings.yml\" manually."); } } config = YamlConfiguration.loadConfiguration(configFile); setupConfig(); } catch (final Exception err_trans) { Logger.add(LogLevel.DANGER, "Failed to save settings.yml"); log("Failed to save settings.yml"); } try { storageFile = new File(IMP.getDirectory() + File.separator + "config" + File.separator + "storage.yml"); if (!storageFile.exists()) { if (!storageFile.createNewFile()) { log("Could not the storage settings file, please create \"storage.yml\" manually."); } } storage = YamlConfiguration.loadConfiguration(storageFile); setupStorage(); } catch (final Exception err_trans) { Logger.add(LogLevel.DANGER, "Failed to save storage.yml"); log("Failed to save storage.yml"); } try { style.save(styleFile); config.save(configFile); storage.save(storageFile); } catch (final IOException e) { Logger.add(LogLevel.DANGER, "Configuration file saving failed"); e.printStackTrace(); } } /** * Setup the storage file (load + save missing nodes) */ private void setupStorage() { storage.set("version", VERSION); final Map options = new HashMap<>(); options.put("mysql.use", false); options.put("sqlite.use", true); options.put("sqlite.db", "storage"); options.put("mysql.host", "localhost"); options.put("mysql.port", "3306"); options.put("mysql.user", "root"); options.put("mysql.password", "password"); options.put("mysql.database", "plot_db"); options.put("prefix", ""); for (final Entry node : options.entrySet()) { if (!storage.contains(node.getKey())) { storage.set(node.getKey(), node.getValue()); } } Settings.DB.USE_MYSQL = storage.getBoolean("mysql.use"); Settings.DB.USER = storage.getString("mysql.user"); Settings.DB.PASSWORD = storage.getString("mysql.password"); Settings.DB.HOST_NAME = storage.getString("mysql.host"); Settings.DB.PORT = storage.getString("mysql.port"); Settings.DB.DATABASE = storage.getString("mysql.database"); Settings.DB.USE_SQLITE = storage.getBoolean("sqlite.use"); Settings.DB.SQLITE_DB = storage.getString("sqlite.db"); Settings.DB.PREFIX = storage.getString("prefix"); Settings.METRICS = config.getBoolean("metrics"); Settings.AUTO_CLEAR = config.getBoolean("clear.auto.enabled"); Settings.AUTO_CLEAR_DAYS = config.getInt("clear.auto.days"); Settings.DELETE_PLOTS_ON_BAN = config.getBoolean("clear.on.ban"); } /** * Show startup debug information */ public void showDebug() { if (Settings.DEBUG) { final Map settings = new HashMap<>(); settings.put("Kill Road Mobs", "" + Settings.KILL_ROAD_MOBS); settings.put("Use Metrics", "" + Settings.METRICS); settings.put("Delete Plots On Ban", "" + Settings.DELETE_PLOTS_ON_BAN); settings.put("Mob Pathfinding", "" + Settings.MOB_PATHFINDING); settings.put("DB Mysql Enabled", "" + Settings.DB.USE_MYSQL); settings.put("DB SQLite Enabled", "" + Settings.DB.USE_SQLITE); settings.put("Auto Clear Enabled", "" + Settings.AUTO_CLEAR); settings.put("Auto Clear Days", "" + Settings.AUTO_CLEAR_DAYS); settings.put("Schematics Save Path", "" + Settings.SCHEMATIC_SAVE_PATH); settings.put("API Location", "" + Settings.API_URL); for (final Entry setting : settings.entrySet()) { log(C.PREFIX.s() + String.format("&cKey: &6%s&c, Value: &6%s", setting.getKey(), setting.getValue())); } } } /** * Setup the style.yml file */ private void setupStyle() { style.set("version", VERSION); final Map o = new HashMap<>(); o.put("color.1", "6"); o.put("color.2", "7"); o.put("color.3", "8"); o.put("color.4", "3"); if (!style.contains("color")) { for (final Entry node : o.entrySet()) { style.set(node.getKey(), node.getValue()); } } } /** * Get the java version * @return Java version as a double */ public double getJavaVersion() { return Double.parseDouble(System.getProperty("java.specification.version")); } /** * Get the list of plot world names * @return Set of world names (String) */ public Set getPlotWorlds() { return plotworlds.keySet(); } /** * Get a list of PlotWorld objects * @return Collection of PlotWorld objects */ public Collection getPlotWorldObjects() { return plotworlds.values(); } }