package com.intellectualcrafters.plot;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.configuration.MemorySection;
import com.intellectualcrafters.configuration.file.YamlConfiguration;
import com.intellectualcrafters.plot.commands.WE_Anywhere;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Configuration;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.config.Storage;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.database.Database;
import com.intellectualcrafters.plot.database.SQLManager;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.generator.HybridPlotWorld;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
import com.intellectualcrafters.plot.logger.DelegateLogger;
import com.intellectualcrafters.plot.logger.ILogger;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotCluster;
import com.intellectualcrafters.plot.object.PlotFilter;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.object.worlds.DefaultPlotAreaManager;
import com.intellectualcrafters.plot.object.worlds.PlotAreaManager;
import com.intellectualcrafters.plot.object.worlds.SinglePlotArea;
import com.intellectualcrafters.plot.object.worlds.SinglePlotAreaManager;
import com.intellectualcrafters.plot.util.AbstractTitle;
import com.intellectualcrafters.plot.util.ChatManager;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.CommentManager;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.InventoryUtil;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.ReflectionUtils;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.expiry.ExpireManager;
import com.intellectualcrafters.plot.util.expiry.ExpiryTask;
import com.plotsquared.listener.WESubscriber;
import com.sk89q.worldedit.WorldEdit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.sql.SQLException;
import java.util.ArrayDeque;
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.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* An implementation of the core, with a static getter for easy access.
*/
public class PS{
private static PS instance;
// Implementation
public final IPlotMain IMP;
// Implementation logger
private ILogger logger;
// Current thread
private final Thread thread;
// Platform / Version / Update URL
private final String platform;
private final int[] version;
private int[] lastVersion;
public URL update;
// WorldEdit instance
public WorldEdit worldedit;
// Files and configuration
private File jarFile = null; // This file
public File styleFile;
public File configFile;
public File worldsFile;
public File commandsFile;
public File translationFile;
private File storageFile;
public YamlConfiguration style;
public YamlConfiguration config;
public YamlConfiguration worlds;
public YamlConfiguration storage;
public YamlConfiguration commands;
// Temporary hold the plots/clusters before the worlds load
public HashMap<String, Set<PlotCluster>> clusters_tmp;
public HashMap<String, HashMap<PlotId, Plot>> plots_tmp;
private PlotAreaManager manager;
/**
* Initialize PlotSquared with the desired Implementation class.
* @param iPlotMain Implementation of {@link IPlotMain} used
* @param platform The platform being used
*/
public PS(IPlotMain iPlotMain, String platform) {
PS.instance = this;
this.thread = Thread.currentThread();
this.IMP = iPlotMain;
this.logger = iPlotMain;
this.platform = platform;
this.version = this.IMP.getPluginVersion();
try {
new ReflectionUtils(this.IMP.getNMSPackage());
try {
URL url = PS.class.getProtectionDomain().getCodeSource().getLocation();
this.jarFile = new File(new URL(url.toURI().toString().split("\\!")[0].replaceAll("jar:file", "file")).toURI().getPath());
} catch (MalformedURLException | URISyntaxException | SecurityException e) {
e.printStackTrace();
this.jarFile = new File(this.IMP.getDirectory().getParentFile(), "PlotSquared.jar");
if (!this.jarFile.exists()) {
this.jarFile = new File(this.IMP.getDirectory().getParentFile(), "PlotSquared-" + platform + ".jar");
}
}
if (getJavaVersion() < 1.8) {
PS.log(C.CONSOLE_JAVA_OUTDATED.f(IMP.getPluginName()));
}
TaskManager.IMP = this.IMP.getTaskManager();
setupConfigs();
this.translationFile =
MainUtil.getFile(this.IMP.getDirectory(), Settings.Paths.TRANSLATIONS + File.separator + IMP.getPluginName() + ".use_THIS.yml");
C.load(this.translationFile);
// Setup manager
if (Settings.Enabled_Components.WORLDS) {
this.manager = new SinglePlotAreaManager();
} else {
this.manager = new DefaultPlotAreaManager();
}
// Database
if (Settings.Enabled_Components.DATABASE) {
setupDatabase();
}
// Comments
CommentManager.registerDefaultInboxes();
// Kill entities
if (Settings.Enabled_Components.KILL_ROAD_MOBS || Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
this.IMP.runEntityTask();
}
if (Settings.Enabled_Components.EVENTS) {
this.IMP.registerPlayerEvents();
this.IMP.registerInventoryEvents();
this.IMP.registerPlotPlusEvents();
}
// Required
this.IMP.registerWorldEvents();
if (Settings.Enabled_Components.METRICS) {
this.IMP.startMetrics();
} else {
PS.log(C.CONSOLE_PLEASE_ENABLE_METRICS.f(IMP.getPluginName()));
}
if (Settings.Enabled_Components.CHUNK_PROCESSOR) {
this.IMP.registerChunkProcessor();
}
// create UUIDWrapper
UUIDHandler.implementation = this.IMP.initUUIDHandler();
if (Settings.Enabled_Components.UUID_CACHE) {
startUuidCatching();
} else {
// Start these separately
UUIDHandler.add(new StringWrapper("*"), DBFunc.everyone);
startExpiryTasks();
startPlotMeConversion();
}
// create event util class
EventUtil.manager = this.IMP.initEventUtil();
// create Hybrid utility class
HybridUtils.manager = this.IMP.initHybridUtils();
// Inventory utility class
InventoryUtil.manager = this.IMP.initInventoryUtil();
// create setup util class
SetupUtils.manager = this.IMP.initSetupUtils();
// World Util
WorldUtil.IMP = this.IMP.initWorldUtil();
// Set block
GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1);
GlobalBlockQueue.IMP.runTask();
// Set chunk
ChunkManager.manager = this.IMP.initChunkManager();
// Schematic handler
SchematicHandler.manager = this.IMP.initSchematicHandler();
// Titles
AbstractTitle.TITLE_CLASS = this.IMP.initTitleManager();
// Chat
ChatManager.manager = this.IMP.initChatManager();
// Commands
if (Settings.Enabled_Components.COMMANDS) {
this.IMP.registerCommands();
}
// WorldEdit
if (Settings.Enabled_Components.WORLDEDIT_RESTRICTIONS) {
try {
if (this.IMP.initWorldEdit()) {
PS.debug(IMP.getPluginName() + " hooked into WorldEdit.");
this.worldedit = WorldEdit.getInstance();
WorldEdit.getInstance().getEventBus().register(new WESubscriber());
if (Settings.Enabled_Components.COMMANDS) {
new WE_Anywhere();
}
}
} catch (Throwable e) {
PS.debug("Incompatible version of WorldEdit, please upgrade: http://builds.enginehub.org/job/worldedit?branch=master");
}
}
// Economy
if (Settings.Enabled_Components.ECONOMY) {
TaskManager.runTask(new Runnable() {
@Override
public void run() {
EconHandler.manager = PS.this.IMP.getEconomyHandler();
}
});
}
// Check for updates
if (Settings.Enabled_Components.UPDATER) {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
URL url = Updater.getUpdate();
if (url != null) {
PS.this.update = url;
} else if (PS.this.lastVersion == null) {
PS.log("&aThanks for installing " + IMP.getPluginName() + "!");
} else if (!get().checkVersion(PS.this.lastVersion, PS.this.version)) {
PS.log("&aThanks for updating from " + StringMan.join(PS.this.lastVersion, ".") + " to " + StringMan
.join(PS.this.version, ".") + "!");
DBFunc.updateTables(PS.this.lastVersion);
}
}
});
}
// World generators:
final ConfigurationSection section = this.worlds.getConfigurationSection("worlds");
if (section != null) {
for (String world : section.getKeys(false)) {
if (world.equals("CheckingPlotSquaredGenerator")) {
continue;
}
if (WorldUtil.IMP.isWorld(world)) {
this.IMP.setGenerator(world);
}
}
TaskManager.runTaskLater(new Runnable() {
@Override
public void run() {
for (String world : section.getKeys(false)) {
if (world.equals("CheckingPlotSquaredGenerator")) {
continue;
}
if (!WorldUtil.IMP.isWorld(world) && !world.equals("*")) {
debug("&c`" + world + "` was not properly loaded - " + IMP.getPluginName() + " will now try to load it properly: ");
debug("&8 - &7Are you trying to delete this world? Remember to remove it from the settings.yml, bukkit.yml and multiverse worlds.yml");
debug("&8 - &7Your world management plugin may be faulty (or non existent)");
PS.this.IMP.setGenerator(world);
}
}
}
}, 1);
}
// Copy files
copyFile("automerge.js", Settings.Paths.SCRIPTS);
copyFile("town.template", Settings.Paths.TEMPLATES);
copyFile("skyblock.template", Settings.Paths.TEMPLATES);
copyFile("german.yml", Settings.Paths.TRANSLATIONS);
copyFile("s_chinese_unescaped.yml", Settings.Paths.TRANSLATIONS);
copyFile("s_chinese.yml", Settings.Paths.TRANSLATIONS);
copyFile("italian.yml", Settings.Paths.TRANSLATIONS);
showDebug();
} catch (Throwable e) {
e.printStackTrace();
}
PS.log(C.ENABLED.f(IMP.getPluginName()));
}
/**
* Get an instance of PlotSquared.
*
* @return instance of PlotSquared
*/
public static PS get() {
return PS.instance;
}
public static IPlotMain imp() {
if (instance != null) {
return instance.IMP;
}
return null;
}
/**
* Log a message to the IPlotMain logger.
*
* @param message Message to log
* @see IPlotMain#log(String)
*/
public static void log(Object message) {
if (message == null || message.toString().isEmpty()) {
return;
}
PS.get().getLogger().log(StringMan.getString(message));
}
/**
* Log a message to the IPlotMain logger.
*
* @param message Message to log
* @see IPlotMain#log(String)
*/
public static void debug(Object message) {
if (Settings.DEBUG) {
PS.log(message);
}
}
/**
* Get the current logger.
*
* @return The assigned logger
*/
public ILogger getLogger() {
return logger;
}
public PlotAreaManager getPlotAreaManager() {
return manager;
}
/**
* Set the Logger.
* @see DelegateLogger
* @see #getLogger()
* @param logger the logger the plugin should use
*/
public void setLogger(ILogger logger) {
this.logger = logger;
}
private void startUuidCatching() {
TaskManager.runTaskLater(new Runnable() {
@Override
public void run() {
debug("Starting UUID caching");
UUIDHandler.startCaching(new Runnable() {
@Override
public void run() {
UUIDHandler.add(new StringWrapper("*"), DBFunc.everyone);
foreachPlotRaw(new RunnableVal<Plot>() {
@Override
public void run(Plot plot) {
if (plot.hasOwner() && plot.temp != -1) {
if (UUIDHandler.getName(plot.owner) == null) {
UUIDHandler.implementation.unknown.add(plot.owner);
}
}
}
});
startExpiryTasks();
startPlotMeConversion();
}
});
}
}, 20);
}
private void startExpiryTasks() {
if (Settings.Enabled_Components.PLOT_EXPIRY) {
ExpireManager.IMP = new ExpireManager();
ExpireManager.IMP.runAutomatedTask();
for (Settings.Auto_Clear settings : Settings.AUTO_CLEAR.getInstances()) {
ExpiryTask task = new ExpiryTask(settings);
ExpireManager.IMP.addTask(task);
}
}
}
private void startPlotMeConversion() {
if (Settings.Enabled_Components.PLOTME_CONVERTER || Settings.PlotMe.CACHE_UUDS) {
TaskManager.IMP.taskAsync(new Runnable() {
@Override
public void run() {
if (PS.this.IMP.initPlotMeConverter()) {
PS.log("&c=== IMPORTANT ===");
PS.log("&cTHIS MESSAGE MAY BE EXTREMELY HELPFUL IF YOU HAVE TROUBLE CONVERTING PlotMe!");
PS.log("&c - Make sure 'UUID.read-from-disk' is disabled (false)!");
PS.log("&c - Sometimes the database can be locked, deleting PlotMe.jar beforehand will fix the issue!");
PS.log("&c - After the conversion is finished, please set 'plotme-converter' to false in the "
+ "'settings.yml'");
}
Settings.Enabled_Components.PLOTME_CONVERTER = false;
}
});
}
}
public boolean isMainThread(Thread thread) {
return this.thread == thread;
}
/**
* Check if `version` is >= `version2`.
* @param version
* @param version2
* @return true if `version` is >= `version2`
*/
public boolean checkVersion(int[] version, int... version2) {
return version[0] > version2[0] || version[0] == version2[0] && version[1] > version2[1] || version[0] == version2[0]
&& version[1] == version2[1] && version[2] >= version2[2];
}
/**
* Get the last PlotSquared version.
* @return last version in config or null
*/
public int[] getLastVersion() {
return this.lastVersion;
}
/**
* Get the current PlotSquared version.
* @return current version in config or null
*/
public int[] getVersion() {
return this.version;
}
/**
* Get the server platform this plugin is running on this is running on.
*
* <p>This will be either <b>Bukkit</b> or <b>Sponge</b></p>
* @return the server implementation
*/
public String getPlatform() {
return this.platform;
}
public PlotManager getPlotManager(Plot plot) {
return plot.getArea().manager;
}
public PlotManager getPlotManager(Location location) {
PlotArea pa = getPlotAreaAbs(location);
return pa != null ? pa.manager : null;
}
/**
* Add a global reference to a plot world.
*
* @param plotArea the {@code PlotArea} to add.
* @see #removePlotArea(PlotArea) To remove the reference
*/
public void addPlotArea(PlotArea plotArea) {
HashMap<PlotId, Plot> plots;
if (plots_tmp == null || (plots = plots_tmp.remove(plotArea.toString())) == null) {
if (plotArea.TYPE == 2) {
plots = this.plots_tmp.get(plotArea.worldname);
if (plots != null) {
Iterator<Entry<PlotId, Plot>> iterator = plots.entrySet().iterator();
while (iterator.hasNext()) {
Entry<PlotId, Plot> next = iterator.next();
PlotId id = next.getKey();
if (plotArea.contains(id)) {
next.getValue().setArea(plotArea);
iterator.remove();
}
}
}
}
} else {
for (Plot entry : plots.values()) {
entry.setArea(plotArea);
}
}
Set<PlotCluster> clusters;
if (clusters_tmp == null || (clusters = clusters_tmp.remove(plotArea.toString())) == null) {
if (plotArea.TYPE == 2) {
clusters = this.clusters_tmp.get(plotArea.worldname);
if (clusters != null) {
Iterator<PlotCluster> iterator = clusters.iterator();
while (iterator.hasNext()) {
PlotCluster next = iterator.next();
if (next.intersects(plotArea.getMin(), plotArea.getMax())) {
next.setArea(plotArea);
iterator.remove();
}
}
}
}
} else {
for (PlotCluster cluster : clusters) {
cluster.setArea(plotArea);
}
}
manager.addPlotArea(plotArea);
plotArea.setupBorder();
}
/**
* Remove a plot world reference.
*
* @param area the {@code PlotArea} to remove
*/
public void removePlotArea(PlotArea area) {
manager.removePlotArea(area);
setPlotsTmp(area);
}
public void removePlotAreas(String world) {
for (PlotArea area : getPlotAreas(world)) {
if (area.worldname.equals(world)) {
removePlotArea(area);
}
}
}
private void setPlotsTmp(PlotArea area) {
if (this.plots_tmp == null) {
this.plots_tmp = new HashMap<>();
}
HashMap<PlotId, Plot> map = this.plots_tmp.get(area.toString());
if (map == null) {
map = new HashMap<>();
this.plots_tmp.put(area.toString(), map);
}
for (Plot plot : area.getPlots()) {
map.put(plot.getId(), plot);
}
if (this.clusters_tmp == null) {
this.clusters_tmp = new HashMap<>();
}
this.clusters_tmp.put(area.toString(), area.getClusters());
}
public Set<PlotCluster> getClusters(String world) {
HashSet<PlotCluster> set = new HashSet<>();
for (PlotArea area : getPlotAreas(world)) {
set.addAll(area.getClusters());
}
return set;
}
/**
* Get all the base plots in a single set (for merged plots it just returns
* the bottom plot).
* @return Set of base Plots
*/
public Set<Plot> getBasePlots() {
int size = getPlotCount();
final Set<Plot> result = new HashSet<>(size);
foreachPlotArea(new RunnableVal<PlotArea>() {
@Override
public void run(PlotArea value) {
for (Plot plot : value.getPlots()) {
if (!plot.isBasePlot()) {
continue;
}
result.add(plot);
}
}
});
return result;
}
public List<Plot> sortPlotsByTemp(Collection<Plot> plots) {
int max = 0;
int overflowCount = 0;
for (Plot plot : plots) {
if (plot.temp > 0) {
if (plot.temp > max) {
max = plot.temp;
}
} else {
overflowCount++;
}
}
Plot[] array = new Plot[max + 1];
List<Plot> overflow = new ArrayList<>(overflowCount);
for (Plot plot : plots) {
if (plot.temp <= 0) {
overflow.add(plot);
} else {
array[plot.temp] = plot;
}
}
ArrayList<Plot> result = new ArrayList<>(plots.size());
for (Plot plot : array) {
if (plot != null) {
result.add(plot);
}
}
Collections.sort(overflow, new Comparator<Plot>() {
@Override
public int compare(Plot a, Plot b) {
return a.hashCode() - b.hashCode();
}
});
result.addAll(overflow);
return result;
}
/**
* Sort plots by hashcode.
* @param plots the collection of plots to sort
* @return the sorted collection
* @deprecated Unchecked, please use
* {@link #sortPlots(Collection, SortType, PlotArea)} which has
* additional checks before calling this
*/
@Deprecated
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<>(overflowSize);
ArrayList<Plot> extra = new ArrayList<>();
for (Plot plot : plots) {
int hash = MathMan.getPositiveId(plot.hashCode());
if (hash < hardmax) {
if (hash >= 0) {
cache[hash] = plot;
} else {
extra.add(plot);
}
} else if (Math.abs(plot.getId().x) > 15446 || Math.abs(plot.getId().y) > 15446) {
extra.add(plot);
} else {
overflow.add(plot);
}
}
Plot[] overflowArray = overflow.toArray(new Plot[overflow.size()]);
sortPlotsByHash(overflowArray);
ArrayList<Plot> result = new ArrayList<>(cache.length + overflowArray.length);
for (Plot plot : cache) {
if (plot != null) {
result.add(plot);
}
}
Collections.addAll(result, overflowArray);
for (Plot plot : extra) {
result.add(plot);
}
return result;
}
/**
* Unchecked, use {@link #sortPlots(Collection, SortType, PlotArea)} instead which will in turn call this.
* @param input an array of plots to sort
*/
@Deprecated
public void sortPlotsByHash(Plot[] input) {
List<Plot>[] bucket = new ArrayList[32];
for (int i = 0; i < bucket.length; i++) {
bucket[i] = new ArrayList<>();
}
boolean maxLength = false;
int placement = 1;
while (!maxLength) {
maxLength = true;
for (Plot i : input) {
int tmp = MathMan.getPositiveId(i.hashCode()) / placement;
bucket[tmp & 31].add(i);
if (maxLength && tmp > 0) {
maxLength = false;
}
}
int a = 0;
for (int b = 0; b < 32; b++) {
for (Plot i : bucket[b]) {
input[a++] = i;
}
bucket[b].clear();
}
placement *= 32;
}
}
@Deprecated
public ArrayList<Plot> sortPlotsByTimestamp(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<>(overflowSize);
ArrayList<Plot> extra = new ArrayList<>();
for (Plot plot : plots) {
int hash = MathMan.getPositiveId(plot.hashCode());
if (hash < hardMax) {
if (hash >= 0) {
cache[hash] = plot;
} else {
extra.add(plot);
}
} else if (Math.abs(plot.getId().x) > 15446 || Math.abs(plot.getId().y) > 15446) {
extra.add(plot);
} else {
overflow.add(plot);
}
}
Plot[] overflowArray = overflow.toArray(new Plot[overflow.size()]);
sortPlotsByHash(overflowArray);
ArrayList<Plot> result = new ArrayList<>(cache.length + overflowArray.length);
for (Plot plot : cache) {
if (plot != null) {
result.add(plot);
}
}
Collections.addAll(result, overflowArray);
for (Plot plot : extra) {
result.add(plot);
}
return result;
}
/**
* Sort plots by creation timestamp.
* @param input
* @deprecated Unchecked, use {@link #sortPlots(Collection, SortType, PlotArea)} instead which will call this after checks
* @return
*/
@Deprecated
public List<Plot> sortPlotsByModified(Collection<Plot> input) {
List<Plot> list;
if (input instanceof List) {
list = (List<Plot>) input;
} else {
list = new ArrayList<>(input);
}
Collections.sort(list, new Comparator<Plot>() {
@Override
public int compare(Plot a, Plot b) {
return Long.compare(ExpireManager.IMP.getTimestamp(a.owner), ExpireManager.IMP.getTimestamp(b.owner));
}
});
return list;
}
/**
* Sort a collection of plots by world (with a priority world), then
* by hashcode.
* @param plots the plots to sort
* @param type The sorting method to use for each world (timestamp, or hash)
* @param priorityArea Use null, "world", or "gibberish" if you
* want default world order
* @return ArrayList of plot
*/
public ArrayList<Plot> sortPlots(Collection<Plot> plots, SortType type, final PlotArea priorityArea) {
// group by world
// sort each
HashMap<PlotArea, Collection<Plot>> map = new HashMap<>();
int totalSize = getPlotCount();
if (plots.size() == totalSize) {
for (PlotArea area : manager.getAllPlotAreas()) {
map.put(area, area.getPlots());
}
} else {
for (PlotArea area : manager.getAllPlotAreas()) {
map.put(area, new ArrayList<Plot>(0));
}
Collection<Plot> lastList = null;
PlotArea lastWorld = null;
for (Plot plot : plots) {
if (lastWorld == plot.getArea()) {
lastList.add(plot);
} else {
lastWorld = plot.getArea();
lastList = map.get(lastWorld);
lastList.add(plot);
}
}
}
List<PlotArea> areas = Arrays.asList(manager.getAllPlotAreas());
Collections.sort(areas, new Comparator<PlotArea>() {
@Override
public int compare(PlotArea a, PlotArea b) {
if (priorityArea != null && StringMan.isEqual(a.toString(), b.toString())) {
return -1;
}
return a.hashCode() - b.hashCode();
}
});
ArrayList<Plot> toReturn = new ArrayList<>(plots.size());
for (PlotArea area : areas) {
switch (type) {
case CREATION_DATE:
toReturn.addAll(sortPlotsByTemp(map.get(area)));
break;
case CREATION_DATE_TIMESTAMP:
toReturn.addAll(sortPlotsByTimestamp(map.get(area)));
break;
case DISTANCE_FROM_ORIGIN:
toReturn.addAll(sortPlotsByHash(map.get(area)));
break;
case LAST_MODIFIED:
toReturn.addAll(sortPlotsByModified(map.get(area)));
break;
default:
break;
}
}
return toReturn;
}
/**
* A more generic way to filter plots - make your own method
* if you need complex filters.
* @param filters the filter
* @return a filtered set of plots
*/
public Set<Plot> getPlots(final PlotFilter... filters) {
final HashSet<Plot> set = new HashSet<>();
foreachPlotArea(new RunnableVal<PlotArea>() {
@Override
public void run(PlotArea value) {
for (PlotFilter filter : filters) {
if (!filter.allowsArea(value)) {
return;
}
}
loop:
for (Entry<PlotId, Plot> entry2 : value.getPlotEntries()) {
Plot plot = entry2.getValue();
for (PlotFilter filter : filters) {
if (!filter.allowsPlot(plot)) {
continue loop;
}
}
set.add(plot);
}
}
});
return set;
}
/**
* Get all the plots in a single set.
* @return Set of Plots
*/
public Set<Plot> getPlots() {
int size = getPlotCount();
final Set<Plot> result = new HashSet<>(size);
foreachPlotArea(new RunnableVal<PlotArea>() {
@Override
public void run(PlotArea value) {
result.addAll(value.getPlots());
}
});
return result;
}
public void setPlots(HashMap<String, HashMap<PlotId, Plot>> plots) {
if (this.plots_tmp == null) {
this.plots_tmp = new HashMap<>();
}
for (Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
String world = entry.getKey();
PlotArea area = getPlotArea(world, null);
if (area == null) {
HashMap<PlotId, Plot> map = this.plots_tmp.get(world);
if (map == null) {
map = new HashMap<>();
this.plots_tmp.put(world, map);
}
map.putAll(entry.getValue());
} else {
for (Plot plot : entry.getValue().values()) {
plot.setArea(area);
area.addPlot(plot);
}
}
}
}
/**
* Get all the plots owned by a player name.
* @param world the world
* @param player the plot owner
* @return Set of Plot
*/
public Set<Plot> getPlots(String world, String player) {
UUID uuid = UUIDHandler.getUUID(player, null);
return getPlots(world, uuid);
}
/**
* Get all the plots owned by a player name.
* @param area the PlotArea
* @param player the plot owner
* @return Set of Plot
*/
public Set<Plot> getPlots(PlotArea area, String player) {
UUID uuid = UUIDHandler.getUUID(player, null);
return getPlots(area, uuid);
}
/**
* Get all plots by a PlotPlayer.
* @param world the world
* @param player the plot owner
* @return Set of plot
*/
public Set<Plot> getPlots(String world, PlotPlayer player) {
return getPlots(world, player.getUUID());
}
/**
* Get all plots by a PlotPlayer.
* @param area the PlotArea
* @param player the plot owner
* @return Set of plot
*/
public Set<Plot> getPlots(PlotArea area, PlotPlayer player) {
return getPlots(area, player.getUUID());
}
/**
* Get all plots by a UUID in a world.
* @param world the world
* @param uuid the plot owner
* @return Set of plot
*/
public Set<Plot> getPlots(String world, UUID uuid) {
ArrayList<Plot> myPlots = new ArrayList<>();
for (Plot plot : getPlots(world)) {
if (plot.hasOwner()) {
if (plot.isOwnerAbs(uuid)) {
myPlots.add(plot);
}
}
}
return new HashSet<>(myPlots);
}
/**
* Get all plots by a UUID in an area.
* @param area the {@code PlotArea}
* @param uuid the plot owner
* @return Set of plot
*/
public Set<Plot> getPlots(PlotArea area, UUID uuid) {
ArrayList<Plot> myplots = new ArrayList<>();
for (Plot plot : getPlots(area)) {
if (plot.hasOwner()) {
if (plot.isOwnerAbs(uuid)) {
myplots.add(plot);
}
}
}
return new HashSet<>(myplots);
}
/**
* Use {@link #hasPlotArea(String)}.
* Note: Worlds may have more than one plot area
* @deprecated
* @param world the world
* @return if the world is a plotworld
*/
@Deprecated
public boolean isPlotWorld(String world) {
return hasPlotArea(world);
}
/**
* Check if a plot world.
* @param world the world
* @see #getPlotAreaByString(String) to get the PlotArea object
* @return if a plot world is registered
*/
public boolean hasPlotArea(String world) {
return manager.getPlotAreas(world, null).length != 0;
}
public Collection<Plot> getPlots(String world) {
final HashSet<Plot> set = new HashSet<>();
foreachPlotArea(world, new RunnableVal<PlotArea>() {
@Override
public void run(PlotArea value) {
set.addAll(value.getPlots());
}
});
return set;
}
/**
* Get the plots for a PlotPlayer.
* @param player the player to retrieve the plots for
* @return Set of Plot
*/
public Set<Plot> getPlots(PlotPlayer player) {
return getPlots(player.getUUID());
}
public Collection<Plot> getPlots(PlotArea area) {
return area == null ? new HashSet<Plot>() : area.getPlots();
}
public Plot getPlot(PlotArea area, PlotId id) {
return area == null ? null : id == null ? null : area.getPlot(id);
}
public Set<Plot> getBasePlots(PlotPlayer player) {
return getBasePlots(player.getUUID());
}
/**
* Get the plots for a UUID.
* @param uuid the plot owner
* @return Set of Plot's owned by the player
*/
public Set<Plot> getPlots(final UUID uuid) {
final ArrayList<Plot> myPlots = new ArrayList<>();
foreachPlot(new RunnableVal<Plot>() {
@Override
public void run(Plot value) {
if (value.isOwnerAbs(uuid)) {
myPlots.add(value);
}
}
});
return new HashSet<>(myPlots);
}
public Set<Plot> getBasePlots(final UUID uuid) {
final ArrayList<Plot> myplots = new ArrayList<>();
foreachBasePlot(new RunnableVal<Plot>() {
@Override
public void run(Plot value) {
if (value.isOwner(uuid)) {
myplots.add(value);
}
}
});
return new HashSet<>(myplots);
}
/**
* Get the plots for a UUID.
* @param uuid the UUID of the owner
* @return Set of Plot
*/
public Set<Plot> getPlotsAbs(final UUID uuid) {
final ArrayList<Plot> myPlots = new ArrayList<>();
foreachPlot(new RunnableVal<Plot>() {
@Override
public void run(Plot value) {
if (value.isOwnerAbs(uuid)) {
myPlots.add(value);
}
}
});
return new HashSet<>(myPlots);
}
/**
* Unregister a plot from local memory (does not call DB).
* @param plot the plot to remove
* @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(Plot plot, boolean callEvent) {
if (plot == null) {
return false;
}
if (callEvent) {
EventUtil.manager.callDelete(plot);
}
if (plot.getArea().removePlot(plot.getId())) {
PlotId last = (PlotId) plot.getArea().getMeta("lastPlot");
int last_max = Math.max(Math.abs(last.x), Math.abs(last.y));
int this_max = Math.max(Math.abs(plot.getId().x), Math.abs(plot.getId().y));
if (this_max < last_max) {
plot.getArea().setMeta("lastPlot", plot.getId());
}
return true;
}
return false;
}
/**
* This method is called by the PlotGenerator class normally.
* <ul>
* <li>Initializes the PlotArea and PlotManager classes
* <li>Registers the PlotArea and PlotManager classes
* <li>Loads (and/or generates) the PlotArea configuration
* <li>Sets up the world border if configured
* </ul>
*
* <p>If loading an augmented plot world:
* <ul>
* <li>Creates the AugmentedPopulator classes
* <li>Injects the AugmentedPopulator classes if required
* </ul>
* @param world the world to load
* @param baseGenerator The generator for that world, or null
*/
public void loadWorld(String world, GeneratorWrapper<?> baseGenerator) {
if (world.equals("CheckingPlotSquaredGenerator")) {
return;
}
this.manager.addWorld(world);
Set<String> worlds;
if (this.worlds.contains("worlds")) {
worlds = this.worlds.getConfigurationSection("worlds").getKeys(false);
} else {
worlds = new HashSet<>();
}
String path = "worlds." + world;
ConfigurationSection worldSection = this.worlds.getConfigurationSection(path);
int type;
if (worldSection != null) {
type = worldSection.getInt("generator.type", 0);
} else {
type = 0;
}
if (type == 0) {
if (manager.getPlotAreas(world, null).length != 0) {
debug("World possibly already loaded: " + world);
return;
}
IndependentPlotGenerator plotGenerator;
if (baseGenerator != null && baseGenerator.isFull()) {
plotGenerator = baseGenerator.getPlotGenerator();
} else if (worldSection != null) {
String secondaryGeneratorName = worldSection.getString("generator.plugin");
GeneratorWrapper<?> secondaryGenerator = this.IMP.getGenerator(world, secondaryGeneratorName);
if (secondaryGenerator != null && secondaryGenerator.isFull()) {
plotGenerator = secondaryGenerator.getPlotGenerator();
} else {
String primaryGeneratorName = worldSection.getString("generator.init");
GeneratorWrapper<?> primaryGenerator = this.IMP.getGenerator(world, primaryGeneratorName);
if (primaryGenerator != null && primaryGenerator.isFull()) {
plotGenerator = primaryGenerator.getPlotGenerator();
} else {
return;
}
}
} else {
return;
}
// Conventional plot generator
PlotArea plotArea = plotGenerator.getNewPlotArea(world, null, null, null);
PlotManager plotManager = plotGenerator.getNewPlotManager();
PS.log(C.PREFIX + "&aDetected world load for '" + world + "'");
PS.log(C.PREFIX + "&3 - generator: &7" + baseGenerator + ">" + plotGenerator);
PS.log(C.PREFIX + "&3 - plotworld: &7" + plotArea.getClass().getName());
PS.log(C.PREFIX + "&3 - manager: &7" + plotManager.getClass().getName());
if (!this.worlds.contains(path)) {
this.worlds.createSection(path);
worldSection = this.worlds.getConfigurationSection(path);
}
plotArea.saveConfiguration(worldSection);
plotArea.loadDefaultConfiguration(worldSection);
try {
this.worlds.save(this.worldsFile);
} catch (IOException e) {
e.printStackTrace();
}
// Now add it
addPlotArea(plotArea);
plotGenerator.initialize(plotArea);
} else {
if (!worlds.contains(world)) {
return;
}
ConfigurationSection areasSection = worldSection.getConfigurationSection("areas");
if (areasSection == null) {
if (manager.getPlotAreas(world, null).length != 0) {
debug("World possibly already loaded: " + world);
return;
}
PS.log(C.PREFIX + "&aDetected world load for '" + world + "'");
String gen_string = worldSection.getString("generator.plugin", IMP.getPluginName());
if (type == 2) {
Set<PlotCluster> clusters = this.clusters_tmp != null ? this.clusters_tmp.get(world) : new HashSet<PlotCluster>();
if (clusters == null) {
throw new IllegalArgumentException("No cluster exists for world: " + world);
}
ArrayDeque<PlotArea> toLoad = new ArrayDeque<>();
for (PlotCluster cluster : clusters) {
PlotId pos1 = cluster.getP1(); // Cluster pos1
PlotId pos2 = cluster.getP2(); // Cluster pos2
String name = cluster.getName(); // Cluster name
String fullId = name + "-" + pos1 + "-" + pos2;
worldSection.createSection("areas." + fullId);
DBFunc.replaceWorld(world, world + ";" + name, pos1, pos2); // NPE
PS.log(C.PREFIX + "&3 - " + name + "-" + pos1 + "-" + pos2);
GeneratorWrapper<?> areaGen = this.IMP.getGenerator(world, gen_string);
if (areaGen == null) {
throw new IllegalArgumentException("Invalid Generator: " + gen_string);
}
PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, name, pos1, pos2);
pa.saveConfiguration(worldSection);
pa.loadDefaultConfiguration(worldSection);
try {
this.worlds.save(this.worldsFile);
} catch (IOException e) {
e.printStackTrace();
}
PS.log(C.PREFIX + "&c | &9generator: &7" + baseGenerator + ">" + areaGen);
PS.log(C.PREFIX + "&c | &9plotworld: &7" + pa);
PS.log(C.PREFIX + "&c | &9manager: &7" + pa);
PS.log(C.PREFIX + "&cNote: &7Area created for cluster:" + name + " (invalid or old configuration?)");
areaGen.getPlotGenerator().initialize(pa);
areaGen.augment(pa);
toLoad.add(pa);
}
for (PlotArea area : toLoad) {
addPlotArea(area);
}
return;
}
GeneratorWrapper<?> areaGen = this.IMP.getGenerator(world, gen_string);
if (areaGen == null) {
throw new IllegalArgumentException("Invalid Generator: " + gen_string);
}
PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, null, null, null);
pa.saveConfiguration(worldSection);
pa.loadDefaultConfiguration(worldSection);
try {
this.worlds.save(this.worldsFile);
} catch (IOException e) {
e.printStackTrace();
}
PS.log(C.PREFIX + "&3 - generator: &7" + baseGenerator + ">" + areaGen);
PS.log(C.PREFIX + "&3 - plotworld: &7" + pa);
PS.log(C.PREFIX + "&3 - manager: &7" + pa.getPlotManager());
areaGen.getPlotGenerator().initialize(pa);
areaGen.augment(pa);
addPlotArea(pa);
return;
}
if (type == 1) {
throw new IllegalArgumentException("Invalid type for multi-area world. Expected `2`, got `" + 1 + "`");
}
for (String areaId : areasSection.getKeys(false)) {
PS.log(C.PREFIX + "&3 - " + areaId);
String[] split = areaId.split("(?<=[^;-])-");
if (split.length != 3) {
throw new IllegalArgumentException("Invalid Area identifier: " + areaId + ". Expected form `<name>-<pos1>-<pos2>`");
}
String name = split[0];
PlotId pos1 = PlotId.fromString(split[1]);
PlotId pos2 = PlotId.fromString(split[2]);
if (pos1 == null || pos2 == null || name.isEmpty()) {
throw new IllegalArgumentException("Invalid Area identifier: " + areaId + ". Expected form `<name>-<x1;z1>-<x2;z2>`");
}
PlotArea existing = getPlotArea(world, name);
if (existing != null && name.equals(existing.id)) {
continue;
}
ConfigurationSection section = areasSection.getConfigurationSection(areaId);
YamlConfiguration clone = new YamlConfiguration();
for (String key : section.getKeys(true)) {
if (section.get(key) instanceof MemorySection) {
continue;
}
if (!clone.contains(key)) {
clone.set(key, section.get(key));
}
}
for (String key : worldSection.getKeys(true)) {
if (worldSection.get(key) instanceof MemorySection) {
continue;
}
if (!key.startsWith("areas") && !clone.contains(key)) {
clone.set(key, worldSection.get(key));
}
}
String gen_string = clone.getString("generator.plugin", IMP.getPluginName());
GeneratorWrapper<?> areaGen = this.IMP.getGenerator(world, gen_string);
if (areaGen == null) {
throw new IllegalArgumentException("Invalid Generator: " + gen_string);
}
PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, name, pos1, pos2);
pa.saveConfiguration(clone);
// netSections is the combination of
for (String key : clone.getKeys(true)) {
if (clone.get(key) instanceof MemorySection) {
continue;
}
if (!worldSection.contains(key)) {
worldSection.set(key, clone.get(key));
} else {
Object value = worldSection.get(key);
if (!Objects.equals(value, clone.get(key))) {
section.set(key, clone.get(key));
}
}
}
pa.loadDefaultConfiguration(clone);
try {
this.worlds.save(this.worldsFile);
} catch (IOException e) {
e.printStackTrace();
}
PS.log(C.PREFIX + "&aDetected area load for '" + world + "'");
PS.log(C.PREFIX + "&c | &9generator: &7" + baseGenerator + ">" + areaGen);
PS.log(C.PREFIX + "&c | &9plotworld: &7" + pa);
PS.log(C.PREFIX + "&c | &9manager: &7" + pa.getPlotManager());
areaGen.getPlotGenerator().initialize(pa);
areaGen.augment(pa);
addPlotArea(pa);
}
}
}
/**
* Setup the configuration for a plot world based on world arguments.
*
* <p>
* <i>e.g. /mv create <world> normal -g PlotSquared:<args></i>
*
* @param world The name of the world
* @param args The arguments
* @param generator the plot generator
* @return boolean | if valid arguments were provided
*/
public boolean setupPlotWorld(String world, String args, IndependentPlotGenerator generator) {
if (args != null && !args.isEmpty()) {
// save configuration
String[] split = args.split(",");
HybridPlotWorld plotworld = new HybridPlotWorld(world, null, generator, null, null);
for (String element : split) {
String[] pair = element.split("=");
if (pair.length != 2) {
PS.log("&cNo value provided for: &7" + element);
return false;
}
String key = pair[0].toLowerCase();
String value = pair[1];
String base = "worlds." + world + ".";
try {
switch (key) {
case "s":
case "size":
this.worlds.set(base + "plot.size", Configuration.INTEGER.parseString(value).shortValue());
break;
case "g":
case "gap":
this.worlds.set(base + "road.width", Configuration.INTEGER.parseString(value).shortValue());
break;
case "h":
case "height":
this.worlds.set(base + "road.height", Configuration.INTEGER.parseString(value).shortValue());
this.worlds.set(base + "plot.height", Configuration.INTEGER.parseString(value).shortValue());
this.worlds.set(base + "wall.height", Configuration.INTEGER.parseString(value).shortValue());
break;
case "f":
case "floor":
this.worlds.set(base + "plot.floor",
new ArrayList<>(Arrays.asList(StringMan.join(Configuration.BLOCKLIST.parseString(value), ",").split(","))));
break;
case "m":
case "main":
this.worlds.set(base + "plot.filling",
new ArrayList<>(Arrays.asList(StringMan.join(Configuration.BLOCKLIST.parseString(value), ",").split(","))));
break;
case "w":
case "wall":
this.worlds.set(base + "wall.filling", Configuration.BLOCK.parseString(value).toString());
break;
case "b":
case "border":
this.worlds.set(base + "wall.block", Configuration.BLOCK.parseString(value).toString());
break;
default:
PS.log("&cKey not found: &7" + element);
return false;
}
} catch (Exception e) {
e.printStackTrace();
PS.log("&cInvalid value: &7" + value + " in arg " + element);
return false;
}
}
try {
ConfigurationSection section = this.worlds.getConfigurationSection("worlds." + world);
plotworld.saveConfiguration(section);
plotworld.loadConfiguration(section);
this.worlds.save(this.worldsFile);
} catch (IOException 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) {
String[] split = Pattern.compile(".", Pattern.LITERAL).split(version);
StringBuilder sb = new StringBuilder();
for (String s : split) {
sb.append(String.format("%" + 4 + 's', s));
}
return sb.toString();
}
public boolean update(PlotPlayer sender, URL url) {
try {
String name = this.jarFile.getName();
File newJar = new File("plugins/update/" + name);
MainUtil.sendMessage(sender, "$1Downloading from provided URL: &7" + url);
URLConnection con = url.openConnection();
try (InputStream stream = con.getInputStream()) {
File parent = newJar.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
MainUtil.sendMessage(sender, "$2 - Output: " + newJar);
if (!newJar.delete()) {
MainUtil.sendMessage(sender, "Failed to update " + IMP.getPluginName() + "");
MainUtil.sendMessage(sender, "Jar file failed to delete.");
MainUtil.sendMessage(sender, " - Please update manually");
}
Files.copy(stream, newJar.toPath());
}
MainUtil.sendMessage(sender, "$1The update will take effect when the server is restarted next");
return true;
} catch (IOException e) {
MainUtil.sendMessage(sender, "Failed to update " + IMP.getPluginName() + "");
MainUtil.sendMessage(sender, " - Please update manually");
PS.log("============ Stacktrace ============");
e.printStackTrace();
PS.log("====================================");
}
return false;
}
/**
* 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 {
File output = this.IMP.getDirectory();
if (!output.exists()) {
output.mkdirs();
}
File newFile = MainUtil.getFile(output, folder + File.separator + file);
if (newFile.exists()) {
return;
}
try (InputStream stream = this.IMP.getClass().getResourceAsStream(file)) {
byte[] buffer = new byte[2048];
if (stream == null) {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(this.jarFile))) {
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String name = ze.getName();
if (name.equals(file)) {
new File(newFile.getParent()).mkdirs();
try (FileOutputStream fos = new FileOutputStream(newFile)) {
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
ze = null;
} else {
ze = zis.getNextEntry();
}
}
zis.closeEntry();
}
return;
}
newFile.createNewFile();
try (FileOutputStream fos = new FileOutputStream(newFile)) {
int len;
while ((len = stream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
}
} catch (IOException e) {
e.printStackTrace();
PS.log("&cCould not save " + file);
}
}
private Map<String, Map<PlotId, Plot>> getPlotsRaw() {
HashMap<String, Map<PlotId, Plot>> map = new HashMap<>();
for (PlotArea area : this.manager.getAllPlotAreas()) {
Map<PlotId, Plot> map2 = map.get(area.toString());
if (map2 == null) {
map.put(area.toString(), area.getPlotsRaw());
} else {
map2.putAll(area.getPlotsRaw());
}
}
return map;
}
/**
* Close the database connection.
*/
public void disable() {
try {
// Validate that all data in the db is correct
final HashSet<Plot> plots = new HashSet<>();
foreachPlotRaw(new RunnableVal<Plot>() {
@Override
public void run(Plot value) {
plots.add(value);
}
});
DBFunc.validatePlots(plots);
// Close the connection
DBFunc.close();
UUIDHandler.handleShutdown();
} catch (NullPointerException ignored) {
ignored.printStackTrace();
PS.log("&cCould not close database connection!");
}
}
/**
* Setup the database connection.
*/
public void setupDatabase() {
try {
if (DBFunc.dbManager != null) {
DBFunc.dbManager.close();
}
Database database;
if (Storage.MySQL.USE) {
database = new com.intellectualcrafters.plot.database.MySQL(Storage.MySQL.HOST, Storage.MySQL.PORT, Storage.MySQL.DATABASE,
Storage.MySQL.USER, Storage.MySQL.PASSWORD);
} else if (Storage.SQLite.USE) {
File file = MainUtil.getFile(IMP.getDirectory(), Storage.SQLite.DB + ".db");
database = new com.intellectualcrafters.plot.database.SQLite(file);
} else {
PS.log(C.PREFIX + "&cNo storage type is set!");
this.IMP.disable();
return;
}
DBFunc.dbManager = new SQLManager(database, Storage.PREFIX, false);
this.plots_tmp = DBFunc.getPlots();
if (manager instanceof SinglePlotAreaManager) {
SinglePlotArea area = ((SinglePlotAreaManager) manager).getArea();
addPlotArea(area);
ConfigurationSection section = worlds.getConfigurationSection("worlds.*");
if (section == null) {
section = worlds.createSection("worlds.*");
}
area.saveConfiguration(section);
area.loadDefaultConfiguration(section);
}
this.clusters_tmp = DBFunc.getClusters();
} catch (ClassNotFoundException | SQLException e) {
PS.log(C.PREFIX + "&cFailed to open DATABASE connection. The plugin will disable itself.");
if (Storage.MySQL.USE) {
PS.log("$4MYSQL");
} else if (Storage.SQLite.USE) {
PS.log("$4SQLITE");
}
PS.log("&d==== Here is an ugly stacktrace, if you are interested in those things ===");
e.printStackTrace();
PS.log("&d==== End of stacktrace ====");
PS.log("&6Please go to the " + IMP.getPluginName() + " 'storage.yml' and configure the database correctly.");
this.IMP.disable();
}
}
/**
* Setup the default configuration.
* @throws IOException if the config failed to save
*/
public void setupConfig() throws IOException {
String lastVersionString = this.config.getString("version");
if (lastVersionString != null) {
String[] split = lastVersionString.split("\\.");
this.lastVersion = new int[]{Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])};
}
if (lastVersion != null && checkVersion(new int[]{3, 4, 0}, lastVersion)) {
Settings.convertLegacy(configFile);
if (config.contains("worlds")) {
ConfigurationSection worldSection = config.getConfigurationSection("worlds");
worlds.set("worlds", worldSection);
try {
worlds.save(worldsFile);
} catch (IOException e) {
PS.debug("Failed to save " + IMP.getPluginName() + " worlds.yml");
e.printStackTrace();
}
}
} else {
Settings.load(configFile);
}
Settings.VERSION = StringMan.join(this.version, ".");
Settings.PLATFORM = platform;
Settings.save(configFile);
config = YamlConfiguration.loadConfiguration(configFile);
}
/**
* Setup all configuration files<br>
* - Config: settings.yml<br>
* - Storage: storage.yml<br>
* - Translation: PlotSquared.use_THIS.yml, style.yml<br>
*/
public void setupConfigs() {
File folder = new File(this.IMP.getDirectory(), "config");
if (!folder.exists() && !folder.mkdirs()) {
PS.log(C.PREFIX + "&cFailed to create the /plugins/config folder. Please create it manually.");
}
try {
this.worldsFile = new File(folder, "worlds.yml");
if (!this.worldsFile.exists() && !this.worldsFile.createNewFile()) {
PS.log("Could not create the worlds file, please create \"worlds.yml\" manually.");
}
this.worlds = YamlConfiguration.loadConfiguration(this.worldsFile);
} catch (IOException ignored) {
PS.log("Failed to save settings.yml");
}
try {
this.configFile = new File(folder, "settings.yml");
if (!this.configFile.exists() && !this.configFile.createNewFile()) {
PS.log("Could not create the settings file, please create \"settings.yml\" manually.");
}
this.config = YamlConfiguration.loadConfiguration(this.configFile);
setupConfig();
} catch (IOException ignored) {
PS.log("Failed to save settings.yml");
}
try {
this.styleFile = MainUtil.getFile(IMP.getDirectory(), Settings.Paths.TRANSLATIONS + File.separator + "style.yml");
if (!this.styleFile.exists()) {
if (!this.styleFile.getParentFile().exists()) {
this.styleFile.getParentFile().mkdirs();
}
if (!this.styleFile.createNewFile()) {
PS.log("Could not create the style file, please create \"translations/style.yml\" manually");
}
}
this.style = YamlConfiguration.loadConfiguration(this.styleFile);
setupStyle();
} catch (IOException err) {
err.printStackTrace();
PS.log("failed to save style.yml");
}
try {
this.storageFile = new File(folder, "storage.yml");
if (!this.storageFile.exists() && !this.storageFile.createNewFile()) {
PS.log("Could not the storage settings file, please create \"storage.yml\" manually.");
}
this.storage = YamlConfiguration.loadConfiguration(this.storageFile);
setupStorage();
} catch (IOException ignored) {
PS.log("Failed to save storage.yml");
}
try {
this.commandsFile = new File(folder, "commands.yml");
if (!this.commandsFile.exists() && !this.commandsFile.createNewFile()) {
PS.log("Could not the storage settings file, please create \"commands.yml\" manually.");
}
this.commands = YamlConfiguration.loadConfiguration(this.commandsFile);
} catch (IOException ignored) {
PS.log("Failed to save commands.yml");
}
try {
this.style.save(this.styleFile);
this.commands.save(this.commandsFile);
} catch (IOException e) {
PS.log("Configuration file saving failed");
e.printStackTrace();
}
}
/**
* Setup the storage file (load + save missing nodes).
*/
private void setupStorage() {
Storage.load(storageFile);
Storage.save(storageFile);
storage = YamlConfiguration.loadConfiguration(storageFile);
}
/**
* Show startup debug information.
*/
private void showDebug() {
if (Settings.DEBUG) {
Map<String, Object> components = Settings.getFields(Settings.Enabled_Components.class);
for (Entry<String, Object> component : components.entrySet()) {
PS.log(C.PREFIX + String.format("&cKey: &6%s&c, Value: &6%s", component.getKey(), component.getValue()));
}
}
}
/**
* Setup the style.yml file
*/
private void setupStyle() {
this.style.set("version", StringMan.join(this.version, "."));
Map<String, Object> o = new HashMap<>(4);
o.put("color.1", "6");
o.put("color.2", "7");
o.put("color.3", "8");
o.put("color.4", "3");
if (!this.style.contains("color")) {
for (Entry<String, Object> node : o.entrySet()) {
this.style.set(node.getKey(), node.getValue());
}
}
}
/**
* Get the Java version.
* @return the java version
*/
public double getJavaVersion() {
return Double.parseDouble(System.getProperty("java.specification.version"));
}
public void foreachPlotArea(RunnableVal<PlotArea> runnable) {
for (PlotArea area : this.manager.getAllPlotAreas()) {
runnable.run(area);
}
}
public void foreachPlotArea(String world, RunnableVal<PlotArea> runnable) {
PlotArea[] array = this.manager.getPlotAreas(world, null);
if (array == null) {
return;
}
for (PlotArea area : array) {
runnable.run(area);
}
}
public void foreachPlot(RunnableVal<Plot> runnable) {
for (PlotArea area : this.manager.getAllPlotAreas()) {
for (Plot plot : area.getPlots()) {
runnable.run(plot);
}
}
}
public void foreachPlotRaw(RunnableVal<Plot> runnable) {
for (PlotArea area : this.manager.getAllPlotAreas()) {
for (Plot plot : area.getPlots()) {
runnable.run(plot);
}
}
if (this.plots_tmp != null) {
for (HashMap<PlotId, Plot> entry : this.plots_tmp.values()) {
for (Plot entry2 : entry.values()) {
runnable.run(entry2);
}
}
}
}
public void foreachBasePlot(RunnableVal<Plot> run) {
for (PlotArea area : this.manager.getAllPlotAreas()) {
area.foreachBasePlot(run);
}
}
public PlotArea getFirstPlotArea() {
PlotArea[] areas = manager.getAllPlotAreas();
return areas.length > 0 ? areas[0] : null;
}
public int getPlotAreaCount() {
return this.manager.getAllPlotAreas().length;
}
public int getPlotCount() {
int count = 0;
for (PlotArea area : this.manager.getAllPlotAreas()) {
count += area.getPlotCount();
}
return count;
}
public Set<PlotArea> getPlotAreas() {
HashSet<PlotArea> set = new HashSet<>();
Collections.addAll(set, manager.getAllPlotAreas());
return set;
}
/**
* Not recommended for use since worlds can have multiple PlotAreas.
* @return Set of world names
*/
@Deprecated
public Set<String> getPlotWorldStrings() {
HashSet<String> set = new HashSet<>(manager.getAllPlotAreas().length);
for (String world : manager.getAllWorlds()) {
if (manager.getPlotAreas(world, null).length != 0) {
set.add(world);
}
}
return set;
}
public boolean isAugmented(String world) {
PlotArea[] areas = manager.getPlotAreas(world, null);
if (areas == null) {
return false;
}
if (areas.length > 1) {
return true;
}
return areas[0].TYPE != 0;
}
/**
* Get a list of PlotArea objects.
* @param world the world
* @return Collection of PlotArea objects
*/
public Set<PlotArea> getPlotAreas(String world) {
Set<PlotArea> set = new HashSet<>();
Collections.addAll(set, manager.getPlotAreas(world, null));
return set;
}
/**
* Get the relevant plot area for a specified location.
* <ul>
* <li>If there is only one plot area globally that will be returned.
* <li>If there is only one plot area in the world, it will return that.
* <li>If the plot area for a location cannot be unambiguously
* resolved, null will be returned.
* </ul>
* Note: An applicable plot area may not include the location i.e. clusters
* @param location the location
* @return
*/
public PlotArea getApplicablePlotArea(Location location) {
return manager.getApplicablePlotArea(location);
}
public PlotArea getPlotArea(String world, String id) {
return manager.getPlotArea(world, id);
}
/**
* Get the {@code PlotArea} which contains a location.
* <ul>
* <li>If the plot area does not contain a location, null
* will be returned.
* </ul>
*
* @param location the location
* @return the {@link PlotArea} in the location, null if non existent
*/
public PlotArea getPlotAreaAbs(Location location) {
return manager.getPlotArea(location);
}
public PlotArea getPlotAreaByString(String search) {
String[] split = search.split(";|,");
PlotArea[] areas = manager.getPlotAreas(split[0], null);
if (areas == null) {
for (PlotArea area : manager.getAllPlotAreas()) {
if (area.worldname.equalsIgnoreCase(split[0])) {
if (area.id == null || split.length == 2 && area.id.equalsIgnoreCase(split[1])) {
return area;
}
}
}
return null;
}
if (areas.length == 1) {
return areas[0];
} else if (split.length == 1) {
return null;
} else {
for (PlotArea area : areas) {
if (StringMan.isEqual(split[1], area.id)) {
return area;
}
}
return null;
}
}
public Set<PlotArea> getPlotAreas(String world, RegionWrapper region) {
PlotArea[] areas = manager.getPlotAreas(world, region);
Set<PlotArea> set = new HashSet<>();
Collections.addAll(set, areas);
return set;
}
public enum SortType {
CREATION_DATE, CREATION_DATE_TIMESTAMP, LAST_MODIFIED, DISTANCE_FROM_ORIGIN
}
}