mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2024-11-26 23:26:45 +01:00
1690 lines
66 KiB
Java
1690 lines
66 KiB
Java
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.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 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.PlotFilter;
|
|
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.MathMan;
|
|
import com.intellectualcrafters.plot.util.StringMan;
|
|
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.intellectualcrafters.plot.util.bukkit.uuid.FileUUIDHandler;
|
|
import com.intellectualcrafters.plot.util.bukkit.uuid.SQLUUIDHandler;
|
|
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<String, PlotWorld> plotworlds = new HashMap<>();
|
|
private final HashMap<String, PlotManager> 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<String, HashMap<PlotId, Plot>> 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.setUUIDWrapper(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<PlotId, Plot>());
|
|
}
|
|
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<PlotId, Plot>());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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<String, HashMap<PlotId, Plot>> getAllPlotsRaw() {
|
|
return plots;
|
|
}
|
|
|
|
/**
|
|
* A more generic way to filter plots - make your own method if you need complex filters
|
|
* @param filters
|
|
* @return
|
|
*/
|
|
public Set<Plot> getPlots(PlotFilter... filters) {
|
|
HashSet<Plot> set = new HashSet<>();
|
|
for (Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
|
|
for (PlotFilter filter : filters) {
|
|
if (!filter.allowsWorld(entry.getKey())) {
|
|
continue;
|
|
}
|
|
}
|
|
for (Plot plot : entry.getValue().values()) {
|
|
for (PlotFilter filter : filters) {
|
|
if (!filter.allowsPlot(plot)) {
|
|
continue;
|
|
}
|
|
}
|
|
set.add(plot);
|
|
}
|
|
}
|
|
return set;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Set all the plots as a raw object
|
|
* @see #getAllPlotsRaw() to get the raw plot object
|
|
* @param plots
|
|
*/
|
|
public void setAllPlotsRaw(final LinkedHashMap<String, HashMap<PlotId, Plot>> plots) {
|
|
this.plots = plots;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get all the plots in a single set
|
|
* @return Set of Plot
|
|
*/
|
|
public Set<Plot> getPlots() {
|
|
final ArrayList<Plot> newplots = new ArrayList<>();
|
|
for (final Entry<String, HashMap<PlotId, Plot>> 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<Plot> getPlotsRaw() {
|
|
final ArrayList<Plot> newplots = new ArrayList<>();
|
|
for (final Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
|
|
newplots.addAll(entry.getValue().values());
|
|
}
|
|
return new LinkedHashSet<>(newplots);
|
|
}
|
|
|
|
|
|
/**
|
|
* Sort a collection of plots by the hashcode (assumes that all plots are in the same world)
|
|
* @param plots
|
|
* @return ArrayList of plot
|
|
*/
|
|
@Deprecated
|
|
public ArrayList<Plot> sortPlots(Collection<Plot> plots) {
|
|
return sortPlotsByWorld(plots);
|
|
}
|
|
|
|
/**
|
|
* Sort plots by hashcode
|
|
* @param plots
|
|
* @return
|
|
*/
|
|
public ArrayList<Plot> sortPlotsByHash(Collection<Plot> plots) {
|
|
int hardmax = 256000;
|
|
int max = 0;
|
|
int overflowSize = 0;
|
|
for (Plot plot : plots) {
|
|
int hash = MathMan.getPositiveId(plot.hashCode());
|
|
if (hash > max) {
|
|
if (hash >= hardmax) {
|
|
overflowSize++;
|
|
}
|
|
else {
|
|
max = hash;
|
|
}
|
|
}
|
|
}
|
|
hardmax = Math.min(hardmax, max);
|
|
Plot[] cache = new Plot[hardmax + 1];
|
|
List<Plot> overflow = new ArrayList<Plot>(overflowSize);
|
|
for (Plot plot : plots) {
|
|
int hash = MathMan.getPositiveId(plot.hashCode());
|
|
if (hash < hardmax) {
|
|
cache[hash] = plot;
|
|
}
|
|
else {
|
|
overflow.add(plot);
|
|
}
|
|
}
|
|
Plot[] overflowArray = overflow.toArray(new Plot[overflow.size()]);
|
|
sortPlotsByHash(overflowArray);
|
|
ArrayList<Plot> result = new ArrayList<Plot>(cache.length + overflowArray.length);
|
|
for (Plot plot : cache) {
|
|
if (plot != null) {
|
|
result.add(plot);
|
|
}
|
|
}
|
|
for (Plot plot : overflowArray) {
|
|
result.add(plot);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static void sortPlotsByHash(Plot[] input) {
|
|
final int SIZE = 100;
|
|
List<Plot>[] bucket = new ArrayList[SIZE];
|
|
for (int i = 0; i < bucket.length; i++) {
|
|
bucket[i] = new ArrayList<Plot>();
|
|
}
|
|
boolean maxLength = false;
|
|
int tmp = -1, placement = 1;
|
|
while (!maxLength) {
|
|
maxLength = true;
|
|
for (Plot i : input) {
|
|
tmp = MathMan.getPositiveId(i.hashCode()) / placement;
|
|
bucket[tmp % SIZE].add(i);
|
|
if (maxLength && tmp > 0) {
|
|
maxLength = false;
|
|
}
|
|
}
|
|
int a = 0;
|
|
for (int b = 0; b < SIZE; b++) {
|
|
for (Plot i : bucket[b]) {
|
|
input[a++] = i;
|
|
}
|
|
bucket[b].clear();
|
|
}
|
|
placement *= SIZE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sort a collection of plots by world (with a priority world), then by hashcode
|
|
* @param plots
|
|
* @param priorityWorld - Use "world" or "gibberish" if you don't care
|
|
* @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<Plot> sortPlots(Collection<Plot> plots, final String priorityWorld) {
|
|
// group by world
|
|
// sort each
|
|
HashMap<String, Collection<Plot>> map = new HashMap<>();
|
|
ArrayList<String> worlds = new ArrayList<String>(getPlotWorlds());
|
|
int totalSize = 0;
|
|
for (Entry<String, HashMap<PlotId, Plot>> entry : this.plots.entrySet()) {
|
|
totalSize += entry.getValue().size();
|
|
}
|
|
if (plots.size() == totalSize) {
|
|
for (Entry<String, HashMap<PlotId, Plot>> entry : this.plots.entrySet()) {
|
|
map.put(entry.getKey(), entry.getValue().values());
|
|
}
|
|
}
|
|
else {
|
|
for (String world : worlds) {
|
|
map.put(world, new ArrayList<Plot>(plots.size() / worlds.size()));
|
|
}
|
|
Collection<Plot> lastList = null;
|
|
String lastWorld = "";
|
|
for (Plot plot : plots) {
|
|
if (StringMan.isEqual(lastWorld, plot.world)) {
|
|
lastList.add(plot);
|
|
}
|
|
else {
|
|
lastWorld = plot.world;
|
|
lastList = map.get(lastWorld);
|
|
lastList.add(plot);
|
|
}
|
|
}
|
|
}
|
|
Collections.sort(worlds, new Comparator<String>() {
|
|
@Override
|
|
public int compare(String a, String b) {
|
|
if (StringMan.isEqual(a, priorityWorld)) {
|
|
return -1;
|
|
}
|
|
return a.hashCode() - b.hashCode();
|
|
}
|
|
});
|
|
ArrayList<Plot> toReturn = new ArrayList<Plot>(plots.size());
|
|
for (String world : worlds) {
|
|
toReturn.addAll(sortPlotsByHash(map.get(world)));
|
|
}
|
|
return toReturn;
|
|
}
|
|
|
|
|
|
/**
|
|
* 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<Plot> sortPlotsByWorld(Collection<Plot> plots) {
|
|
ArrayList<Plot> newPlots = new ArrayList<>();
|
|
ArrayList<String> worlds = new ArrayList<>(this.plots.keySet());
|
|
HashSet<Plot> set = new HashSet<>(plots);
|
|
Collections.sort(worlds);
|
|
for (String world : worlds) {
|
|
for (Plot plot : this.plots.get(world).values()) {
|
|
if (set.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<Plot> 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<Plot> 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<Plot> getPlots(final String world, final UUID uuid) {
|
|
final ArrayList<Plot> 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<String> 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<PlotId, Plot> 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<Plot> getPlots(final PlotPlayer player) {
|
|
return getPlots(player.getUUID());
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the plots for a UUID
|
|
* @param uuid
|
|
* @return Set of Plot
|
|
*/
|
|
public Set<Plot> getPlots(final UUID uuid) {
|
|
final ArrayList<Plot> 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<PlotId, Plot> 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<br>
|
|
* - Initializes the PlotWorld and PlotManager classes<br>
|
|
* - Registers the PlotWorld and PlotManager classes<br>
|
|
* - Loads (and/or generates) the PlotWorld configuration<br>
|
|
* - Sets up the world border if configured<br>
|
|
* If loading an augmented plot world:<br>
|
|
* - Creates the AugmentedPopulator classes<br>
|
|
* - 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<String> worlds = (config.contains("worlds") ? config.getConfigurationSection("worlds").getKeys(false) : new HashSet<String>());
|
|
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<br>
|
|
* e.g. /mv create <world> normal -g PlotSquared:<args>
|
|
* @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 = "<a href=\"resources/" + resource + "/download?version=";
|
|
String version = "<td class=\"version\">";
|
|
try {
|
|
URL history = new URL(url);
|
|
URLConnection con = history.openConnection();
|
|
con.addRequestProperty("User-Agent", "Mozilla/5.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(PlotPlayer sender, URL url) {
|
|
if (url == null) {
|
|
return false;
|
|
}
|
|
try {
|
|
File newJar = new File("plugins/update/PlotSquared.jar");
|
|
MainUtil.sendMessage(sender, "$1Downloading from provided URL: &7" + url);
|
|
MainUtil.sendMessage(sender, "$2 - 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();
|
|
}
|
|
MainUtil.sendMessage(sender, "$2 - Output: " + newJar);
|
|
newJar.delete();
|
|
Files.copy(stream, newJar.toPath());
|
|
stream.close();
|
|
MainUtil.sendMessage(sender, "$1The update will take effect when the server is restarted next");
|
|
return true;
|
|
}
|
|
catch (Exception e) {
|
|
MainUtil.sendMessage(sender, "Failed to update PlotSquared");
|
|
MainUtil.sendMessage(sender, " - Please update manually");
|
|
log("============ Stacktrace ============");
|
|
e.printStackTrace();
|
|
log("====================================");
|
|
}
|
|
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();
|
|
UUIDHandler.handleShutdown();
|
|
} 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<br>
|
|
* - Create the flags
|
|
* - Register with FlagManager and parse raw flag values
|
|
*/
|
|
public void setupDefaultFlags() {
|
|
final List<String> booleanFlags = Arrays.asList("notify-enter", "notify-leave", "item-drop", "invincible", "instabreak", "drop-protection", "forcefield", "titles", "pve", "pvp", "no-worldedit", "redstone", "keep");
|
|
final List<String> intervalFlags = Arrays.asList("feed", "heal");
|
|
final List<String> stringFlags = Arrays.asList("greeting", "farewell");
|
|
final List<String> 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("analysis", new FlagValue.IntegerListValue()), 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("blocked-cmds", new FlagValue.StringListValue()));
|
|
FlagManager.addFlag(new AbstractFlag("ice-met", new FlagValue.BooleanValue()));
|
|
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'";
|
|
}
|
|
});
|
|
FlagManager.addFlag(new AbstractFlag("description", new FlagValue.StringValue()), true);
|
|
}
|
|
|
|
|
|
/**
|
|
* Setup the default configuration (settings.yml)
|
|
*/
|
|
public void setupConfig() {
|
|
LAST_VERSION = config.getString("version");
|
|
config.set("version", VERSION);
|
|
|
|
final Map<String, Object> 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.use_sqluuidhandler", Settings.USE_SQLUUIDHANDLER);
|
|
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", 1);
|
|
options.put("clear.auto.calibration.faces", 2);
|
|
options.put("clear.auto.calibration.data", 32);
|
|
options.put("clear.auto.calibration.air", 0);
|
|
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", 0);
|
|
options.put("clear.auto.calibration.variety_sd", 1);
|
|
|
|
int keep = config.getInt("clear.keep-if-modified");
|
|
int ignore = config.getInt("clear.ignore-if-modified");
|
|
if (keep > 0 || ignore > 0) {
|
|
options.put("clear.auto.threshold", 1);
|
|
log("&cIMPORTANT MESSAGE ABOUT THIS UPDATE!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
|
log("&cSorry for all the exclamation marks, but this could be important.");
|
|
log("&cPlot clearing has changed to a new system that requires calibration.");
|
|
log("&cThis is how it will work: ");
|
|
log("&c - Players will rate plots");
|
|
log("&c - When enough plots are rated, you can run /plot debugexec calibrate-analysis");
|
|
log("&c - You can decide the (rough) percentage of expired plots to clear");
|
|
log("&c - To just clear all expired plot, ignore this and set: &7threshold: -1");
|
|
log("&cMore information:&7 https://github.com/IntellectualSites/PlotSquared/wiki/Plot-analysis:");
|
|
}
|
|
else {
|
|
options.put("clear.auto.threshold", Settings.CLEAR_THRESHOLD);
|
|
}
|
|
config.set("clear.keep-if-modified", null);
|
|
config.set("clear.ignore-if-modified", null);
|
|
|
|
// 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);
|
|
options.put("chunk-processor.disable-physics", Settings.CHUNK_PROCESSOR_DISABLE_PHYSICS);
|
|
|
|
// 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<String, Object> 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.USE_SQLUUIDHANDLER = config.getBoolean("uuid.use_sqluuidhandler");
|
|
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.AUTO_CLEAR_DAYS = config.getInt("clear.auto.days");
|
|
Settings.CLEAR_THRESHOLD = config.getInt("clear.auto.threshold");
|
|
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");
|
|
Settings.CHUNK_PROCESSOR_DISABLE_PHYSICS = config.getBoolean("chunk-processor.disable-physics");
|
|
|
|
// 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");
|
|
|
|
UUIDHandler.implementation = Settings.USE_SQLUUIDHANDLER ? new SQLUUIDHandler() : new FileUUIDHandler();
|
|
}
|
|
|
|
|
|
/**
|
|
* Setup all configuration files<br>
|
|
* - Config: settings.yml<br>
|
|
* - Storage: storage.yml<br>
|
|
* - Translation: PlotSquared.use_THIS.yml, style.yml<br>
|
|
*/
|
|
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<String, Object> 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<String, Object> 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<String, String> 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<String, String> 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<String, Object> 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<String, Object> 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<String> getPlotWorlds() {
|
|
return plotworlds.keySet();
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a list of PlotWorld objects
|
|
* @return Collection of PlotWorld objects
|
|
*/
|
|
public Collection<PlotWorld> getPlotWorldObjects() {
|
|
return plotworlds.values();
|
|
}
|
|
}
|