diff --git a/pom.xml b/pom.xml
index 51dcd497..65ab69e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,14 +89,14 @@
com.fastasyncworldedit
FAWE-Core
- 1.17-93
+ 1.12
provided
com.fastasyncworldedit
FAWE-Bukkit
- 1.17-93
+ 1.12
provided
@@ -122,6 +122,14 @@
compile
+
+
+ com.github.fierioziy.particlenativeapi
+ ParticleNativeAPI-plugin
+ 3.2.0
+ provided
+
+
com.github.IPVP-MC
diff --git a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java
index 56480d96..1e163d90 100644
--- a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java
+++ b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java
@@ -188,6 +188,7 @@ public void onEnable() {
PlotManager.checkPlotsForLastActivity();
PlotManager.syncPlotSchematicFiles();
+ PlotManager.startTimer();
try {
new PacketListener();
@@ -309,10 +310,25 @@ public static boolean isHolographicDisplaysEnabled() {
return plugin.getServer().getPluginManager().isPluginEnabled("HolographicDisplays");
}
+ /**
+ * @return True if ParticleNativeAPI is present
+ */
+ public static boolean isParticleNativeAPIEnabled() {
+ return plugin.getServer().getPluginManager().isPluginEnabled("ParticleNativeAPI");
+ }
+
public static boolean isMultiverseInventoriesEnabled() {
return plugin.getServer().getPluginManager().isPluginEnabled("Multiverse-Inventories");
}
+ /**
+ * @param worldName Name of the world
+ * @return Config path for the world
+ */
+ public static String getMultiverseInventoriesConfigPath(String worldName) {
+ return PlotSystem.DependencyManager.isMultiverseInventoriesEnabled() ? Bukkit.getPluginManager().getPlugin("Multiverse-Inventories").getDataFolder() + "/worlds/" + worldName : "";
+ }
+
/**
* @return Multiverse-Core instance
*/
@@ -334,6 +350,14 @@ public static WorldGuardPlugin getWorldGuard() {
return WorldGuardPlugin.inst();
}
+ /**
+ * @param worldName Name of the world
+ * @return Config path for the world
+ */
+ public static String getWorldGuardConfigPath(String worldName) {
+ return Bukkit.getPluginManager().getPlugin("WorldGuard").getDataFolder() + "/worlds/" + worldName;
+ }
+
/**
* @return Protocol Lib Instance
*/
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java
index 4cccfcf1..9d997899 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java
@@ -53,7 +53,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String s, String[] a
player.sendMessage(Utils.getErrorMessageFormat(LangUtil.get(sender, LangPaths.Message.Error.PLAYER_NOT_FOUND)));
}
} else {
- new PlayerPlotsMenu(player, new Builder(player.getUniqueId()));
+ new PlayerPlotsMenu(player, Builder.byUUID(player.getUniqueId()));
}
} catch (SQLException ex) {
sender.sendMessage(Utils.getErrorMessageFormat(LangUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED)));
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java
index 5bc89ed1..b66b6829 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java
@@ -24,11 +24,13 @@
package com.alpsbte.plotsystem.commands;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.utils.Utils;
import com.alpsbte.plotsystem.utils.conversion.CoordinateConversion;
import com.alpsbte.plotsystem.utils.conversion.projection.OutOfProjectionBoundsException;
+import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.io.language.LangPaths;
import com.alpsbte.plotsystem.utils.io.language.LangUtil;
import org.bukkit.Bukkit;
@@ -88,7 +90,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String s, String[] a
double[] terraCoords = CoordinateConversion.convertFromGeo(lon, lat);
// Get plot, that the player is in
- Plot plot = PlotManager.getPlotByWorld(playerWorld);
+ Plot plot = PlotManager.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished, Status.unreviewed);
// Convert terra coordinates to plot relative coordinates
CompletableFuture plotCoords = PlotManager.convertTerraToPlotXZ(plot, terraCoords);
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java
index 3d4f41c7..46abea9c 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java
@@ -26,6 +26,7 @@
import com.alpsbte.plotsystem.commands.BaseCommand;
import com.alpsbte.plotsystem.commands.SubCommand;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.core.system.plot.PlotHandler;
@@ -58,7 +59,7 @@ public void onCommand(CommandSender sender, String[] args) {
return;
}
} else if (getPlayer(sender) != null && PlotManager.isPlotWorld(getPlayer(sender).getWorld())) {
- plot = PlotManager.getPlotByWorld(getPlayer(sender).getWorld());
+ plot = PlotManager.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unfinished);
} else {
sendInfo(sender);
return;
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java
index 81452313..57adb258 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java
@@ -27,9 +27,11 @@
import com.alpsbte.plotsystem.commands.BaseCommand;
import com.alpsbte.plotsystem.commands.SubCommand;
import com.alpsbte.plotsystem.core.menus.FeedbackMenu;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.utils.Utils;
+import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.io.language.LangPaths;
import com.alpsbte.plotsystem.utils.io.language.LangUtil;
import org.bukkit.Bukkit;
@@ -59,7 +61,7 @@ public void onCommand(CommandSender sender, String[] args) {
return;
}
} else if (PlotManager.isPlotWorld(getPlayer(sender).getWorld())) {
- plot = PlotManager.getPlotByWorld(getPlayer(sender).getWorld());
+ plot = PlotManager.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.completed);
} else {
sendInfo(sender);
return;
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java
index 57b62c75..abe6ba32 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java
@@ -26,10 +26,12 @@
import com.alpsbte.plotsystem.commands.BaseCommand;
import com.alpsbte.plotsystem.commands.SubCommand;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotHandler;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.utils.Utils;
+import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.io.language.LangPaths;
import com.alpsbte.plotsystem.utils.io.language.LangUtil;
import org.bukkit.Bukkit;
@@ -57,7 +59,7 @@ public void onCommand(CommandSender sender, String[] args) {
sender.sendMessage(Utils.getErrorMessageFormat(LangUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST)));
}
} else if (PlotManager.isPlotWorld(getPlayer(sender).getWorld())) {
- PlotHandler.sendLinkMessages(PlotManager.getPlotByWorld(getPlayer(sender).getWorld()), getPlayer(sender));
+ PlotHandler.sendLinkMessages(PlotManager.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unfinished, Status.unreviewed), getPlayer(sender));
} else {
sendInfo(sender);
}
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java
index af9cc140..c7377623 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java
@@ -2,11 +2,12 @@
import com.alpsbte.plotsystem.commands.BaseCommand;
import com.alpsbte.plotsystem.commands.SubCommand;
-import com.alpsbte.plotsystem.core.menus.FeedbackMenu;
import com.alpsbte.plotsystem.core.menus.PlotMemberMenu;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.utils.Utils;
+import com.alpsbte.plotsystem.utils.enums.Status;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -37,7 +38,7 @@ public void onCommand(CommandSender sender, String[] args) {
}
} else if (PlotManager.isPlotWorld(getPlayer(sender).getWorld())) {
//plot members
- plot = PlotManager.getPlotByWorld(getPlayer(sender).getWorld());
+ plot = PlotManager.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unfinished, Status.unreviewed);
} else {
sendInfo(sender);
return;
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java
index 088d78d4..fd0c2c36 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java
@@ -26,6 +26,7 @@
import com.alpsbte.plotsystem.commands.BaseCommand;
import com.alpsbte.plotsystem.commands.SubCommand;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotHandler;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
@@ -58,7 +59,7 @@ public void onCommand(CommandSender sender, String[] args) {
return;
}
} else if (getPlayer(sender) != null && PlotManager.isPlotWorld(getPlayer(sender).getWorld())) {
- plot = PlotManager.getPlotByWorld(getPlayer(sender).getWorld());
+ plot = PlotManager.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()));
} else {
sendInfo(sender);
return;
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java
index 89fe30dd..b4f93611 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java
@@ -59,7 +59,7 @@ public void onCommand(CommandSender sender, String[] args) {
plot.getWorld().teleportPlayer(getPlayer(sender));
} else {
if (sender.hasPermission("plotsystem.admin") && PlotManager.plotExists(plotID)) {
- new DefaultPlotGenerator(new Plot(plotID), new Builder(getPlayer(sender).getUniqueId()));
+ new DefaultPlotGenerator(new Plot(plotID), Builder.byUUID(getPlayer(sender).getUniqueId()));
} else {
sender.sendMessage(Utils.getErrorMessageFormat(LangUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST)));
}
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java
index ec366c1a..fbc4025c 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java
@@ -26,6 +26,7 @@
import com.alpsbte.plotsystem.commands.BaseCommand;
import com.alpsbte.plotsystem.commands.SubCommand;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotHandler;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
@@ -58,7 +59,7 @@ public void onCommand(CommandSender sender, String[] args) {
return;
}
} else if (getPlayer(sender) != null && PlotManager.isPlotWorld(getPlayer(sender).getWorld())) {
- plot = PlotManager.getPlotByWorld(getPlayer(sender).getWorld());
+ plot = PlotManager.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unreviewed);
} else {
sendInfo(sender);
return;
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java
index da77e87d..28f3926a 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java
@@ -26,7 +26,9 @@
import com.alpsbte.plotsystem.PlotSystem;
import com.alpsbte.plotsystem.commands.BaseCommand;
+import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.io.config.ConfigPaths;
+import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.utils.Utils;
@@ -56,7 +58,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String s, String[] a
return true;
}
} else if (getPlayer(sender) != null && PlotManager.isPlotWorld(getPlayer(sender).getWorld())) {
- plot = PlotManager.getPlotByWorld(getPlayer(sender).getWorld());
+ plot = PlotManager.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unfinished, Status.unreviewed);
} else {
sendInfo(sender);
return true;
diff --git a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java
index 403a9690..84d35f82 100644
--- a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java
+++ b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java
@@ -27,6 +27,8 @@
import com.alpsbte.plotsystem.commands.BaseCommand;
import com.alpsbte.plotsystem.core.menus.ReviewMenu;
import com.alpsbte.plotsystem.core.menus.ReviewPlotMenu;
+import com.alpsbte.plotsystem.core.system.Builder;
+import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.utils.Utils;
import com.alpsbte.plotsystem.utils.enums.Status;
@@ -48,11 +50,10 @@ public boolean onCommand(CommandSender sender, Command cmd, String s, String[] a
if (getPlayer(sender) != null) {
try {
Player player = (Player) sender;
- if (PlotManager.isPlotWorld(player.getWorld()) && PlotManager.getPlotByWorld(player.getWorld()).getStatus() == Status.unreviewed) {
- new ReviewPlotMenu(player, PlotManager.getPlotByWorld(player.getWorld()));
- } else {
- new ReviewMenu(player);
- }
+ Plot plot = PlotManager.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unreviewed);
+ if (plot != null && plot.getStatus() == Status.unreviewed) {
+ new ReviewPlotMenu(player, plot);
+ } else new ReviewMenu(player);
} catch (SQLException ex) {
sender.sendMessage(Utils.getErrorMessageFormat(LangUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED)));
Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
diff --git a/src/main/java/com/alpsbte/plotsystem/core/EventListener.java b/src/main/java/com/alpsbte/plotsystem/core/EventListener.java
index b2ad7ca4..5be28584 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/EventListener.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/EventListener.java
@@ -25,6 +25,7 @@
package com.alpsbte.plotsystem.core;
import com.alpsbte.plotsystem.PlotSystem;
+import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld;
import com.alpsbte.plotsystem.utils.io.config.ConfigPaths;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
import com.alpsbte.plotsystem.core.menus.CompanionMenu;
@@ -101,7 +102,7 @@ public void onPlayerJoinEvent(PlayerJoinEvent event) {
// Check if player has changed his name
try {
- Builder builder = new Builder(event.getPlayer().getUniqueId());
+ Builder builder = Builder.byUUID(event.getPlayer().getUniqueId());
if (!builder.getName().equals(event.getPlayer().getName())) {
DatabaseConnection.createStatement("UPDATE plotsystem_builders SET name = ? WHERE uuid = ?")
.setValue(event.getPlayer().getName()).setValue(event.getPlayer().getUniqueId().toString()).executeUpdate();
@@ -112,7 +113,7 @@ public void onPlayerJoinEvent(PlayerJoinEvent event) {
// Informing player about new feedback
try {
- List plots = PlotManager.getPlots(new Builder(event.getPlayer().getUniqueId()), Status.completed, Status.unfinished);
+ List plots = PlotManager.getPlots(Builder.byUUID(event.getPlayer().getUniqueId()), Status.completed, Status.unfinished);
List reviewedPlots = new ArrayList<>();
for(Plot plot : plots) {
@@ -132,7 +133,7 @@ public void onPlayerJoinEvent(PlayerJoinEvent event) {
// Informing player about unfinished plots
try {
- List plots = PlotManager.getPlots(new Builder(event.getPlayer().getUniqueId()), Status.unfinished);
+ List plots = PlotManager.getPlots(Builder.byUUID(event.getPlayer().getUniqueId()), Status.unfinished);
if(plots.size() >= 1) {
PlotHandler.sendUnfinishedPlotReminderMessage(plots, event.getPlayer());
event.getPlayer().sendMessage("");
@@ -196,36 +197,28 @@ public void onPlayerInteractEvent(PlayerInteractEvent event) {
@EventHandler
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) throws SQLException {
if (event.getRightClicked().getType().equals(EntityType.PLAYER)) {
- event.getPlayer().performCommand("plots " + new Builder(event.getRightClicked().getUniqueId()).getName());
+ event.getPlayer().performCommand("plots " + Builder.byUUID(event.getRightClicked().getUniqueId()).getName());
}
}
@EventHandler
public void onPlayerQuitEvent(PlayerQuitEvent event) {
final World w = event.getPlayer().getWorld();
+
Bukkit.getScheduler().scheduleSyncDelayedTask(PlotSystem.getPlugin(), () -> {
if(PlotManager.isPlotWorld(w)) {
- try {
- PlotManager.getPlotByWorld(w).getWorld().unloadWorld(false);
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
- }
- DefaultPlotGenerator.playerPlotGenerationHistory.remove(event.getPlayer().getUniqueId());
+ try { PlotWorld.getPlotWorldByName(w.getName()).unloadWorld(false);
+ } catch (SQLException ex) { Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex); }
}
+ DefaultPlotGenerator.playerPlotGenerationHistory.remove(event.getPlayer().getUniqueId());
+ PlotManager.clearCache(event.getPlayer().getUniqueId());
}, 60L);
}
- @EventHandler
- public void onPlayerTeleportEvent(PlayerTeleportEvent event) throws SQLException {
- if(PlotManager.isPlotWorld(event.getPlayer().getWorld()) && !event.getFrom().getWorld().equals(event.getTo().getWorld())) {
- PlotManager.getPlotByWorld(event.getFrom().getWorld()).getWorld().unloadWorld(false);
- }
- }
-
@EventHandler
public void onPlayerChangedWorldEvent(PlayerChangedWorldEvent event) throws SQLException {
if (PlotManager.isPlotWorld(event.getFrom())) {
- PlotManager.getPlotByWorld(event.getFrom()).getWorld().unloadWorld(false);
+ PlotWorld.getPlotWorldByName(event.getFrom().getName()).unloadWorld(false);
}
if (PlotManager.isPlotWorld(event.getPlayer().getWorld())) {
diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/DatabaseConnection.java b/src/main/java/com/alpsbte/plotsystem/core/database/DatabaseConnection.java
index af022e22..c6360a2f 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/database/DatabaseConnection.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/database/DatabaseConnection.java
@@ -263,14 +263,16 @@ public static List getTables() {
"(" +
" `uuid` varchar(36) NOT NULL ," +
" `name` varchar(16) NOT NULL ," +
- " `score` int DEFAULt 0 ," +
+ " `score` int DEFAULT 0 ," +
" `completed_plots` int DEFAULT 0 ," +
+ " `third_slot` int NULL ," +
" `first_slot` int NULL ," +
" `second_slot` int NULL ," +
" `third_slot` int NULL ," +
"PRIMARY KEY (`uuid`)" +
");",
"ALTER TABLE plotsystem_builders ADD COLUMN IF NOT EXISTS lang varchar(5) NULL;",
+ "ALTER TABLE plotsystem_builders ADD COLUMN IF NOT EXISTS setting_plot_type int DEFAULT 1;",
// Reviews
"CREATE TABLE IF NOT EXISTS `plotsystem_reviews`" +
@@ -322,8 +324,9 @@ public static List getTables() {
"KEY `fkIdx_82` (`difficulty_id`)," +
"CONSTRAINT `FK_81` FOREIGN KEY `fkIdx_82` (`difficulty_id`) REFERENCES `plotsystem_difficulties` (`id`)" +
");",
- "ALTER TABLE plotsystem_plots ADD COLUMN IF NOT EXISTS outline longtext NOT NULL;"
-
+ "ALTER TABLE plotsystem_plots ADD COLUMN IF NOT EXISTS outline longtext NULL DEFAULT NULL;",
+ "ALTER TABLE plotsystem_plots ADD COLUMN IF NOT EXISTS type int NOT NULL DEFAULT 1;",
+ "ALTER TABLE plotsystem_plots ADD COLUMN IF NOT EXISTS version DOUBLE NULL DEFAULT NULL;"
);
}
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java
index b9fba787..b5ee5f3d 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java
@@ -33,6 +33,11 @@
public abstract class AbstractMenu {
+ public static int MAX_CHARS_PER_LINE = 30;
+ public static char LINE_BAKER = '\n';
+
+
+
private final Menu menu;
private final Player menuPlayer;
@@ -53,9 +58,9 @@ public AbstractMenu(int rows, String title, Player menuPlayer, boolean reload) {
protected abstract void setMenuItemsAsync();
/**
- * Sets click events for the items placed in the menu after it is opened
+ * Sets click events for the items placed in the menu async after it is opened
*/
- protected abstract void setItemClickEvents();
+ protected abstract void setItemClickEventsAsync();
/**
* Places pre-defined items in the menu before it is opened
@@ -75,13 +80,13 @@ protected void setPreviewItems() {
/**
* Reloads all menu items and click events in the menu asynchronously
- * {@link #setPreviewItems()}.{@link #setMenuItemsAsync()}.{@link #setItemClickEvents()}
+ * {@link #setPreviewItems()}.{@link #setMenuItemsAsync()}.{@link #setItemClickEventsAsync()}
*/
protected void reloadMenuAsync() {
setPreviewItems();
Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> {
setMenuItemsAsync();
- Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), this::setItemClickEvents);
+ setItemClickEventsAsync();
});
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java
index b7a69e3a..5734e25e 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java
@@ -78,7 +78,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for custom-heads menu item
getMenu().getSlot(10).setClickHandler((clickPlayer, clickInformation) -> clickPlayer.performCommand("hdb"));
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/CompanionMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/CompanionMenu.java
index 34e5e4d6..72238018 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/CompanionMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/CompanionMenu.java
@@ -93,7 +93,7 @@ protected void setPreviewItems() {
slots = new Plot[3];
for (int i = 0; i < 3; i++) {
try {
- Builder builder = new Builder(getMenuPlayer().getUniqueId());
+ Builder builder = Builder.byUUID(getMenuPlayer().getUniqueId());
slots[i] = builder.getPlot(Slot.values()[i]);
if (slots[i] != null) {
@@ -141,7 +141,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for navigator item
getMenu().getSlot(4).setClickHandler((clickPlayer, clickInformation) -> {
clickPlayer.closeInventory();
@@ -171,7 +171,7 @@ protected void setItemClickEvents() {
if (!getMenu().getSlot(9 + itemSlot).getItem(clickPlayer).equals(MenuItems.errorItem(getMenuPlayer()))) {
try {
clickPlayer.closeInventory();
- Builder builder = new Builder(clickPlayer.getUniqueId());
+ Builder builder = Builder.byUUID(clickPlayer.getUniqueId());
int cityID = cityProjects.get(itemSlot).getID();
PlotDifficulty plotDifficultyForCity = selectedPlotDifficulty != null ? selectedPlotDifficulty : PlotManager.getPlotDifficultyForBuilder(cityID, builder).get();
@@ -257,7 +257,7 @@ private void setCityProjectItems() throws SQLException {
ItemStack cpItem = cp.getCountry().getHead();
try {
PlotDifficulty cpPlotDifficulty = selectedPlotDifficulty != null ?
- selectedPlotDifficulty : PlotManager.getPlotDifficultyForBuilder(cp.getID(), new Builder(getMenuPlayer().getUniqueId())).get();
+ selectedPlotDifficulty : PlotManager.getPlotDifficultyForBuilder(cp.getID(), Builder.byUUID(getMenuPlayer().getUniqueId())).get();
int plotsOpen = PlotManager.getPlots(cp.getID(), Status.unclaimed).size();
int plotsInProgress = PlotManager.getPlots(cp.getID(), Status.unfinished, Status.unreviewed).size();
@@ -326,7 +326,7 @@ private ItemStack getSelectedDifficultyItem() {
public static ItemStack getMenuItem(Player player) {
return new ItemBuilder(Material.NETHER_STAR, 1)
.setName("§b§l" + LangUtil.get(player, LangPaths.MenuTitle.COMPANION) + " §7(" + LangUtil.get(player, LangPaths.Note.Action.RIGHT_CLICK) + ")")
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
}
}
\ No newline at end of file
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java
index 15b258f8..59bc3a87 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java
@@ -122,7 +122,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {}
+ protected void setItemClickEventsAsync() {}
@Override
protected Mask getMask() {
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java
index ab6e42e4..030d999e 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java
@@ -116,7 +116,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Add click event for player plot items
for(int i = 0; i < plotDisplayCount; i++) {
int itemSlot = i;
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java
index 8e7c036f..714d05f8 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java
@@ -138,7 +138,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for submit or undo submit plot item
getMenu().getSlot(10).setClickHandler((clickPlayer, clickInformation) -> {
clickPlayer.closeInventory();
@@ -180,7 +180,7 @@ protected void setItemClickEvents() {
new PlotMemberMenu(plot,clickPlayer);
} else if (plot.getPlotMembers().stream().anyMatch(m -> m.getUUID().equals(getMenuPlayer().getUniqueId()))) {
// Leave Plot
- plot.removePlotMember(new Builder(clickPlayer.getUniqueId()));
+ plot.removePlotMember(Builder.byUUID(clickPlayer.getUniqueId()));
clickPlayer.sendMessage(Utils.getInfoMessageFormat(LangUtil.get(getMenuPlayer(), LangPaths.Message.Info.LEFT_PLOT, Integer.toString(plot.getID()))));
clickPlayer.closeInventory();
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java
index e0a31d97..668220aa 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java
@@ -107,7 +107,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for member slots
for (int i = 12; i < 15; i++) {
int itemSlot = i;
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewMenu.java
index d546f4f8..6c7d91d4 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewMenu.java
@@ -136,7 +136,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for previous page item
getMenu().getSlot(46).setClickHandler((clickPlayer, clickInformation) -> {
if (hasPreviousPage()) {
@@ -176,7 +176,7 @@ protected Mask getMask() {
public static ItemStack getMenuItem(Player player) {
return new ItemBuilder(Material.BOOK, 1)
.setName("§b§l" + LangUtil.get(player, LangPaths.MenuTitle.REVIEW_PLOTS) + " §7(" + LangUtil.get(player, LangPaths.Note.Action.RIGHT_CLICK) + ")")
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
}
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewPlotMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewPlotMenu.java
index d51110c7..436e4dbd 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewPlotMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewPlotMenu.java
@@ -213,7 +213,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for close item
getMenu().getSlot(50).setClickHandler((clickPlayer, clickInformation) -> clickPlayer.closeInventory());
@@ -356,7 +356,13 @@ protected void setItemClickEvents() {
}
// Delete plot world after reviewing
- if (!finalIsRejected) plot.getWorld().deleteWorld();
+ try {
+ if (!finalIsRejected && plot.getPlotType().hasOnePlotPerWorld())
+ plot.getWorld().deleteWorld();
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }
+
clickPlayer.sendMessage(reviewerConfirmationMessage);
clickPlayer.playSound(clickPlayer.getLocation(), Utils.FinishPlotSound, 1f, 1f);
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/SelectLanguageMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/SelectLanguageMenu.java
index c305ade6..8e55cac3 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/SelectLanguageMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/SelectLanguageMenu.java
@@ -29,7 +29,7 @@ public SelectLanguageMenu(Player player) {
protected void setPreviewItems() {
super.setPreviewItems();
- builder = new Builder(getMenuPlayer().getUniqueId());
+ builder = Builder.byUUID(getMenuPlayer().getUniqueId());
isAutoDetectEnabled = builder.getLanguageTag() == null;
}
@@ -60,13 +60,13 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for language items
for (int i = 0; i < LangUtil.languages.length; i++) {
LangUtil.LanguageFile langFile = LangUtil.languages[i];
getMenu().getSlot(i).setClickHandler((clickPlayer, clickInformation) -> {
try {
- Builder builder = new Builder(getMenuPlayer().getUniqueId());
+ Builder builder = Builder.byUUID(getMenuPlayer().getUniqueId());
builder.setLanguageTag(langFile.getTag());
Utils.updatePlayerInventorySlots(clickPlayer);
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/SelectPlotTypeMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/SelectPlotTypeMenu.java
new file mode 100644
index 00000000..a581163e
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/SelectPlotTypeMenu.java
@@ -0,0 +1,107 @@
+package com.alpsbte.plotsystem.core.menus;
+
+import com.alpsbte.plotsystem.core.system.Builder;
+import com.alpsbte.plotsystem.core.system.plot.PlotType;
+import com.alpsbte.plotsystem.utils.Utils;
+import com.alpsbte.plotsystem.utils.io.language.LangPaths;
+import com.alpsbte.plotsystem.utils.io.language.LangUtil;
+import com.alpsbte.plotsystem.utils.items.MenuItems;
+import com.alpsbte.plotsystem.utils.items.builder.ItemBuilder;
+import com.alpsbte.plotsystem.utils.items.builder.LoreBuilder;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.ipvp.canvas.mask.BinaryMask;
+import org.ipvp.canvas.mask.Mask;
+
+public class SelectPlotTypeMenu extends AbstractMenu {
+ private Builder builder;
+
+ public SelectPlotTypeMenu(Player player) {
+ super(3, LangUtil.get(player, LangPaths.MenuTitle.SELECT_PLOT_TYPE), player);
+ }
+
+ @Override
+ protected void setPreviewItems() {
+ super.setPreviewItems();
+
+ builder = Builder.byUUID(getMenuPlayer().getUniqueId());
+ }
+
+ @Override
+ protected void setMenuItemsAsync() {
+ // Set plot type items
+ getMenu().getSlot(11).setItem(
+ new ItemBuilder(Utils.CustomHead.FOCUS_MODE.getAsItemStack())
+ .setName("§6§l" + LangUtil.get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_FOCUS_MODE))
+ .setLore(new LoreBuilder()
+ .addLines(Utils.createMultilineFromString(LangUtil.get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_FOCUS_MODE), AbstractMenu.MAX_CHARS_PER_LINE, AbstractMenu.LINE_BAKER))
+ .build())
+ .setEnchanted(builder.getPlotTypeSetting().getId() == PlotType.FOCUS_MODE.getId())
+ .build());
+
+ getMenu().getSlot(13).setItem(
+ new ItemBuilder(Material.SAPLING, 1, (byte) 5)
+ .setName("§6§l" + LangUtil.get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_INSPIRATION_MODE))
+ .setLore(new LoreBuilder()
+ .addLines(Utils.createMultilineFromString(LangUtil.get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_INSPIRATION_MODE), AbstractMenu.MAX_CHARS_PER_LINE, AbstractMenu.LINE_BAKER))
+ .build())
+ .setEnchanted(builder.getPlotTypeSetting().getId() == PlotType.LOCAL_INSPIRATION_MODE.getId())
+ .build());
+
+ getMenu().getSlot(15).setItem(
+ new ItemBuilder(Utils.CustomHead.CITY_INSPIRATION_MODE.getAsItemStack())
+ .setName("§6§l" + LangUtil.get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_CITY_INSPIRATION_MODE))
+ .setLore(new LoreBuilder()
+ .addLines(Utils.createMultilineFromString(LangUtil.get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_CITY_INSPIRATION_MODE), AbstractMenu.MAX_CHARS_PER_LINE, AbstractMenu.LINE_BAKER))
+ .build())
+ .setEnchanted(builder.getPlotTypeSetting().getId() == PlotType.CITY_INSPIRATION_MODE.getId())
+ .build());
+
+ // Set selected glass pane
+ int selectedPlotTypeSlot = 13;
+ if(builder.getPlotTypeSetting() == PlotType.FOCUS_MODE)
+ selectedPlotTypeSlot = 11;
+ if(builder.getPlotTypeSetting() == PlotType.CITY_INSPIRATION_MODE)
+ selectedPlotTypeSlot = 15;
+ getMenu().getSlot(selectedPlotTypeSlot - 9).setItem(new ItemBuilder(Material.STAINED_GLASS_PANE, 1, (byte) 5).setName(" ").build());
+
+
+ // Set back item
+ getMenu().getSlot(22).setItem(MenuItems.backMenuItem(getMenuPlayer()));
+ }
+
+ @Override
+ protected void setItemClickEventsAsync() {
+ // Set click event for plot type items
+ getMenu().getSlot(11).setClickHandler(((clickPlayer, clickInformation) -> {
+ builder.setPlotTypeSetting(PlotType.FOCUS_MODE);
+ getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.Done, 1f, 1f);
+ reloadMenuAsync();
+ }));
+
+ getMenu().getSlot(13).setClickHandler(((clickPlayer, clickInformation) -> {
+ builder.setPlotTypeSetting(PlotType.LOCAL_INSPIRATION_MODE);
+ getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.Done, 1f, 1f);
+ reloadMenuAsync();
+ }));
+
+ getMenu().getSlot(15).setClickHandler(((clickPlayer, clickInformation) -> {
+ builder.setPlotTypeSetting(PlotType.CITY_INSPIRATION_MODE);
+ getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.Done, 1f, 1f);
+ reloadMenuAsync();
+ }));
+
+ // Set click event for back item
+ getMenu().getSlot(22).setClickHandler((clickPlayer, clickInformation) -> new SettingsMenu(clickPlayer));
+ }
+
+ @Override
+ protected Mask getMask() {
+ return BinaryMask.builder(getMenu())
+ .item(new ItemBuilder(Material.STAINED_GLASS_PANE, 1, (byte) 7).setName(" ").build())
+ .pattern("111111111")
+ .pattern("000000000")
+ .pattern("111101111")
+ .build();
+ }
+}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java
index 83b0d97d..8b3f4149 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java
@@ -19,7 +19,7 @@ public SettingsMenu(Player player) {
@Override
protected void setMenuItemsAsync() {
// Set language item
- getMenu().getSlot(10).setItem(
+ getMenu().getSlot(11).setItem(
new ItemBuilder(Utils.CustomHead.GLOBE.getAsItemStack())
.setName("§6§l" + LangUtil.get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_LANGUAGE))
.setLore(new LoreBuilder()
@@ -27,18 +27,33 @@ protected void setMenuItemsAsync() {
.build())
.build());
+ // Set Plot type item
+ getMenu().getSlot(15).setItem(
+ new ItemBuilder(Utils.CustomHead.PLOT_TYPE.getAsItemStack())
+ .setName("§6§l" + LangUtil.get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_PLOT_TYPE))
+ .setLore(new LoreBuilder()
+ .addLine(LangUtil.get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_PLOT_TYPE))
+ .build())
+ .build());
+
// Set back item
getMenu().getSlot(22).setItem(MenuItems.backMenuItem(getMenuPlayer()));
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for language item
- getMenu().getSlot(10).setClickHandler(((clickPlayer, clickInformation) -> {
+ getMenu().getSlot(11).setClickHandler(((clickPlayer, clickInformation) -> {
getMenuPlayer().closeInventory();
new SelectLanguageMenu(clickPlayer);
}));
+ // Set click event for plot type item
+ getMenu().getSlot(15).setClickHandler(((clickPlayer, clickInformation) -> {
+ getMenuPlayer().closeInventory();
+ new SelectPlotTypeMenu(clickPlayer);
+ }));
+
// Set click event for back item
getMenu().getSlot(22).setClickHandler((clickPlayer, clickInformation) -> clickPlayer.performCommand("companion"));
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialBlocksMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialBlocksMenu.java
index 736817e9..db87ee7a 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialBlocksMenu.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialBlocksMenu.java
@@ -56,7 +56,7 @@ protected void setMenuItemsAsync() {
}
@Override
- protected void setItemClickEvents() {
+ protected void setItemClickEventsAsync() {
// Set click event for special block items
for(int i = 0; i <= 14; i++) {
int specialBlockID = i;
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java b/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java
index acbb667b..b17244a4 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java
@@ -30,6 +30,7 @@
import com.alpsbte.plotsystem.core.database.DatabaseConnection;
import com.alpsbte.plotsystem.core.holograms.PlotsLeaderboard;
import com.alpsbte.plotsystem.core.holograms.ScoreLeaderboard;
+import com.alpsbte.plotsystem.core.system.plot.PlotType;
import com.alpsbte.plotsystem.utils.enums.Slot;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -37,27 +38,42 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
public class Builder {
- private final UUID UUID;
+ public static HashMap builders = new HashMap<>();
- public Builder(UUID UUID) {
- this.UUID = UUID;
+ private final UUID uuid;
+ public PlotType plotType;
+
+ private Builder(UUID UUID) {
+ this.uuid = UUID;
}
+ public static Builder byUUID(UUID uuid){
+ if(builders.containsKey(uuid))
+ return builders.get(uuid);
+
+ Builder builder = new Builder(uuid);
+ builders.put(uuid, builder);
+
+ return builders.get(uuid);
+ }
+
+
public Player getPlayer() {
- return Bukkit.getPlayer(UUID);
+ return Bukkit.getPlayer(uuid);
}
public java.util.UUID getUUID() {
- return UUID;
+ return uuid;
}
- public boolean isOnline() { return Bukkit.getPlayer(UUID) != null; }
+ public boolean isOnline() { return Bukkit.getPlayer(uuid) != null; }
public String getName() throws SQLException {
try (ResultSet rs = DatabaseConnection.createStatement("SELECT name FROM plotsystem_builders WHERE uuid = ?")
@@ -174,7 +190,7 @@ public static Builder getBuilderByName(String name) throws SQLException {
if (rs.next()) {
String s = rs.getString(1);
DatabaseConnection.closeResultSet(rs);
- return new Builder(java.util.UUID.fromString(s));
+ return Builder.byUUID(UUID.fromString(s));
}
DatabaseConnection.closeResultSet(rs);
@@ -245,4 +261,44 @@ public void setLanguageTag(String langTag) throws SQLException {
.executeUpdate();
}
}
+
+ public PlotType getPlotTypeSetting() {
+ if(plotType != null)
+ return plotType;
+
+ try (ResultSet rs = DatabaseConnection.createStatement("SELECT setting_plot_type FROM plotsystem_builders WHERE uuid = ?")
+ .setValue(getUUID().toString()).executeQuery()) {
+
+ if (rs.next()) {
+ int id = rs.getInt(1);
+ this.plotType = PlotType.byId(id);
+ DatabaseConnection.closeResultSet(rs);
+
+ return plotType;
+ }
+ DatabaseConnection.closeResultSet(rs);
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE,"An error occurred while getting language setting from database", ex);
+ }
+ return null;
+ }
+
+ public void setPlotTypeSetting(PlotType plotType){
+ try {
+ if (plotType == null) {
+ DatabaseConnection.createStatement("UPDATE plotsystem_builders SET setting_plot_type = DEFAULT(setting_plot_type) WHERE uuid = ?")
+ .setValue(getUUID().toString()).executeUpdate();
+ } else {
+ DatabaseConnection.createStatement("UPDATE plotsystem_builders SET setting_plot_type = ? WHERE uuid = ?")
+ .setValue(plotType.getId()).setValue(getUUID().toString())
+ .executeUpdate();
+ }
+ }catch (SQLException ex){
+ Bukkit.getLogger().log(Level.SEVERE,"An error occurred while getting language setting from database", ex);
+ }
+
+ this.plotType = plotType;
+ }
+
+
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Review.java b/src/main/java/com/alpsbte/plotsystem/core/system/Review.java
index 37975ee6..0cbaec40 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/Review.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/Review.java
@@ -93,7 +93,7 @@ public Builder getReviewer() throws SQLException {
if (rs.next()) {
String s = rs.getString(1);
DatabaseConnection.closeResultSet(rs);
- return new Builder(UUID.fromString(s));
+ return Builder.byUUID(UUID.fromString(s));
}
DatabaseConnection.closeResultSet(rs);
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/IPlot.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/IPlot.java
index d3d2a377..53018acd 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/IPlot.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/IPlot.java
@@ -31,13 +31,13 @@
import com.alpsbte.plotsystem.utils.enums.PlotDifficulty;
import com.alpsbte.plotsystem.utils.enums.Slot;
import com.alpsbte.plotsystem.utils.enums.Status;
-import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
+import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
@@ -69,8 +69,9 @@ public interface IPlot {
/**
* @return polygon outline of the plot
* @throws SQLException SQL database exception
+ * @throws IOException IO exception
*/
- List getOutline() throws SQLException;
+ List getOutline() throws SQLException, IOException;
/**
* Sets the given builder to the plot owner
@@ -99,14 +100,14 @@ public interface IPlot {
Review getReview() throws SQLException;
/**
- * @return plot world, can be null if it has not yet been generated
+ * @return plot world, can be one or city plot world
*/
- PlotWorld getWorld();
+ T getWorld() throws SQLException;
/**
* @return plot permission manager to add or remove build rights
*/
- PlotPermissions getPermissions();
+ PlotPermissions getPermissions() throws SQLException;
/**
* @return total points given for the plot
@@ -177,6 +178,11 @@ public interface IPlot {
*/
File getOutlinesSchematic();
+ /**
+ * @return schematic file with environment only
+ */
+ File getEnvironmentSchematic();
+
/**
* @return schematic file of the completed plot
*/
@@ -186,9 +192,9 @@ public interface IPlot {
* Returns geographic coordinates in numeric format
* @return WG84 EPSG:4979 coordinates as double array {lon,lat} in degrees
* @see com.alpsbte.plotsystem.utils.conversion.CoordinateConversion#convertToGeo(double, double)
- * @throws SQLException SQL database exception
+ * @throws IOException fails to load schematic file
*/
- String getGeoCoordinates() throws SQLException;
+ String getGeoCoordinates() throws IOException;
/**
* Returns in-game Minecraft coordinates on a Terra121 world
@@ -196,14 +202,43 @@ public interface IPlot {
* @see com.alpsbte.plotsystem.utils.conversion.CoordinateConversion#convertFromGeo(double, double)
* @throws SQLException SQL database exception
*/
+ @Deprecated
Vector getMinecraftCoordinates() throws SQLException;
+ /**
+ * Returns in-game Minecraft coordinates on a Terra121 world
+ * @return the in-game coordinates (x, z)
+ * @see com.alpsbte.plotsystem.utils.conversion.CoordinateConversion#convertFromGeo(double, double)
+ * @throws IOException fails to load schematic file
+ */
+ Vector getCoordinates() throws IOException;
+
+ /**
+ * Returns the plot type the player has selected when creating the plot
+ * @return the plot type
+ * @throws SQLException SQL database exception
+ */
+ PlotType getPlotType() throws SQLException;
+
+ /**
+ * Sets the plot type the player has selected
+ * @param type plot type
+ * @throws SQLException SQL database exception
+ */
+ void setPlotType(PlotType type) throws SQLException;
+
/**
* @param pasted if true, plot has been pasted on the Terra121 server
* @throws SQLException SQL database exception
*/
void setPasted(boolean pasted) throws SQLException;
+ /**
+ * @return plot version in which it was created
+ * @throws SQLException SQL database exception
+ */
+ double getVersion() throws SQLException;
+
/**
* @return if {@link #getReview()} is null, it will return false
* @throws SQLException SQL database exception
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java
index 70ac3f6c..3cbec94c 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java
@@ -27,8 +27,11 @@
import com.alpsbte.plotsystem.core.system.CityProject;
import com.alpsbte.plotsystem.core.system.Review;
import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld;
+import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld;
+import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld;
+import com.alpsbte.plotsystem.utils.Utils;
import com.alpsbte.plotsystem.utils.conversion.CoordinateConversion;
-import com.sk89q.worldedit.BlockVector;
+import com.boydti.fawe.FaweAPI;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.Vector;
import com.alpsbte.plotsystem.core.database.DatabaseConnection;
@@ -38,10 +41,13 @@
import com.alpsbte.plotsystem.utils.enums.Slot;
import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.ftp.FTPManager;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.regions.CuboidRegion;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import java.io.File;
+import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.sql.ResultSet;
@@ -54,9 +60,18 @@
import java.util.stream.Collectors;
public class Plot implements IPlot {
+ public static final double PLOT_VERSION = 3;
private final int ID;
- private PlotWorld plotWorld;
+ private List outline;
+ private List blockOutline;
+ private CityProject city;
+ private Builder plotOwner;
+ private PlotType plotType;
+ private double plotVersion = -1;
+
+ private OnePlotWorld onePlotWorld;
+ private CityPlotWorld cityPlotWorld;
private PlotPermissions plotPermissions;
public Plot(int ID) throws SQLException {
@@ -70,13 +85,20 @@ public int getID() {
@Override
public CityProject getCity() throws SQLException {
+ if(this.city != null)
+ return this.city;
+
try (ResultSet rs = DatabaseConnection.createStatement("SELECT city_project_id FROM plotsystem_plots WHERE id = ?")
.setValue(this.ID).executeQuery()) {
if (rs.next()){
int i = rs.getInt(1);
DatabaseConnection.closeResultSet(rs);
- return new CityProject(i);
+ CityProject cityProject = new CityProject(i);
+
+ this.city = cityProject;
+
+ return cityProject;
}
DatabaseConnection.closeResultSet(rs);
@@ -101,31 +123,66 @@ public PlotDifficulty getDifficulty() throws SQLException {
}
@Override
- public List getOutline() throws SQLException {
+ /* return the outline of the plot which contains all corner points of the polygon */
+ public List getOutline() throws SQLException, IOException {
+ if(this.outline != null)
+ return this.outline;
+
try (ResultSet rs = DatabaseConnection.createStatement("SELECT outline FROM plotsystem_plots WHERE id = ?")
.setValue(this.ID).executeQuery()) {
+ List locations = new ArrayList<>();
if (rs.next()){
- List locations = new ArrayList<>();
- String[] list = rs.getString(1).split("\\|");
-
- for(String s : list) {
- String[] locs = s.split(",");
- locations.add(new BlockVector2D(Double.parseDouble(locs[0]), Double.parseDouble(locs[1])));
+ String listString = rs.getString(1);
+ if (rs.wasNull() || listString.isEmpty() || getVersion() <= 2) {
+ CuboidRegion plotRegion = PlotManager.getPlotAsRegion(this);
+ if (plotRegion != null) locations.addAll(plotRegion.polygonize(4));
+ } else {
+ String[] list = listString.split("\\|");
+
+ for (String s : list) {
+ String[] locs = s.split(",");
+ locations.add(new BlockVector2D(Double.parseDouble(locs[0]), Double.parseDouble(locs[1])));
+ }
}
-
- DatabaseConnection.closeResultSet(rs);
- return locations;
}
+ this.outline = locations;
DatabaseConnection.closeResultSet(rs);
+ return locations;
}
+ }
- return null;
+ /** return the outline of the polygon with one point per Block*/
+ public List getBlockOutline() throws SQLException, IOException {
+ if(this.blockOutline != null)
+ return this.blockOutline;
+
+ List points = new ArrayList<>();
+ List outline = getOutline();
+
+ for(int i = 0; i < outline.size() - 1; i++){
+ BlockVector2D b1 = outline.get(i);
+ BlockVector2D b2 = outline.get(i + 1);
+ int distance = (int) b1.distance(b2);
+
+ points.addAll(Utils.getLineBetweenPoints(b1, b2, distance));
+ }
+
+ BlockVector2D first = outline.get(0);
+ BlockVector2D last = outline.get(outline.size() - 1);
+ points.addAll(Utils.getLineBetweenPoints(last, first, (int) first.distance(last)));
+
+ blockOutline = points;
+
+ return points;
}
@Override
public Builder getPlotOwner() throws SQLException {
+ if(plotOwner != null)
+ return plotOwner;
+
if(getStatus() != Status.unclaimed) {
try (ResultSet rs = DatabaseConnection.createStatement("SELECT owner_uuid FROM plotsystem_plots WHERE id = ?")
.setValue(this.ID).executeQuery()) {
@@ -133,7 +190,10 @@ public Builder getPlotOwner() throws SQLException {
if (rs.next()){
String s = rs.getString(1);
DatabaseConnection.closeResultSet(rs);
- return new Builder(UUID.fromString(s));
+
+ plotOwner = Builder.byUUID(UUID.fromString(s));
+
+ return plotOwner;
}
DatabaseConnection.closeResultSet(rs);
@@ -151,6 +211,8 @@ public void setPlotOwner(String UUID) throws SQLException {
DatabaseConnection.createStatement("UPDATE plotsystem_plots SET owner_uuid = ? WHERE id = ?")
.setValue(UUID).setValue(this.ID).executeUpdate();
}
+
+ plotOwner = null;
}
@Override
@@ -166,7 +228,7 @@ public List getPlotMembers() throws SQLException {
String[] uuidMembers = members.split(",");
for (String uuid : uuidMembers) {
- builders.add(new Builder(UUID.fromString(uuid)));
+ builders.add(Builder.byUUID(UUID.fromString(uuid)));
}
}
}
@@ -208,10 +270,19 @@ public Review getReview() throws SQLException {
return null;
}
+ @SuppressWarnings("unchecked")
@Override
- public PlotWorld getWorld() {
- if (plotWorld == null) plotWorld = new PlotWorld(this);
- return plotWorld;
+ public T getWorld() {
+ try {
+ if (getVersion() <= 2 || getPlotType().hasOnePlotPerWorld()) {
+ if (onePlotWorld == null) onePlotWorld = new OnePlotWorld(this);
+ return (T) onePlotWorld;
+ } else {
+ if (cityPlotWorld == null) cityPlotWorld = new CityPlotWorld(this);
+ return (T) cityPlotWorld;
+ }
+ } catch (SQLException ex) { Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex); }
+ return null;
}
@Override
@@ -333,7 +404,7 @@ public Builder getPlotCreator() throws SQLException {
if (rs.next()) {
String s = rs.getString(1);
DatabaseConnection.closeResultSet(rs);
- return new Builder(UUID.fromString(s));
+ return Builder.byUUID(UUID.fromString(s));
}
DatabaseConnection.closeResultSet(rs);
@@ -365,10 +436,19 @@ public Slot getSlot() throws SQLException {
@Override
public File getOutlinesSchematic() {
+ return getSchematic(getID() + "");
+ }
+
+ @Override
+ public File getEnvironmentSchematic() {
+ return getSchematic(getID() + "-env");
+ }
+
+ private File getSchematic(String filename){
try {
return CompletableFuture.supplyAsync(() -> {
try {
- File file = Paths.get(PlotManager.getDefaultSchematicPath(), String.valueOf(getCity().getCountry().getServer().getID()), String.valueOf(getCity().getID()), getID() + ".schematic").toFile();
+ File file = Paths.get(PlotManager.getDefaultSchematicPath(), String.valueOf(getCity().getCountry().getServer().getID()), String.valueOf(getCity().getID()), filename + ".schematic").toFile();
if(!file.exists()) {
if (getCity().getCountry().getServer().getFTPConfiguration() != null) {
@@ -397,9 +477,9 @@ public File getFinishedSchematic() {
}
@Override
- public String getGeoCoordinates() throws SQLException {
+ public String getGeoCoordinates() throws IOException {
// Convert MC coordinates to geo coordinates
- Vector mcCoordinates = getMinecraftCoordinates();
+ Vector mcCoordinates = getCoordinates();
try {
return CoordinateConversion.formatGeoCoordinatesNumeric(CoordinateConversion.convertToGeo(mcCoordinates.getX(), mcCoordinates.getZ()));
} catch (OutOfProjectionBoundsException ex) {
@@ -408,6 +488,7 @@ public String getGeoCoordinates() throws SQLException {
return null;
}
+ @Deprecated
@Override
public Vector getMinecraftCoordinates() throws SQLException {
try (ResultSet rs = DatabaseConnection.createStatement("SELECT mc_coordinates FROM plotsystem_plots WHERE id = ?")
@@ -425,15 +506,64 @@ public Vector getMinecraftCoordinates() throws SQLException {
}
}
- public String getOSMMapsLink() throws SQLException {
+ @Override
+ public Vector getCoordinates() throws IOException {
+ Clipboard clipboard = FaweAPI.load(getOutlinesSchematic()).getClipboard();
+ if (clipboard != null) return clipboard.getOrigin();
+ return null;
+ }
+
+ @Override
+ public PlotType getPlotType() throws SQLException {
+ if (plotType != null) return plotType;
+
+ try (ResultSet rs = DatabaseConnection.createStatement("SELECT type FROM plotsystem_plots WHERE id = ?")
+ .setValue(this.ID).executeQuery()) {
+
+ if (rs.next()) {
+ int typeId = rs.getInt(1);
+ DatabaseConnection.closeResultSet(rs);
+
+ plotType = PlotType.byId(typeId);
+ return plotType;
+ }
+
+ DatabaseConnection.closeResultSet(rs);
+ return null;
+ }
+ }
+
+ @Override
+ public void setPlotType(PlotType type) throws SQLException {
+ DatabaseConnection.createStatement("UPDATE plotsystem_plots SET type = ? WHERE id = ?")
+ .setValue(type.ordinal()).setValue(this.ID).executeUpdate();
+ plotType = type;
+ }
+
+ public Vector getCenter() {
+ try {
+ if (getVersion() >= 3) {
+ Clipboard clipboard = FaweAPI.load(getOutlinesSchematic()).getClipboard();
+ if (clipboard != null) {
+ Vector clipboardCenter = clipboard.getRegion().getCenter();
+ return new Vector(clipboardCenter.getX(), this.getWorld().getPlotHeightCentered(), clipboardCenter.getZ());
+ }
+ } else return new Vector(PlotWorld.PLOT_SIZE / 2d, this.getWorld().getPlotHeightCentered(), PlotWorld.PLOT_SIZE / 2d);
+ } catch (IOException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "Failed to load schematic file to clipboard!", ex);
+ }
+ return null;
+ }
+
+ public String getOSMMapsLink() throws IOException {
return "https://www.openstreetmap.org/#map=19/" + getGeoCoordinates().replace(",", "/");
}
- public String getGoogleMapsLink() throws SQLException {
+ public String getGoogleMapsLink() throws IOException {
return "https://www.google.com/maps/place/"+ getGeoCoordinates();
}
- public String getGoogleEarthLink() throws SQLException {
+ public String getGoogleEarthLink() throws IOException {
return "https://earth.google.com/web/@" + getGeoCoordinates() + ",0a,1000d,20y,-0h,0t,0r";
}
@@ -443,6 +573,30 @@ public void setPasted(boolean pasted) throws SQLException {
.setValue(pasted).setValue(this.ID).executeUpdate();
}
+ @Override
+ public double getVersion() {
+ if (plotVersion != -1) return plotVersion;
+
+ try (ResultSet rs = DatabaseConnection.createStatement("SELECT version FROM plotsystem_plots WHERE id = ?")
+ .setValue(this.ID).executeQuery()) {
+
+ if (rs.next()) {
+ double version = rs.getDouble(1);
+ if (!rs.wasNull()) {
+ plotVersion = version;
+ } else {
+ plotVersion = 2; // Plot version was implemented since v3, so we assume that the plot is v2.
+ }
+
+ DatabaseConnection.closeResultSet(rs);
+ return plotVersion;
+ }
+
+ DatabaseConnection.closeResultSet(rs);
+ } catch (SQLException ex) { Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex); }
+ return PLOT_VERSION;
+ }
+
public void addPlotMember(Builder member) throws SQLException {
List members = getPlotMembers();
if (members.size() < 3 && members.stream().noneMatch(m -> m.getUUID().equals(member.getUUID()))) {
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotHandler.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotHandler.java
index e198a5fd..c5b5749d 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotHandler.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotHandler.java
@@ -28,6 +28,9 @@
import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.database.DatabaseConnection;
import com.alpsbte.plotsystem.core.system.Server;
+import com.alpsbte.plotsystem.core.system.plot.generator.AbstractPlotGenerator;
+import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld;
+import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld;
import com.alpsbte.plotsystem.utils.ShortLink;
import com.alpsbte.plotsystem.utils.Utils;
import com.alpsbte.plotsystem.utils.enums.Status;
@@ -35,6 +38,9 @@
import com.alpsbte.plotsystem.utils.io.config.ConfigPaths;
import com.alpsbte.plotsystem.utils.io.language.LangPaths;
import com.alpsbte.plotsystem.utils.io.language.LangUtil;
+import com.sk89q.worldedit.WorldEditException;
+import com.sk89q.worldguard.bukkit.RegionContainer;
+import com.sk89q.worldguard.protection.managers.RegionManager;
import net.md_5.bungee.api.chat.*;
import org.bukkit.*;
import org.bukkit.entity.Player;
@@ -46,6 +52,7 @@
import java.nio.file.Paths;
import java.sql.SQLException;
import java.text.DecimalFormat;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@@ -57,7 +64,7 @@ public static void submitPlot(Plot plot) throws SQLException {
plot.setStatus(Status.unreviewed);
if(plot.getWorld().isWorldLoaded()) {
- for(Player player : plot.getWorld().getBukkitWorld().getPlayers()) {
+ for(Player player : plot.getWorld() instanceof OnePlotWorld ? plot.getWorld().getBukkitWorld().getPlayers() : ((CityPlotWorld) plot.getWorld()).getPlayersOnPlot()) {
player.teleport(Utils.getSpawnLocation());
}
}
@@ -74,52 +81,82 @@ public static void undoSubmit(Plot plot) throws SQLException {
plot.setStatus(Status.unfinished);
plot.getPermissions().addBuilderPerms(plot.getPlotOwner().getUUID()).save();
+ if (plot.getPlotMembers().size() != 0) {
+ for (Builder builder : plot.getPlotMembers()) {
+ plot.getPermissions().addBuilderPerms(builder.getUUID());
+ }
+ }
}
public static boolean abandonPlot(Plot plot) {
try {
- if (plot.getWorld().isWorldGenerated() && plot.getWorld().loadWorld()) {
- for (Player player : plot.getWorld().getBukkitWorld().getPlayers()) {
- player.teleport(Utils.getSpawnLocation());
+ if (plot.getWorld() instanceof OnePlotWorld) {
+ if (plot.getWorld().isWorldGenerated()) {
+ if (plot.getWorld().isWorldLoaded()) {
+ for(Player player : plot.getWorld().getBukkitWorld().getPlayers()) {
+ player.teleport(Utils.getSpawnLocation());
+ }
+ }
+ if (!plot.getWorld().deleteWorld()) Bukkit.getLogger().log(Level.WARNING, "Could not delete plot world " + plot.getWorld().getWorldName() + "!");
}
+ } else {
+ RegionContainer regionContainer = PlotSystem.DependencyManager.getWorldGuard().getRegionContainer();
- if (plot.getWorld().deleteWorld()) {
- for (Builder builder : plot.getPlotMembers()) {
- plot.removePlotMember(builder);
+ if (plot.getWorld().loadWorld()) {
+ CityPlotWorld world = plot.getWorld();
+ List playersToTeleport = new ArrayList<>(world.getPlayersOnPlot());
+
+ RegionManager regionManager = regionContainer.get(world.getBukkitWorld());
+ if (regionManager != null) {
+ for (Builder builder : plot.getPlotMembers()) {
+ plot.removePlotMember(builder);
+ }
+
+ if (regionManager.hasRegion(world.getRegionName())) regionManager.removeRegion(world.getRegionName());
+ if (regionManager.hasRegion(world.getRegionName() + "-1")) regionManager.removeRegion(world.getRegionName() + "-1");
+
+ AbstractPlotGenerator.pasteSchematic(null, plot.getOutlinesSchematic(), world, true);
+ } else Bukkit.getLogger().log(Level.WARNING, "Region Manager is null!");
+
+ playersToTeleport.forEach(p -> p.teleport(Utils.getSpawnLocation()));
+ if (plot.getWorld().isWorldLoaded()) plot.getWorld().unloadWorld(false);
+ }
+ }
+ } catch (SQLException | IOException | WorldEditException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "Failed to abandon plot with the ID " + plot.getID() + "!", ex);
+ return false;
+ }
+
+ try {
+ CompletableFuture.runAsync(() -> {
+ try {
+ if (plot.isReviewed()) {
+ DatabaseConnection.createStatement("UPDATE plotsystem_plots SET review_id = DEFAULT(review_id) WHERE id = ?")
+ .setValue(plot.getID()).executeUpdate();
+
+ DatabaseConnection.createStatement("DELETE FROM plotsystem_reviews WHERE id = ?")
+ .setValue(plot.getReview().getReviewID()).executeUpdate();
}
- try {
- CompletableFuture.runAsync(() -> {
- try {
- if (plot.isReviewed()) {
- DatabaseConnection.createStatement("UPDATE plotsystem_plots SET review_id = DEFAULT(review_id) WHERE id = ?")
- .setValue(plot.getID()).executeUpdate();
-
- DatabaseConnection.createStatement("DELETE FROM plotsystem_reviews WHERE id = ?")
- .setValue(plot.getReview().getReviewID()).executeUpdate();
- }
-
- plot.getPlotOwner().removePlot(plot.getSlot());
- plot.setPlotOwner(null);
- plot.setLastActivity(true);
- plot.setTotalScore(-1);
- plot.setStatus(Status.unclaimed);
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
- throw new CompletionException(ex);
- }
- }).join();
- } catch (CompletionException ex) {
- return false;
+ if (plot.getPlotOwner() != null) {
+ PlotManager.clearCache(plot.getPlotOwner().getUUID());
+ plot.getPlotOwner().removePlot(plot.getSlot());
}
- return true;
+ plot.setPlotOwner(null);
+ plot.setLastActivity(true);
+ plot.setTotalScore(-1);
+ plot.setStatus(Status.unclaimed);
+ plot.setPlotType(PlotType.LOCAL_INSPIRATION_MODE);
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ throw new CompletionException(ex);
}
- }
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }).join();
+ } catch (CompletionException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "Failed to abandon plot with the ID " + plot.getID() + "!", ex);
+ return false;
}
- Bukkit.getLogger().log(Level.WARNING, "Failed to abandon plot with the ID " + plot.getID() + "!");
- return false;
+ return true;
}
public static boolean deletePlot(Plot plot) throws SQLException {
@@ -184,8 +221,6 @@ public static void sendLinkMessages(Plot plot, Player player){
tc[0].setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, plot.getGoogleMapsLink()));
tc[1].setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, plot.getGoogleEarthLink()));
tc[2].setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, plot.getOSMMapsLink()));
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, "A SQl error occurred!", ex);
} catch (IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, "An error occurred while creating shortlink!", ex);
}
@@ -203,7 +238,7 @@ public static void sendLinkMessages(Plot plot, Player player){
DecimalFormat df = new DecimalFormat("##.#####");
df.setRoundingMode(RoundingMode.FLOOR);
coords = "§a" + df.format(lat) + "§7, §a" + df.format(lon);
- } catch (SQLException ex) {
+ } catch (IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotManager.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotManager.java
index 824a7ba8..141b1743 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotManager.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotManager.java
@@ -24,8 +24,16 @@
package com.alpsbte.plotsystem.core.system.plot;
+import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld;
+import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld;
import com.alpsbte.plotsystem.utils.io.config.ConfigPaths;
import com.alpsbte.plotsystem.core.system.CityProject;
+import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld;
+import com.boydti.fawe.FaweAPI;
+import com.github.fierioziy.particlenativeapi.api.ParticleNativeAPI;
+import com.github.fierioziy.particlenativeapi.api.Particles_1_8;
+import com.github.fierioziy.particlenativeapi.plugin.ParticleNativePlugin;
+import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@@ -43,9 +51,13 @@
import com.alpsbte.plotsystem.utils.enums.PlotDifficulty;
import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.ftp.FTPManager;
+import com.sk89q.worldedit.regions.Polygonal2DRegion;
import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.entity.Player;
import java.io.File;
import java.io.FileInputStream;
@@ -55,16 +67,80 @@
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
public class PlotManager {
+ // TODO: Start -> Move to another class
+ public static int CACHE_UPDATE_TICKS = 20*60;
- public final static int PLOT_SIZE = 150;
+ public static int time;
+
+ public static HashMap> cachedInProgressPlots = new HashMap<>();
+
+ private static boolean ParticleAPIEnabled = false;
+ private static Particles_1_8 particles;
+
+
+
+ public static void startTimer(){
+ if(PlotSystem.DependencyManager.isParticleNativeAPIEnabled())
+ loadParticleNativeAPI();
+
+ Bukkit.getScheduler().scheduleSyncDelayedTask(PlotSystem.getPlugin(), () -> {
+ if(PlotSystem.DependencyManager.isParticleNativeAPIEnabled())
+ loadParticleNativeAPI();
+ }, 20*10L);
+
+
+ Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), PlotManager::tick, 0L, 0L);
+ }
+
+ public static void tick(){
+ time++;
+
+ if(time%CACHE_UPDATE_TICKS == 0)
+ clearCache();
+
+
+ if(time%10 == 0)
+ showOutlines();
+ }
+
+ public static void clearCache(){
+ cachedInProgressPlots.clear();
+ }
+
+ public static void clearCache(UUID builderUUID) {
+ cachedInProgressPlots.remove(builderUUID);
+ }
+
+ public static void loadParticleNativeAPI(){
+ ParticleAPIEnabled = PlotSystem.DependencyManager.isParticleNativeAPIEnabled();
+
+ // get API
+ ParticleNativeAPI api = ParticleNativePlugin.getAPI();
+
+ // choose particles lists you want to use
+ particles = api.getParticles_1_8();
+ }
+
+
+
+ public static List getCachedInProgressPlots(Builder builder){
+ if(!cachedInProgressPlots.containsKey(builder.getUUID())) {
+ try {
+ cachedInProgressPlots.put(builder.getUUID(), getPlots(builder, Status.unfinished));
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ return new ArrayList<>();
+ }
+ }
+
+ return cachedInProgressPlots.get(builder.getUUID());
+ }
+ // TODO: End -> Move to another class
public static List getPlots() throws SQLException {
return listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots").executeQuery());
@@ -82,9 +158,23 @@ public static List getPlots(Builder builder) throws SQLException {
}
public static List getPlots(Builder builder, Status... statuses) throws SQLException {
- List plots = listPlots(DatabaseConnection.createStatement(getStatusQuery( "' AND owner_uuid = '" + builder.getUUID(), statuses)).executeQuery());
- //plots.addAll(listPlots(DatabaseConnection.createStatement(getStatusQuery("id", "' AND INSTR(member_uuids, '" + builder.getUUID() + "') > 0", statuses)).executeQuery()));
- // TODO: Add support for member plots
+ List plots = listPlots(DatabaseConnection.createStatement(getStatusQuery("' AND owner_uuid = '" + builder.getUUID(), statuses)).executeQuery());
+ plots.addAll(getPlotsAsMember(builder, statuses));
+ return plots;
+ }
+
+ public static List getPlots(Builder builder, int cityID, Status... statuses) throws SQLException {
+ List plots = listPlots(DatabaseConnection.createStatement(getStatusQuery( "' AND owner_uuid = '" + builder.getUUID() + "' AND city_project_id = '" + cityID, statuses)).executeQuery());
+ plots.addAll(getPlotsAsMember(builder, statuses));
+ return plots;
+ }
+
+ // Temporary fix to receive plots of builder as member
+ private static List getPlotsAsMember(Builder builder, Status... status) throws SQLException {
+ List plots = new ArrayList<>();
+ for (Status stat : status) {
+ plots.addAll(listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots WHERE status = '" + stat.name() + "' AND INSTR(member_uuids, '" + builder.getUUID() + "') > 0 ORDER BY CAST(status AS CHAR)").executeQuery()));
+ }
return plots;
}
@@ -150,97 +240,108 @@ private static List listPlots(ResultSet rs) throws SQLException {
return plots;
}
- public static boolean savePlotAsSchematic(Plot plot) throws IOException, SQLException, WorldEditException {
- // TODO: MOVE CONVERSION TO SEPERATE METHODS
-
- Vector terraOrigin, schematicOrigin, plotOrigin;
- Vector schematicMinPoint, schematicMaxPoint;
- Vector plotCenter;
-
- // Load plot outlines schematic as clipboard
- Clipboard outlinesClipboard = ClipboardFormat.SCHEMATIC.getReader(new FileInputStream(plot.getOutlinesSchematic())).read(null);
-
- // Get player origin coordinates on terra
- terraOrigin = plot.getMinecraftCoordinates();
-
-
- // Get plot center
- plotCenter = PlotManager.getPlotCenter();
-
-
- // Calculate min and max points of schematic
- int outlinesClipboardCenterX = (int) Math.floor(outlinesClipboard.getRegion().getWidth() / 2d);
- int outlinesClipboardCenterZ = (int) Math.floor(outlinesClipboard.getRegion().getLength() / 2d);
-
- schematicMinPoint = Vector.toBlockPoint(
- plotCenter.getX() - outlinesClipboardCenterX,
- PlotManager.getPlotCenter().getY(),
- plotCenter.getZ() - outlinesClipboardCenterZ
- );
-
- schematicMaxPoint = Vector.toBlockPoint(
- plotCenter.getX() + outlinesClipboardCenterX,
- 256,
- plotCenter.getZ() + outlinesClipboardCenterZ
- );
-
+ public static CuboidRegion getPlotAsRegion(Plot plot) throws IOException {
+ Clipboard clipboard = FaweAPI.load(plot.getOutlinesSchematic()).getClipboard();
+ if (clipboard != null) {
+ if (plot.getVersion() >= 3) {
+ return new CuboidRegion(
+ clipboard.getMinimumPoint().setY(plot.getWorld().getPlotHeight()),
+ clipboard.getMaximumPoint().setY(PlotWorld.MAX_WORLD_HEIGHT));
+ } else {
+ Vector plotCenter = plot.getCenter();
+
+ // Calculate min and max points of schematic
+ int regionCenterModX = clipboard.getRegion().getWidth() % 2 == 0 ? 1 : 0;
+ int regionCenterModZ = clipboard.getRegion().getLength() % 2 == 0 ? 1 : 0;
+ int outlinesClipboardCenterX = (int) Math.floor(clipboard.getRegion().getWidth() / 2d);
+ int outlinesClipboardCenterZ = (int) Math.floor(clipboard.getRegion().getLength() / 2d);
+
+ Vector schematicMinPoint = new Vector(
+ plotCenter.getX() - (outlinesClipboardCenterX - regionCenterModX),
+ PlotWorld.MIN_WORLD_HEIGHT,
+ plotCenter.getZ() - (outlinesClipboardCenterZ - regionCenterModZ)
+ );
+
+ Vector schematicMaxPoint = new Vector(
+ plotCenter.getX() + outlinesClipboardCenterX,
+ PlotWorld.MAX_WORLD_HEIGHT,
+ plotCenter.getZ() + outlinesClipboardCenterZ
+ );
+
+ return new CuboidRegion(schematicMinPoint, schematicMaxPoint);
+ }
+ }
+ return null;
+ }
- // Convert terra schematic coordinates into relative plot schematic coordinates
- schematicOrigin = Vector.toBlockPoint(
- Math.floor(terraOrigin.getX()) - Math.floor(outlinesClipboard.getMinimumPoint().getX()),
- Math.floor(terraOrigin.getY()) - Math.floor(outlinesClipboard.getMinimumPoint().getY()),
- Math.floor(terraOrigin.getZ()) - Math.floor(outlinesClipboard.getMinimumPoint().getZ())
- );
+ // TODO: MOVE CONVERSION TO SEPARATE METHODS
+ public static boolean savePlotAsSchematic(Plot plot) throws IOException, SQLException, WorldEditException {
+ Clipboard clipboard = FaweAPI.load(plot.getOutlinesSchematic()).getClipboard();
+ if (clipboard != null) {
+ CuboidRegion cuboidRegion = getPlotAsRegion(plot);
+ if (cuboidRegion != null) {
+ Vector plotCenter = plot.getCenter();
- // Add additional plot sizes to relative plot schematic coordinates
- plotOrigin = Vector.toBlockPoint(
- schematicOrigin.getX() + schematicMinPoint.getX(),
- schematicOrigin.getY() + schematicMinPoint.getY(),
- schematicOrigin.getZ() + schematicMinPoint.getZ()
- );
+ // Get plot outline
+ List plotOutlines = plot.getOutline();
+ // Load finished plot region as cuboid region
+ if (plot.getWorld().loadWorld()) {
+ com.sk89q.worldedit.world.World world = new BukkitWorld(plot.getWorld().getBukkitWorld());
+ Polygonal2DRegion region = new Polygonal2DRegion(world, plotOutlines, cuboidRegion.getMinimumPoint().getBlockY(), cuboidRegion.getMaximumPoint().getBlockY());
- // Load finished plot region as cuboid region
- plot.getWorld().loadWorld();
- CuboidRegion region = new CuboidRegion(new BukkitWorld(plot.getWorld().getBukkitWorld()), schematicMinPoint, schematicMaxPoint);
+ // Copy and write finished plot clipboard to schematic file
+ File finishedSchematicFile = plot.getFinishedSchematic();
+ if (!finishedSchematicFile.exists()) {
+ boolean createdDirs = finishedSchematicFile.getParentFile().mkdirs();
+ boolean createdFile = finishedSchematicFile.createNewFile();
+ if ((!finishedSchematicFile.getParentFile().exists() && !createdDirs) || (!finishedSchematicFile.exists() && !createdFile)) {
+ return false;
+ }
+ }
- // Copy finished plot region to clipboard
- Clipboard cb = new BlockArrayClipboard(region);
- cb.setOrigin(plotOrigin);
- EditSession editSession = PlotSystem.DependencyManager.getWorldEdit().getEditSessionFactory().getEditSession(region.getWorld(), -1);
- ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, region, cb, region.getMinimumPoint());
- Operations.complete(forwardExtentCopy);
+ Clipboard cb = new BlockArrayClipboard(region);
+ if (plot.getVersion() >= 3) {
+ cb.setOrigin(new Vector(Math.floor(plotCenter.getX()), cuboidRegion.getMinimumY(), Math.floor(plotCenter.getZ())));
+ } else {
+ Vector terraCenter = plot.getMinecraftCoordinates();
+ plotCenter = new Vector(
+ Math.floor(terraCenter.getX()) - Math.floor(clipboard.getMinimumPoint().getX()) + cuboidRegion.getMinimumPoint().getX(),
+ Math.floor(terraCenter.getY()) - Math.floor(clipboard.getMinimumPoint().getY()) + cuboidRegion.getMinimumPoint().getY(),
+ Math.floor(terraCenter.getZ()) - Math.floor(clipboard.getMinimumPoint().getZ()) + cuboidRegion.getMinimumPoint().getZ()
+ );
+ cb.setOrigin(plotCenter);
+ }
- // Write finished plot clipboard to schematic file
- File finishedSchematicFile = plot.getFinishedSchematic();
+ EditSession editSession = PlotSystem.DependencyManager.getWorldEdit().getEditSessionFactory().getEditSession(region.getWorld(), -1);
+ ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, region, cb, region.getMinimumPoint());
+ Operations.complete(forwardExtentCopy);
- if (!finishedSchematicFile.exists()) {
- boolean createdDirs = finishedSchematicFile.getParentFile().mkdirs();
- boolean createdFile = finishedSchematicFile.createNewFile();
- if ((!finishedSchematicFile.getParentFile().exists() && !createdDirs) || (!finishedSchematicFile.exists() && !createdFile)) {
- return false;
- }
- }
+ try(ClipboardWriter writer = ClipboardFormat.SCHEMATIC.getWriter(new FileOutputStream(finishedSchematicFile, false))) {
+ writer.write(cb, Objects.requireNonNull(region.getWorld()).getWorldData());
+ }
- try(ClipboardWriter writer = ClipboardFormat.SCHEMATIC.getWriter(new FileOutputStream(finishedSchematicFile, false))) {
- writer.write(cb, Objects.requireNonNull(region.getWorld()).getWorldData());
- }
+ // Upload to FTP server
+ if (plot.getCity().getCountry().getServer().getFTPConfiguration() != null) {
+ CompletableFuture.supplyAsync(() -> {
+ try {
+ return FTPManager.uploadSchematic(FTPManager.getFTPUrl(plot.getCity().getCountry().getServer(), plot.getCity().getID()), finishedSchematicFile);
+ } catch (SQLException | URISyntaxException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }
+ return null;
+ });
+ }
- // Upload to FTP server
- if (plot.getCity().getCountry().getServer().getFTPConfiguration() != null) {
- CompletableFuture.supplyAsync(() -> {
- try {
- return FTPManager.uploadSchematic(FTPManager.getFTPUrl(plot.getCity().getCountry().getServer(), plot.getCity().getID()), finishedSchematicFile);
- } catch (SQLException | URISyntaxException ex) {
- Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ // If plot was created in a void world, copy the result to the city world
+ // TODO: Copy finished schematic to city world
+ return true;
}
- return null;
- });
+ }
}
-
- return true;
+ return false;
}
public static CompletableFuture convertTerraToPlotXZ(Plot plot, double[] terraCoords) throws IOException {
@@ -253,15 +354,15 @@ public static CompletableFuture convertTerraToPlotXZ(Plot plot, double
int outlinesClipboardCenterZ = (int) Math.floor(outlinesClipboard.getRegion().getLength() / 2d);
Vector schematicMinPoint = Vector.toBlockPoint(
- PlotManager.getPlotCenter().getX() - outlinesClipboardCenterX + ((outlinesClipboard.getRegion().getWidth() % 2 == 0 ? 1 : 0)),
+ plot.getCenter().getX() - outlinesClipboardCenterX + ((outlinesClipboard.getRegion().getWidth() % 2 == 0 ? 1 : 0)),
0,
- PlotManager.getPlotCenter().getZ() - outlinesClipboardCenterZ + ((outlinesClipboard.getRegion().getLength() % 2 == 0 ? 1 : 0))
+ plot.getCenter().getZ() - outlinesClipboardCenterZ + ((outlinesClipboard.getRegion().getLength() % 2 == 0 ? 1 : 0))
);
Vector schematicMaxPoint = Vector.toBlockPoint(
- PlotManager.getPlotCenter().getX() + outlinesClipboardCenterX,
+ plot.getCenter().getX() + outlinesClipboardCenterX,
256,
- PlotManager.getPlotCenter().getZ() + outlinesClipboardCenterZ
+ plot.getCenter().getZ() + outlinesClipboardCenterZ
);
// Convert terra schematic coordinates into relative plot schematic coordinates
@@ -326,8 +427,53 @@ public static void syncPlotSchematicFiles() {
}
}
- public static Plot getPlotByWorld(World plotWorld) throws SQLException {
- return new Plot(Integer.parseInt(plotWorld.getName().substring(2)));
+ /** Returns the plot that the player is currently standing on or next to.
+ * If he is standing in a single plot world it returns the plot of this world.
+ * If he is standing in a multi plot world it returns the closest plot of all unfinished plots of this city
+ *
+ * @param builder
+ * @return the current plot of the player
+ * @throws SQLException
+ */
+ public static Plot getCurrentPlot(Builder builder, Status... statuses) throws SQLException {
+ if (builder.isOnline()) {
+ String worldName = builder.getPlayer().getWorld().getName();
+
+ if(PlotWorld.isOnePlotWorld(worldName))
+ return new Plot(Integer.parseInt(worldName.substring(2)));
+ else if (CityPlotWorld.isCityPlotWorld(worldName)) {
+ int cityID = Integer.parseInt(worldName.substring(2));
+ List plots = getPlots(cityID, statuses);
+
+ if(plots.size() == 0)
+ return getPlots(builder).get(0);
+ if(plots.size() == 1)
+ return plots.get(0);
+
+ // Find the plot in the city world that is closest to the player
+ Location playerLoc = builder.getPlayer().getLocation().clone();
+ Vector playerVector = new Vector(playerLoc.getX(), playerLoc.getY(), playerLoc.getZ());
+
+ double distance = 100000000;
+ Plot chosenPlot = plots.get(0);
+ for(Plot plot : plots)
+ if(plot.getCenter().distance(playerVector) < distance){
+ distance = plot.getCenter().distance(playerVector);
+ chosenPlot = plot;
+ }
+
+ return chosenPlot;
+ }
+ }
+ return null;
+ }
+
+ public static boolean isPlayerOnPlot(Plot plot, Player player) {
+ if (plot.getWorld().isWorldLoaded() && plot.getWorld().getBukkitWorld().getPlayers().contains(player)) {
+ Location playerLoc = player.getLocation();
+ return plot.getWorld().getProtectedRegion().contains(Vector.toBlockPoint(playerLoc.getX(), playerLoc.getY(), playerLoc.getZ()));
+ }
+ return false;
}
public static boolean plotExists(int ID) {
@@ -380,26 +526,52 @@ public static CompletableFuture getPlotDifficultyForBuilder(int
}
public static boolean isPlotWorld(World world) {
- return PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager().isMVWorld(world) && world.getName().startsWith("P-");
+ return PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager().isMVWorld(world) && (OnePlotWorld.isOnePlotWorld(world.getName()) || CityPlotWorld.isCityPlotWorld(world.getName()));
}
- public static Vector getPlotCenter() {
- return Vector.toBlockPoint(
- PLOT_SIZE / 2d,
- 5,
- PLOT_SIZE / 2d
- );
- }
- public static String getWorldGuardConfigPath(String worldName) {
- return Bukkit.getPluginManager().getPlugin("WorldGuard").getDataFolder() + "/worlds/" + worldName;
+ public static String getDefaultSchematicPath() {
+ return Paths.get(PlotSystem.getPlugin().getDataFolder().getAbsolutePath(), "schematics") + File.separator;
}
- public static String getMultiverseInventoriesConfigPath(String worldName) {
- return PlotSystem.DependencyManager.isMultiverseInventoriesEnabled() ? Bukkit.getPluginManager().getPlugin("Multiverse-Inventories").getDataFolder() + "/worlds/" + worldName : "";
- }
+ public static void showOutlines(){
+ try {
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ Builder builder = Builder.byUUID(player.getUniqueId());
- public static String getDefaultSchematicPath() {
- return Paths.get(PlotSystem.getPlugin().getDataFolder().getAbsolutePath(), "schematics") + File.separator;
+ List plots = getCachedInProgressPlots(builder);
+ BlockVector2D playerPos2D = new BlockVector2D(player.getLocation().getX(), player.getLocation().getZ());
+
+ if(plots.size() == 0)
+ continue;
+
+ for(Plot plot : plots){
+ if(!plot.getWorld().getWorldName().equals(player.getWorld().getName()))
+ continue;
+
+ if(!plot.getPlotOwner().getPlotTypeSetting().hasEnvironment())
+ continue;
+
+ List points = plot.getBlockOutline();
+
+ for(BlockVector2D point : points)
+ if(point.distanceSq(playerPos2D) < 50*50)
+ if(!ParticleAPIEnabled)
+ player.spawnParticle(Particle.FLAME, point.getX(), player.getLocation().getY() + 1, point.getZ(), 1, 0.0 ,0.0,0.0, 0);
+ else{
+ Location loc = new Location(player.getWorld(), point.getX(), player.getLocation().getY() + 1, point.getZ());
+ // create a particle packet
+ Object packet = particles.FLAME().packet(true, loc);
+
+ // send this packet to player
+ particles.sendPacket(player, packet);
+ }
+ }
+ }
+
+ } catch (SQLException | IOException ex) {
+ Bukkit.getLogger().log(Level.INFO, "A SQL error occurred!", ex);
+ }
}
+
}
\ No newline at end of file
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotPermissions.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotPermissions.java
index 4134e355..49dce17b 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotPermissions.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotPermissions.java
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
- * Copyright © 2021, Alps BTE
+ * Copyright © 2021-2022, Alps BTE
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,42 +30,49 @@
public class PlotPermissions {
- private final PlotWorld plotWorld;
+ private final PlotWorld world;
- public PlotPermissions(PlotWorld plotWorld) {
- this.plotWorld = plotWorld;
+ public PlotPermissions(PlotWorld world) {
+ this.world = world;
}
public PlotPermissions addBuilderPerms(UUID builder) {
- plotWorld.getProtectedRegion().getOwners().addPlayer(builder);
+ if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().addPlayer(builder);
+ world.getProtectedBuildRegion().getOwners().addPlayer(builder);
+ PlotManager.clearCache(builder);
return this;
}
public PlotPermissions removeBuilderPerms(UUID builder) {
- plotWorld.getProtectedRegion().getOwners().removePlayer(builder);
+ if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().removePlayer(builder);
+ world.getProtectedBuildRegion().getOwners().removePlayer(builder);
+ PlotManager.clearCache(builder);
return this;
}
public PlotPermissions addReviewerPerms() {
- plotWorld.getProtectedRegion().getOwners().addGroup("staff");
+ if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().addGroup("staff");
+ world.getProtectedBuildRegion().getOwners().addGroup("staff");
return this;
}
public PlotPermissions removeReviewerPerms() {
- plotWorld.getProtectedRegion().getOwners().removeGroup("staff");
+ if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().removeGroup("staff");
+ world.getProtectedBuildRegion().getOwners().removeGroup("staff");
return this;
}
public PlotPermissions clearAllPerms() {
- plotWorld.getProtectedRegion().getOwners().removeAll();
+ if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().removeAll();
+ world.getProtectedBuildRegion().getOwners().removeAll();
return this;
}
public boolean hasReviewerPerms() {
- return plotWorld.getProtectedRegion().getOwners().getGroups().contains("staff");
+ return world.getProtectedBuildRegion().getOwners().getGroups().contains("staff");
}
public void save() {
- plotWorld.unloadWorld(false);
+ world.unloadWorld(false);
}
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotType.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotType.java
new file mode 100644
index 00000000..8ce1a369
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/PlotType.java
@@ -0,0 +1,36 @@
+package com.alpsbte.plotsystem.core.system.plot;
+
+public enum PlotType {
+
+ FOCUS_MODE(0),
+ LOCAL_INSPIRATION_MODE(1),
+ CITY_INSPIRATION_MODE(2);
+
+ int id;
+
+ PlotType(int id){
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ // Returns true, if the plot type only contains environment around the plot.
+ public boolean hasEnvironment(){
+ return id == 1 || id == 2;
+ }
+
+ // Returns true, if the plot type only contains one plot per world.
+ public boolean hasOnePlotPerWorld(){
+ return id == 0 || id == 1;
+ }
+
+ public static PlotType byId(int id){
+ for(PlotType plotType : values())
+ if(plotType.getId() == id)
+ return plotType;
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java
index e9fe262f..b4a3beea 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java
@@ -26,6 +26,10 @@
import com.alpsbte.plotsystem.PlotSystem;
import com.alpsbte.plotsystem.commands.BaseCommand;
+import com.alpsbte.plotsystem.core.system.plot.PlotType;
+import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld;
+import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld;
+import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld;
import com.alpsbte.plotsystem.utils.io.config.ConfigPaths;
import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
@@ -35,18 +39,17 @@
import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.io.language.LangPaths;
import com.alpsbte.plotsystem.utils.io.language.LangUtil;
-import com.onarandombox.MultiverseCore.api.MVWorldManager;
-import com.onarandombox.MultiverseCore.api.MultiverseWorld;
-import com.sk89q.worldedit.BlockVector;
-import com.sk89q.worldedit.EditSession;
+import com.boydti.fawe.FaweAPI;
+import com.boydti.fawe.util.EditSessionBuilder;
+import com.sk89q.worldedit.*;
import com.sk89q.worldedit.Vector;
-import com.sk89q.worldedit.WorldEditException;
+import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.bukkit.BukkitWorld;
-import com.sk89q.worldedit.extent.clipboard.Clipboard;
-import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
-import com.sk89q.worldedit.function.operation.Operation;
-import com.sk89q.worldedit.function.operation.Operations;
-import com.sk89q.worldedit.session.ClipboardHolder;
+import com.sk89q.worldedit.extent.Extent;
+import com.sk89q.worldedit.function.mask.ExistingBlockMask;
+import com.sk89q.worldedit.regions.CylinderRegion;
+import com.sk89q.worldedit.regions.Polygonal2DRegion;
+import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.bukkit.RegionContainer;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
@@ -54,236 +57,225 @@
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.storage.StorageException;
-import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
-import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
+import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
+import java.util.*;
import java.util.logging.Level;
public abstract class AbstractPlotGenerator {
-
- private static final MVWorldManager worldManager = PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager();
- private WorldCreator worldCreator;
-
private final Plot plot;
private final Builder builder;
+ private final PlotWorld world;
+ private final double plotVersion;
+ private final PlotType plotType;
+
+ /**
+ * Generates a new plot in the plot world
+ * @param plot - plot which should be generated
+ * @param builder - builder of the plot
+ */
+ public AbstractPlotGenerator(@NotNull Plot plot, @NotNull Builder builder) throws SQLException {
+ this(plot, builder, builder.getPlotTypeSetting());
+ }
/**
+ * Generates a new plot in the given world
* @param plot - plot which should be generated
* @param builder - builder of the plot
+ * @param plotType - type of the plot
*/
- public AbstractPlotGenerator(@NotNull Plot plot, @NotNull Builder builder) {
+ public AbstractPlotGenerator(@NotNull Plot plot, @NotNull Builder builder, @NotNull PlotType plotType) throws SQLException {
+ this(plot, builder, plotType, plot.getVersion() <= 2 || plotType.hasOnePlotPerWorld() ? new OnePlotWorld(plot) : new CityPlotWorld(plot));
+ }
+
+ /**
+ * Generates a new plot in the given world
+ * @param plot - plot which should be generated
+ * @param builder - builder of the plot
+ * @param world - world of the plot
+ */
+ private AbstractPlotGenerator(@NotNull Plot plot, @NotNull Builder builder, @NotNull PlotType plotType, @NotNull PlotWorld world) {
this.plot = plot;
this.builder = builder;
+ this.world = world;
+ this.plotVersion = plot.getVersion();
+ this.plotType = plotType;
if (init()) {
Exception exception = null;
try {
- generateWorld();
- generateOutlines(plot.getOutlinesSchematic());
- createMultiverseWorld();
- configureWorld(worldManager.getMVWorld(plot.getWorld().getBukkitWorld()));
- createProtection();
+ if (plotType.hasOnePlotPerWorld() || !world.isWorldGenerated()) {
+ new PlotWorldGenerator(world.getWorldName());
+ } else if (!world.isWorldLoaded() && !world.loadWorld()) throw new Exception("Could not load world");
+ generateOutlines(plot.getOutlinesSchematic(), plotVersion >= 3 ? plot.getEnvironmentSchematic() : null);
+ createPlotProtection();
} catch (Exception ex) {
exception = ex;
}
try {
- this.onComplete(exception != null);
+ this.onComplete(exception != null, false);
} catch (SQLException ex) {
exception = ex;
}
if (exception != null) {
- if (worldManager.isMVWorld(plot.getWorld().getWorldName())) PlotHandler.abandonPlot(plot);
+ PlotHandler.abandonPlot(plot);
onException(exception);
}
}
}
+
/**
* Executed before plot generation
* @return true if initialization was successful
*/
protected abstract boolean init();
- /**
- * Generates plot world
- */
- protected void generateWorld() {
- if (getPlot().getWorld().isWorldGenerated()) plot.getWorld().deleteWorld();
-
- worldCreator = new WorldCreator(plot.getWorld().getWorldName());
- worldCreator.environment(org.bukkit.World.Environment.NORMAL);
- worldCreator.type(WorldType.FLAT);
- worldCreator.generatorSettings("2;0;1;");
- worldCreator.createWorld();
- }
-
- /**
- * Creates Multiverse world
- */
- protected void createMultiverseWorld() {
- // Check if world creator is configured and add new world to multiverse world manager
- if (worldCreator != null) {
- worldManager.addWorld(plot.getWorld().getWorldName(), worldCreator.environment(), null, worldCreator.type(), false,
- "VoidGen:{\"caves\":false,\"decoration\":false,\"mobs\":false,\"structures\":false}");
- } else {
- throw new RuntimeException("World Creator is not configured");
- }
- }
/**
* Generates plot schematic and outlines
- * @param plotSchematic - schematic file
+ * @param plotSchematic - plot schematic file
+ * @param environmentSchematic - environment schematic file
*/
- protected void generateOutlines(File plotSchematic) {
- try {
- if (plotSchematic != null) {
- Vector buildingOutlinesCoordinates = PlotManager.getPlotCenter();
-
- com.sk89q.worldedit.world.World weWorld = new BukkitWorld(plot.getWorld().getBukkitWorld());
- Clipboard clipboard = ClipboardFormat.SCHEMATIC.getReader(new FileInputStream(plotSchematic)).read(weWorld.getWorldData());
+ protected void generateOutlines(@NotNull File plotSchematic, @Nullable File environmentSchematic) throws IOException, WorldEditException, SQLException {
+ final class OnlyAirMask extends ExistingBlockMask {
+ public OnlyAirMask(Extent extent) {
+ super(extent);
+ }
- // Place the bottom part of the schematic 5 blocks above 0
- double heightDif = clipboard.getOrigin().getY() - clipboard.getMinimumPoint().getY();
- buildingOutlinesCoordinates = buildingOutlinesCoordinates.add(0, heightDif, 0);
+ @Override
+ public boolean test(Vector vector) {
+ return this.getExtent().getLazyBlock(vector).getType() == 0;
+ }
+ }
- ClipboardHolder clipboardHolder = new ClipboardHolder(clipboard, weWorld.getWorldData());
- EditSession editSession = PlotSystem.DependencyManager.getWorldEdit().getEditSessionFactory().getEditSession(weWorld, -1);
+ com.sk89q.worldedit.world.World weWorld = new BukkitWorld(world.getBukkitWorld());
+ EditSession editSession = new EditSessionBuilder(weWorld).fastmode(true).build();
- Operation operation = clipboardHolder.createPaste(editSession, weWorld.getWorldData()).to(buildingOutlinesCoordinates).ignoreAirBlocks(false).build();
- Operations.complete(operation);
- editSession.flushQueue();
+ if(plotVersion >= 3 && plotType.hasEnvironment() && environmentSchematic != null && environmentSchematic.exists()){
+ editSession.setMask(new OnlyAirMask(weWorld));
+ pasteSchematic(editSession, environmentSchematic, world, false);
+ }
- Location spawnLocation = plot.getWorld().getSpawnPoint();
- if (spawnLocation != null) plot.getWorld().getBukkitWorld().setSpawnLocation(spawnLocation);
- }
- } catch (IOException | WorldEditException ex) {
- Bukkit.getLogger().log(Level.SEVERE, "An error occurred while generating plot outlines!", ex);
- throw new RuntimeException("Plot outlines generation completed exceptionally");
+ pasteSchematic(editSession, plotSchematic, world, true);
+
+ // If the player is playing in his own world, then additionally generate the plot in the city world
+ if (PlotWorld.isOnePlotWorld(world.getWorldName()) && plotVersion >= 3 && plot.getStatus() != Status.completed) {
+ // Generate city plot world if it doesn't exist
+ new AbstractPlotGenerator(plot, builder, PlotType.CITY_INSPIRATION_MODE) {
+ @Override
+ protected boolean init() {
+ return true;
+ }
+
+ @Override
+ protected void createPlotProtection() {}
+
+ @Override
+ protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException {
+ super.onComplete(true, true);
+ }
+
+ @Override
+ protected void onException(Throwable ex) {
+ Bukkit.getLogger().log(Level.WARNING, "Could not generate plot in city world " + world.getWorldName() + "!", ex);
+ }
+ };
}
}
- /**
- * Configures plot world
- * @param mvWorld - plot world
- */
- protected void configureWorld(@NotNull MultiverseWorld mvWorld) {
- // Set Bukkit world game rules
- plot.getWorld().getBukkitWorld().setGameRuleValue("randomTickSpeed", "0");
- plot.getWorld().getBukkitWorld().setGameRuleValue("doDaylightCycle", "false");
- plot.getWorld().getBukkitWorld().setGameRuleValue("doFireTick", "false");
- plot.getWorld().getBukkitWorld().setGameRuleValue("doWeatherCycle", "false");
- plot.getWorld().getBukkitWorld().setGameRuleValue("keepInventory", "true");
- plot.getWorld().getBukkitWorld().setGameRuleValue("announceAdvancements", "false");
-
- // Set world time to midday
- plot.getWorld().getBukkitWorld().setTime(6000);
-
- // Configure multiverse world
- mvWorld.setAllowFlight(true);
- mvWorld.setGameMode(GameMode.CREATIVE);
- mvWorld.setEnableWeather(false);
- mvWorld.setDifficulty(Difficulty.PEACEFUL);
- mvWorld.setAllowAnimalSpawn(false);
- mvWorld.setAllowMonsterSpawn(false);
- mvWorld.setAutoLoad(false);
- mvWorld.setKeepSpawnInMemory(false);
- worldManager.saveWorldsConfig();
- }
/**
* Creates plot protection
*/
- protected void createProtection() {
- BlockVector min = BlockVector.toBlockPoint(0, 1, 0);
- BlockVector max = BlockVector.toBlockPoint(PlotManager.PLOT_SIZE, 256, PlotManager.PLOT_SIZE);
-
- RegionContainer container = PlotSystem.DependencyManager.getWorldGuard().getRegionContainer();
- RegionManager regionManager = container.get(plot.getWorld().getBukkitWorld());
-
- // Create protected region for world
- GlobalProtectedRegion globalRegion = new GlobalProtectedRegion("__global__");
- globalRegion.setFlag(DefaultFlag.ENTRY, StateFlag.State.DENY);
- globalRegion.setFlag(DefaultFlag.ENTRY.getRegionGroupFlag(), RegionGroup.ALL);
-
- // Create protected region for plot
- ProtectedRegion protectedPlotRegion = new ProtectedCuboidRegion(plot.getWorld().getWorldName(), min, max);
- protectedPlotRegion.setPriority(100);
-
- // Add and save regions
- try {
- if (regionManager != null) {
- regionManager.addRegion(globalRegion);
- regionManager.addRegion(protectedPlotRegion);
- regionManager.saveChanges();
- } else {
- throw new RuntimeException("Region Manager is null");
+ protected void createPlotProtection() throws StorageException, SQLException, IOException {
+ RegionContainer regionContainer = PlotSystem.DependencyManager.getWorldGuard().getRegionContainer();
+ RegionManager regionManager = regionContainer.get(world.getBukkitWorld());
+
+ if (regionManager != null) {
+ // Create build region for plot from the outline of the plot
+ ProtectedRegion protectedBuildRegion = new ProtectedPolygonalRegion(world.getRegionName(), plot.getOutline(), PlotWorld.MIN_WORLD_HEIGHT, PlotWorld.MAX_WORLD_HEIGHT);
+ protectedBuildRegion.setPriority(100);
+
+ // Create protected plot region for plot
+ World weWorld = new BukkitWorld(world.getBukkitWorld());
+ CylinderRegion cylinderRegion = new CylinderRegion(weWorld, plot.getCenter(), new Vector2D(PlotWorld.PLOT_SIZE, PlotWorld.PLOT_SIZE), PlotWorld.MIN_WORLD_HEIGHT, PlotWorld.MAX_WORLD_HEIGHT);
+ ProtectedRegion protectedRegion = new ProtectedPolygonalRegion(world.getRegionName() + "-1", cylinderRegion.polygonize(-1), PlotWorld.MIN_WORLD_HEIGHT, PlotWorld.MAX_WORLD_HEIGHT);
+ protectedRegion.setPriority(50);
+
+ // Add plot owner
+ DefaultDomain owner = protectedBuildRegion.getOwners();
+ owner.addPlayer(builder.getUUID());
+ protectedBuildRegion.setOwners(owner);
+ protectedRegion.setOwners(owner);
+
+
+ // Set permissions
+ protectedBuildRegion.setFlag(DefaultFlag.BUILD, StateFlag.State.ALLOW);
+ protectedBuildRegion.setFlag(DefaultFlag.BUILD.getRegionGroupFlag(), RegionGroup.OWNERS);
+ protectedRegion.setFlag(DefaultFlag.BUILD, StateFlag.State.DENY);
+ protectedRegion.setFlag(DefaultFlag.BUILD.getRegionGroupFlag(), RegionGroup.ALL);
+ protectedRegion.setFlag(DefaultFlag.ENTRY, StateFlag.State.ALLOW);
+ protectedRegion.setFlag(DefaultFlag.ENTRY.getRegionGroupFlag(), RegionGroup.ALL);
+
+ FileConfiguration config = PlotSystem.getPlugin().getConfigManager().getCommandsConfig();
+ List allowedCommandsNonBuilder = config.getStringList(ConfigPaths.ALLOWED_COMMANDS_NON_BUILDERS);
+ allowedCommandsNonBuilder.removeIf(c -> c.equals("/cmd1"));
+ for (BaseCommand baseCommand : PlotSystem.getPlugin().getCommandManager().getBaseCommands()) {
+ allowedCommandsNonBuilder.addAll(Arrays.asList(baseCommand.getNames()));
+ for (String command : baseCommand.getNames()) {
+ allowedCommandsNonBuilder.add("/" + command);
+ }
}
- } catch (StorageException ex) {
- Bukkit.getLogger().log(Level.SEVERE, "An error occurred while saving plot protection!", ex);
- throw new RuntimeException("Plot protection creation completed exceptionally");
- }
-
-
- // Add plot owner
- DefaultDomain owner = protectedPlotRegion.getOwners();
- owner.addPlayer(builder.getUUID());
- protectedPlotRegion.setOwners(owner);
-
-
- // Set permissions
- protectedPlotRegion.setFlag(DefaultFlag.PASSTHROUGH, StateFlag.State.ALLOW);
- protectedPlotRegion.setFlag(DefaultFlag.PASSTHROUGH.getRegionGroupFlag(), RegionGroup.OWNERS);
-
- protectedPlotRegion.setFlag(DefaultFlag.ENTRY, StateFlag.State.ALLOW);
- protectedPlotRegion.setFlag(DefaultFlag.ENTRY.getRegionGroupFlag(), RegionGroup.ALL);
-
- FileConfiguration config = PlotSystem.getPlugin().getConfigManager().getCommandsConfig();
-
- List allowedCommandsNonBuilder = config.getStringList(ConfigPaths.ALLOWED_COMMANDS_NON_BUILDERS);
- allowedCommandsNonBuilder.removeIf(c -> c.equals("/cmd1"));
- for (BaseCommand baseCommand : PlotSystem.getPlugin().getCommandManager().getBaseCommands()) {
- allowedCommandsNonBuilder.addAll(Arrays.asList(baseCommand.getNames()));
- for (String command : baseCommand.getNames()) {
- allowedCommandsNonBuilder.add("/" + command);
- }
- }
-
- List blockedCommandsBuilders = config.getStringList(ConfigPaths.BLOCKED_COMMANDS_BUILDERS);
- blockedCommandsBuilders.removeIf(c -> c.equals("/cmd1"));
-
- protectedPlotRegion.setFlag(DefaultFlag.BLOCKED_CMDS, new HashSet<>(blockedCommandsBuilders));
- protectedPlotRegion.setFlag(DefaultFlag.BLOCKED_CMDS.getRegionGroupFlag(), RegionGroup.OWNERS);
-
- protectedPlotRegion.setFlag(DefaultFlag.ALLOWED_CMDS, new HashSet<>(allowedCommandsNonBuilder));
- protectedPlotRegion.setFlag(DefaultFlag.ALLOWED_CMDS.getRegionGroupFlag(), RegionGroup.NON_OWNERS);
+ List blockedCommandsBuilders = config.getStringList(ConfigPaths.BLOCKED_COMMANDS_BUILDERS);
+ blockedCommandsBuilders.removeIf(c -> c.equals("/cmd1"));
+
+ protectedRegion.setFlag(DefaultFlag.BLOCKED_CMDS, new HashSet<>(blockedCommandsBuilders));
+ protectedRegion.setFlag(DefaultFlag.BLOCKED_CMDS.getRegionGroupFlag(), RegionGroup.OWNERS);
+ protectedRegion.setFlag(DefaultFlag.ALLOWED_CMDS, new HashSet<>(allowedCommandsNonBuilder));
+ protectedRegion.setFlag(DefaultFlag.ALLOWED_CMDS.getRegionGroupFlag(), RegionGroup.NON_OWNERS);
+
+
+ // Add regions and save changes
+ if (regionManager.hasRegion(world.getRegionName())) regionManager.removeRegion(world.getRegionName());
+ if (regionManager.hasRegion(world.getRegionName() + "-1")) regionManager.removeRegion(world.getRegionName() + "-1");
+ regionManager.addRegion(protectedBuildRegion);
+ regionManager.addRegion(protectedRegion);
+ regionManager.saveChanges();
+ } else Bukkit.getLogger().log(Level.WARNING, "Region Manager is null!");
}
+
/**
* Gets invoked when generation is completed
* @param failed - true if generation has failed
+ * @param unloadWorld - try to unload world after generation
* @throws SQLException - caused by a database exception
*/
- protected void onComplete(boolean failed) throws SQLException {
+ protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException {
if (!failed) {
builder.setPlot(plot.getID(), builder.getFreeSlot());
+ plot.setPlotType(plotType);
plot.setStatus(Status.unfinished);
plot.setPlotOwner(builder.getPlayer().getUniqueId().toString());
+ PlotManager.clearCache(builder.getUUID());
}
+
+ // Unload plot world if it is not needed anymore
+ if (unloadWorld) world.unloadWorld(false);
}
+
/**
* Gets invoked when an exception has occurred
* @param ex - caused exception
@@ -294,6 +286,7 @@ protected void onException(Throwable ex) {
builder.getPlayer().playSound(builder.getPlayer().getLocation(), Utils.ErrorSound,1,1);
}
+
/**
* @return - plot object
*/
@@ -301,10 +294,33 @@ public Plot getPlot() {
return plot;
}
+
/**
* @return - builder object
*/
public Builder getBuilder() {
return builder;
}
+
+
+
+ /**
+ * Pastes the schematic to the plot center in the given world
+ * @param schematicFile - plot/environment schematic file
+ * @param world - world to paste in
+ */
+ public static void pasteSchematic(@Nullable EditSession editSession, File schematicFile, PlotWorld world, boolean clearArea) throws IOException, MaxChangedBlocksException, SQLException {
+ if (world.loadWorld()) {
+ com.sk89q.worldedit.world.World weWorld = new BukkitWorld(world.getBukkitWorld());
+ if (editSession == null) editSession = new EditSessionBuilder(weWorld).fastmode(true).build();
+ if (clearArea) {
+ Polygonal2DRegion polyRegion = new Polygonal2DRegion(weWorld, world.getPlot().getOutline(), 0, PlotWorld.MAX_WORLD_HEIGHT);
+ editSession.replaceBlocks(polyRegion, null, new BaseBlock(0));
+ editSession.flushQueue();
+ }
+
+ FaweAPI.load(schematicFile).paste(editSession, world.getPlot().getCenter().setY(world.getPlotHeight()), false);
+ editSession.flushQueue();
+ }
+ }
}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java
index 894b5ece..a7ab8f42 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java
@@ -27,6 +27,7 @@
import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
+import com.alpsbte.plotsystem.core.system.plot.PlotType;
import com.alpsbte.plotsystem.utils.Utils;
import com.alpsbte.plotsystem.utils.enums.PlotDifficulty;
import com.alpsbte.plotsystem.utils.enums.Status;
@@ -50,10 +51,14 @@ public DefaultPlotGenerator(int cityID, PlotDifficulty plotDifficulty, Builder b
this(PlotManager.getPlots(cityID, plotDifficulty, Status.unclaimed).get(new Random().nextInt(PlotManager.getPlots(cityID, plotDifficulty, Status.unclaimed).size())), builder);
}
- public DefaultPlotGenerator(@NotNull Plot plot, @NotNull Builder builder) {
+ public DefaultPlotGenerator(@NotNull Plot plot, @NotNull Builder builder) throws SQLException {
super(plot, builder);
}
+ public DefaultPlotGenerator(@NotNull Plot plot, @NotNull Builder builder, PlotType plotType) throws SQLException {
+ super(plot, builder, plotType);
+ }
+
@Override
protected boolean init() {
try {
@@ -83,8 +88,8 @@ protected boolean init() {
}
@Override
- protected void onComplete(boolean failed) throws SQLException {
- super.onComplete(failed);
+ protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException {
+ super.onComplete(failed, false);
if (!failed) {
getPlot().getWorld().teleportPlayer(getBuilder().getPlayer());
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/PlotWorldGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/PlotWorldGenerator.java
new file mode 100644
index 00000000..7972a179
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/PlotWorldGenerator.java
@@ -0,0 +1,102 @@
+package com.alpsbte.plotsystem.core.system.plot.generator;
+
+import com.alpsbte.plotsystem.PlotSystem;
+import com.onarandombox.MultiverseCore.api.MVWorldManager;
+import com.onarandombox.MultiverseCore.api.MultiverseWorld;
+import com.sk89q.worldguard.bukkit.RegionContainer;
+import com.sk89q.worldguard.protection.flags.DefaultFlag;
+import com.sk89q.worldguard.protection.flags.RegionGroup;
+import com.sk89q.worldguard.protection.flags.StateFlag;
+import com.sk89q.worldguard.protection.managers.RegionManager;
+import com.sk89q.worldguard.protection.managers.storage.StorageException;
+import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
+import org.bukkit.*;
+
+import java.util.logging.Level;
+
+public class PlotWorldGenerator {
+ private final MVWorldManager worldManager = PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager();
+ private WorldCreator worldCreator;
+
+ private final String worldName;
+ private static final World.Environment environment = World.Environment.NORMAL;
+ private static final WorldType worldType = WorldType.FLAT;
+ private static final String generatorSettings = "2;0;1;";
+
+ public PlotWorldGenerator(String worldName) throws Exception {
+ this.worldName = worldName;
+
+ generateWorld();
+ createMultiverseWorld();
+ configureWorld();
+ createGlobalProtection();
+ }
+
+ protected void generateWorld() {
+ worldCreator = new WorldCreator(worldName);
+ worldCreator.environment(environment);
+ worldCreator.type(worldType);
+ worldCreator.generatorSettings(generatorSettings);
+ worldCreator.createWorld();
+ }
+
+ protected void createMultiverseWorld() throws Exception {
+ // Check if world creator is configured and add new world to multiverse world manager
+ if (worldCreator != null) {
+ if(!worldManager.isMVWorld(worldName))
+ worldManager.addWorld(worldName, environment, null, worldType, false,
+ "VoidGen:{\"caves\":false,\"decoration\":false,\"mobs\":false,\"structures\":false}", false);
+ } else {
+ throw new Exception("World Creator is not configured");
+ }
+ }
+
+ protected void configureWorld() {
+ World bukkitWorld = Bukkit.getWorld(worldName);
+ MultiverseWorld mvWorld = worldManager.getMVWorld(bukkitWorld);
+
+ // Set world time to midday
+ bukkitWorld.setTime(6000);
+
+ // Set Bukkit world game rules
+ bukkitWorld.setGameRuleValue("randomTickSpeed", "0");
+ bukkitWorld.setGameRuleValue("doDaylightCycle", "false");
+ bukkitWorld.setGameRuleValue("doFireTick", "false");
+ bukkitWorld.setGameRuleValue("doWeatherCycle", "false");
+ bukkitWorld.setGameRuleValue("keepInventory", "true");
+ bukkitWorld.setGameRuleValue("doMobSpawning", "false");
+ bukkitWorld.setGameRuleValue("announceAdvancements", "false");
+
+ // Configure multiverse world
+ mvWorld.setAllowFlight(true);
+ mvWorld.setGameMode(GameMode.CREATIVE);
+ mvWorld.setEnableWeather(false);
+ mvWorld.setDifficulty(Difficulty.PEACEFUL);
+ mvWorld.setAllowAnimalSpawn(false);
+ mvWorld.setAllowMonsterSpawn(false);
+ mvWorld.setAutoLoad(false);
+ mvWorld.setKeepSpawnInMemory(false);
+ worldManager.saveWorldsConfig();
+ }
+
+ protected void createGlobalProtection() throws StorageException {
+ RegionContainer regionContainer = PlotSystem.DependencyManager.getWorldGuard().getRegionContainer();
+ RegionManager regionManager = regionContainer.get(Bukkit.getWorld(worldName));
+
+ if (regionManager != null) {
+ // Create protected region for world
+ String regionName = "__global__";
+ GlobalProtectedRegion globalRegion = new GlobalProtectedRegion(regionName);
+ globalRegion.setFlag(DefaultFlag.ENTRY, StateFlag.State.DENY);
+ globalRegion.setFlag(DefaultFlag.ENTRY.getRegionGroupFlag(), RegionGroup.ALL);
+ globalRegion.setFlag(DefaultFlag.PASSTHROUGH, StateFlag.State.DENY);
+ globalRegion.setFlag(DefaultFlag.PASSTHROUGH.getRegionGroupFlag(), RegionGroup.ALL);
+ globalRegion.setFlag(DefaultFlag.TNT, StateFlag.State.DENY);
+ globalRegion.setFlag(DefaultFlag.TNT.getRegionGroupFlag(), RegionGroup.ALL);
+
+ if (regionManager.hasRegion(regionName)) regionManager.removeRegion(regionName);
+ regionManager.addRegion(globalRegion);
+ regionManager.saveChanges();
+ } else Bukkit.getLogger().log(Level.WARNING, "Region Manager is null!");
+ }
+}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/RawPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/RawPlotGenerator.java
deleted file mode 100644
index 270281f6..00000000
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/RawPlotGenerator.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright © 2021, Alps BTE
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.alpsbte.plotsystem.core.system.plot.generator;
-
-import com.alpsbte.plotsystem.PlotSystem;
-import com.alpsbte.plotsystem.core.system.Builder;
-import com.alpsbte.plotsystem.core.system.plot.Plot;
-import com.alpsbte.plotsystem.utils.Utils;
-import com.onarandombox.MultiverseCore.api.MultiverseWorld;
-import com.sk89q.worldguard.bukkit.RegionContainer;
-import com.sk89q.worldguard.protection.managers.RegionManager;
-import org.bukkit.Bukkit;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.File;
-import java.util.logging.Level;
-
-public class RawPlotGenerator extends AbstractPlotGenerator {
-
- public RawPlotGenerator(Plot plot, Builder builder) {
- super(plot, builder);
- }
-
- @Override
- protected boolean init() {
- return true;
- }
-
- @Override
- protected void generateWorld() {}
-
- @Override
- protected void configureWorld(@NotNull MultiverseWorld mvWorld) {}
-
- @Override
- protected void generateOutlines(@NotNull File plotSchematic) {}
-
- @Override
- protected void createProtection() {
- RegionContainer container = PlotSystem.DependencyManager.getWorldGuard().getRegionContainer();
- RegionManager regionManager = container.get(getPlot().getWorld().getBukkitWorld());
-
- if (regionManager != null) {
- for (String regionID : regionManager.getRegions().keySet()) {
- regionManager.removeRegion(regionID);
- }
- } else {
- throw new RuntimeException("Region Manager is null");
- }
-
- super.createProtection();
- }
-
- @Override
- protected void onComplete(boolean failed) {}
-
- @Override
- protected void onException(Throwable ex) {
- Bukkit.getLogger().log(Level.SEVERE, "An error occurred while cleaning plot!");
- getBuilder().getPlayer().sendMessage(Utils.getErrorMessageFormat("An error occurred while cleaning plot! Please try again!"));
- getBuilder().getPlayer().playSound(getBuilder().getPlayer().getLocation(), Utils.ErrorSound,1,1);
- }
-}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/CityPlotWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/CityPlotWorld.java
new file mode 100644
index 00000000..519e1259
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/CityPlotWorld.java
@@ -0,0 +1,106 @@
+package com.alpsbte.plotsystem.core.system.plot.world;
+
+import com.alpsbte.plotsystem.core.system.plot.Plot;
+import com.alpsbte.plotsystem.core.system.plot.PlotHandler;
+import com.alpsbte.plotsystem.core.system.plot.PlotManager;
+import com.alpsbte.plotsystem.utils.Utils;
+import com.alpsbte.plotsystem.utils.io.language.LangPaths;
+import com.alpsbte.plotsystem.utils.io.language.LangUtil;
+import com.boydti.fawe.FaweAPI;
+import com.google.common.annotations.Beta;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+public class CityPlotWorld extends PlotWorld {
+ public CityPlotWorld(@NotNull Plot plot) throws SQLException {
+ super("C-" + plot.getCity().getID(), plot);
+ }
+
+ @Override
+ public boolean teleportPlayer(@NotNull Player player) {
+ if (super.teleportPlayer(player)) {
+ try {
+ player.playSound(player.getLocation(), Utils.TeleportSound, 1, 1);
+ player.setAllowFlight(true);
+ player.setFlying(true);
+
+ if (getPlot() != null) {
+ player.sendMessage(Utils.getInfoMessageFormat(LangUtil.get(player, LangPaths.Message.Info.TELEPORTING_PLOT, String.valueOf(getPlot().getID()))));
+
+ Utils.updatePlayerInventorySlots(player);
+ PlotHandler.sendLinkMessages(getPlot(), player);
+
+ if(getPlot().getPlotOwner().getUUID().equals(player.getUniqueId())) {
+ getPlot().setLastActivity(false);
+ }
+ }
+
+ return true;
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getRegionName() {
+ return super.getRegionName() + "-" + getPlot().getID();
+ }
+
+
+ @Beta
+ @Override
+ public int getPlotHeight() throws IOException {
+ return getPlot().getVersion() >= 3 ? MIN_WORLD_HEIGHT + getWorldHeight() : getPlotHeightCentered();
+ }
+
+ @Beta
+ @Override
+ public int getPlotHeightCentered() throws IOException {
+ return MIN_WORLD_HEIGHT + getWorldHeight() + super.getPlotHeightCentered();
+ }
+
+ /**
+ * Calculate additional height for the plot
+ * @return additional height
+ * @throws IOException if the outline schematic fails to load
+ */
+ @Beta
+ public int getWorldHeight() throws IOException {
+ Clipboard clipboard = FaweAPI.load(getPlot().getOutlinesSchematic()).getClipboard();
+ int plotHeight = clipboard != null ? clipboard.getMinimumPoint().getBlockY() : MIN_WORLD_HEIGHT;
+
+ // Plots created below min world height are not supported
+ if (plotHeight < MIN_WORLD_HEIGHT) throw new IOException("Plot height is not supported");
+
+ // Move Y height to a usable value below 256 blocks
+ while (plotHeight >= 150) {
+ plotHeight -= 150;
+ }
+ return plotHeight;
+ }
+
+ /**
+ * Gets all players located on the plot in the city plot world
+ * @return a list of players located on the plot
+ */
+ public List getPlayersOnPlot() {
+ List players = new ArrayList<>();
+ if (getPlot() != null && getPlot().getWorld().isWorldLoaded() && !getPlot().getWorld().getBukkitWorld().getPlayers().isEmpty()) {
+ for (Player player : getPlot().getWorld().getBukkitWorld().getPlayers()) {
+ if (PlotManager.isPlayerOnPlot(getPlot(), player)) players.add(player);
+ }
+ return players;
+ }
+ return players;
+ }
+}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IPlotWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IWorld.java
similarity index 71%
rename from src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IPlotWorld.java
rename to src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IWorld.java
index 6b1dcc9a..828f973c 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IPlotWorld.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IWorld.java
@@ -24,29 +24,30 @@
package com.alpsbte.plotsystem.core.system.plot.world;
-import com.alpsbte.plotsystem.core.system.Builder;
-import com.alpsbte.plotsystem.core.system.plot.generator.AbstractPlotGenerator;
+import com.alpsbte.plotsystem.core.system.plot.generator.PlotWorldGenerator;
+import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
-public interface IPlotWorld {
+import java.io.IOException;
+
+public interface IWorld {
/**
* Generates the plot world with the required configurations and schematic
- * @param plotOwner plow owner of the plot
* @param generator generator type as class
* @return true if world was generated successfully
*/
- boolean generateWorld(@NotNull Builder plotOwner, @NotNull Class generator);
+ boolean generateWorld(@NotNull Class generator);
/**
* Regenerates the current plot with an optional new generator type
* @param generator generator type as class
* @return true if world was regenerated successfully
*/
- boolean regenWorld(@NotNull Class generator);
+ boolean regenWorld(@NotNull Class generator);
/**
* Deletes the world file and entry in the config file
@@ -62,7 +63,7 @@ public interface IPlotWorld {
/**
* Unloads the plot world from memory. Plot cannot be used anymore. Plot has to be generated.
- * @param movePlayers - if true, players will get teleported to the spawn location. Otherwise, plot will not get unloaded.
+ * @param movePlayers if true, players will get teleported to the spawn location. Otherwise, plot will not get unloaded.
* @return true if world was loaded successfully
*/
boolean unloadWorld(boolean movePlayers);
@@ -72,13 +73,28 @@ public interface IPlotWorld {
* @param player bukkit player
* @return true if player was teleported successfully
*/
- boolean teleportPlayer(Player player);
+ boolean teleportPlayer(@NotNull Player player);
/**
* Returns the spawn point of the plot
* @return center coordinates of the plot
+ * @param plotVector plot vector
+ */
+ Location getSpawnPoint(Vector plotVector);
+
+ /**
+ * Calculates the origin Y value in the plot world used for schematic pasting
+ * @return the origin Y value
+ * @throws IOException if the outline schematic fails to load
+ */
+ int getPlotHeight() throws IOException;
+
+ /**
+ * Calculates the centered Y value in the plot world
+ * @return the centered Y value
+ * @throws IOException if the outline schematic fails to load
*/
- Location getSpawnPoint();
+ int getPlotHeightCentered() throws IOException;
/**
* @return Bukkit plot world
@@ -90,12 +106,23 @@ public interface IPlotWorld {
*/
String getWorldName();
+ /**
+ * @return region world name of the plot
+ */
+ String getRegionName();
+
/**
* Loads the protected plot world region from WorldGuard config
* @return protected WorldGuard region
*/
ProtectedRegion getProtectedRegion();
+ /**
+ * Loads the protected plot world build region from WorldGuard config
+ * @return protected WorldGuard build region
+ */
+ ProtectedRegion getProtectedBuildRegion();
+
/**
* Checks if the plot world is loaded to memory
* @return true if world is loaded
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/OnePlotWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/OnePlotWorld.java
new file mode 100644
index 00000000..4ddf7433
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/OnePlotWorld.java
@@ -0,0 +1,156 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright © 2021-2022, Alps BTE
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.alpsbte.plotsystem.core.system.plot.world;
+
+import com.alpsbte.plotsystem.core.system.Builder;
+import com.alpsbte.plotsystem.core.system.plot.Plot;
+import com.alpsbte.plotsystem.core.system.plot.PlotHandler;
+import com.alpsbte.plotsystem.core.system.plot.generator.PlotWorldGenerator;
+import com.alpsbte.plotsystem.core.system.plot.generator.DefaultPlotGenerator;
+import com.alpsbte.plotsystem.utils.Utils;
+import com.alpsbte.plotsystem.utils.enums.Status;
+import com.alpsbte.plotsystem.utils.io.language.LangPaths;
+import com.alpsbte.plotsystem.utils.io.language.LangUtil;
+import com.sk89q.worldedit.WorldEditException;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.logging.Level;
+
+public class OnePlotWorld extends PlotWorld {
+ private final Builder plotOwner;
+
+ public OnePlotWorld(@NotNull Plot plot) throws SQLException {
+ super("P-" + plot.getID(), plot);
+ this.plotOwner = plot.getPlotOwner();
+ }
+
+ @Override
+ public boolean generateWorld(@NotNull Class generator) {
+ if (!isWorldGenerated()) {
+ try {
+ if (generator.isAssignableFrom(DefaultPlotGenerator.class)) {
+ new DefaultPlotGenerator(getPlot(), plotOwner);
+ } else return false;
+ return true;
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean loadWorld() {
+ // Generate plot if it doesn't exist
+ if (getPlot() != null && !isWorldGenerated() && getPlot().getFinishedSchematic().exists()) {
+ try {
+ new DefaultPlotGenerator(getPlot(), plotOwner, getPlot().getPlotType()) {
+ @Override
+ protected void generateOutlines(@NotNull File plotSchematic, @Nullable File environmentSchematic) throws SQLException, IOException, WorldEditException {
+ super.generateOutlines(getPlot().getFinishedSchematic(), environmentSchematic);
+ }
+
+ @Override
+ protected boolean init() {
+ return true;
+ }
+
+ @Override
+ protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException {
+ getPlot().getPermissions().clearAllPerms();
+ super.onComplete(true, false);
+ }
+ };
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }
+
+ if (!isWorldGenerated() || !isWorldLoaded()) {
+ Bukkit.getLogger().log(Level.WARNING, "Could not regenerate world " + getWorldName() + " for plot " + getPlot().getID() + "!");
+ return false;
+ }
+ return true;
+ } else return super.loadWorld();
+ }
+
+ @Override
+ public boolean unloadWorld(boolean movePlayers) {
+ if (super.unloadWorld(movePlayers)) {
+ try {
+ if (getPlot() != null && getPlot().getStatus() == Status.completed) {
+ deleteWorld();
+ return true;
+ }
+ return !isWorldLoaded();
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "An SQL error occurred!", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean teleportPlayer(@NotNull Player player) {
+ if (super.teleportPlayer(player)) {
+ try {
+ player.playSound(player.getLocation(), Utils.TeleportSound, 1, 1);
+ player.setAllowFlight(true);
+ player.setFlying(true);
+
+ if (getPlot() != null) {
+ player.sendMessage(Utils.getInfoMessageFormat(LangUtil.get(player, LangPaths.Message.Info.TELEPORTING_PLOT, String.valueOf(getPlot().getID()))));
+
+ Utils.updatePlayerInventorySlots(player);
+ PlotHandler.sendLinkMessages(getPlot(), player);
+
+ if(getPlot().getPlotOwner().getUUID().equals(player.getUniqueId())) {
+ getPlot().setLastActivity(false);
+ }
+ }
+
+ return true;
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "An SQL error occurred!", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getPlotHeight() throws IOException {
+ return getPlot().getVersion() >= 3 ? MIN_WORLD_HEIGHT : getPlotHeightCentered();
+ }
+
+ @Override
+ public int getPlotHeightCentered() throws IOException {
+ return MIN_WORLD_HEIGHT + super.getPlotHeightCentered();
+ }
+}
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java
index a0c54372..51d1e5ec 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java
@@ -1,44 +1,13 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright © 2021-2022, Alps BTE
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
package com.alpsbte.plotsystem.core.system.plot.world;
import com.alpsbte.plotsystem.PlotSystem;
-import com.alpsbte.plotsystem.core.menus.CompanionMenu;
-import com.alpsbte.plotsystem.core.menus.ReviewMenu;
-import com.alpsbte.plotsystem.core.system.Builder;
import com.alpsbte.plotsystem.core.system.plot.Plot;
-import com.alpsbte.plotsystem.core.system.plot.PlotHandler;
-import com.alpsbte.plotsystem.core.system.plot.PlotManager;
-import com.alpsbte.plotsystem.core.system.plot.generator.AbstractPlotGenerator;
-import com.alpsbte.plotsystem.core.system.plot.generator.DefaultPlotGenerator;
-import com.alpsbte.plotsystem.core.system.plot.generator.RawPlotGenerator;
+import com.alpsbte.plotsystem.core.system.plot.generator.PlotWorldGenerator;
import com.alpsbte.plotsystem.utils.Utils;
-import com.alpsbte.plotsystem.utils.enums.Status;
-import com.alpsbte.plotsystem.utils.io.language.LangPaths;
-import com.alpsbte.plotsystem.utils.io.language.LangUtil;
+import com.boydti.fawe.FaweAPI;
import com.onarandombox.MultiverseCore.MultiverseCore;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldguard.bukkit.RegionContainer;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
@@ -48,6 +17,7 @@
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
@@ -55,38 +25,28 @@
import java.util.Locale;
import java.util.logging.Level;
-public class PlotWorld implements IPlotWorld {
+public class PlotWorld implements IWorld {
+ public static final int PLOT_SIZE = 150;
+ public static final int MAX_WORLD_HEIGHT = 256;
+ public static final int MIN_WORLD_HEIGHT = 5;
+ private final MultiverseCore mvCore = PlotSystem.DependencyManager.getMultiverseCore();
+ private final String worldName;
private final Plot plot;
- private final MultiverseCore mvCore;
- public PlotWorld(Plot plot) {
+ public PlotWorld(@NotNull String worldName, @Nullable Plot plot) {
+ this.worldName = worldName;
this.plot = plot;
- this.mvCore = PlotSystem.DependencyManager.getMultiverseCore();
}
@Override
- public boolean generateWorld(@NotNull Builder plotOwner, @NotNull Class generator) {
- if (!isWorldGenerated()) {
- if (generator.isAssignableFrom(DefaultPlotGenerator.class)) {
- new DefaultPlotGenerator(plot, plotOwner);
- } else if (generator.isAssignableFrom(RawPlotGenerator.class)) {
- new RawPlotGenerator(plot, plotOwner);
- } else return false;
- return true;
- }
- return false;
+ public boolean generateWorld(@NotNull Class generator) {
+ throw new UnsupportedOperationException("No world generator set for world " + getWorldName());
}
@Override
- public boolean regenWorld(@NotNull Class generator) {
- try {
- if (deleteWorld() && generateWorld(plot.getPlotOwner(), generator))
- return true;
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
- }
- return false;
+ public boolean regenWorld(@NotNull Class generator) {
+ return deleteWorld() && generateWorld(generator);
}
@Override
@@ -94,152 +54,164 @@ public boolean deleteWorld() {
if (isWorldGenerated() && loadWorld()) {
if (mvCore.getMVWorldManager().deleteWorld(getWorldName(), true, true) && mvCore.saveWorldConfig()) {
try {
- File multiverseInventoriesConfig = new File(PlotManager.getMultiverseInventoriesConfigPath(plot.getWorld().getWorldName()));
- File worldGuardConfig = new File(PlotManager.getWorldGuardConfigPath(plot.getWorld().getWorldName()));
+ File multiverseInventoriesConfig = new File(PlotSystem.DependencyManager.getMultiverseInventoriesConfigPath(getWorldName()));
+ File worldGuardConfig = new File(PlotSystem.DependencyManager.getWorldGuardConfigPath(getWorldName()));
if (multiverseInventoriesConfig.exists()) FileUtils.deleteDirectory(multiverseInventoriesConfig);
if (worldGuardConfig.exists()) FileUtils.deleteDirectory(worldGuardConfig);
} catch (IOException ex) {
- Bukkit.getLogger().log(Level.WARNING, "Could not delete world configs of plot #" + plot.getID() + "!");
+ Bukkit.getLogger().log(Level.WARNING, "Could not delete config files for world " + getWorldName() + "!");
return false;
}
return true;
- } else Bukkit.getLogger().log(Level.WARNING, "Could not delete world of plot #" + plot.getID() + "!");
+ } else Bukkit.getLogger().log(Level.WARNING, "Could not delete world " + getWorldName() + "!");
}
return false;
}
@Override
public boolean loadWorld() {
- try {
- // Generate plot if it doesn't exist
- if (!isWorldGenerated() && plot.getFinishedSchematic().exists()) {
- new DefaultPlotGenerator(plot, plot.getPlotOwner()) {
- @Override
- protected void generateOutlines(File plotSchematic) {
- super.generateOutlines(plot.getFinishedSchematic());
- }
-
- @Override
- protected boolean init() {
- return true;
- }
-
- @Override
- protected void onComplete(boolean failed) throws SQLException {
- plot.getPermissions().clearAllPerms();
- super.onComplete(true); // This code sucks
- }
- };
- if (!isWorldGenerated() || !isWorldLoaded()) {
- Bukkit.getLogger().log(Level.WARNING, "Could not regenerate world of plot #" + plot.getID() + "!");
- return false;
- }
+ if(isWorldGenerated()) {
+ if (isWorldLoaded()) {
return true;
- } else if (isWorldGenerated())
- return mvCore.getMVWorldManager().loadWorld(getWorldName()) || isWorldLoaded();
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
- }
+ } else return mvCore.getMVWorldManager().loadWorld(getWorldName()) || isWorldLoaded();
+ } else Bukkit.getLogger().log(Level.WARNING, "Could not load world " + worldName + " because it is not generated!");
return false;
}
@Override
public boolean unloadWorld(boolean movePlayers) {
- if(isWorldLoaded()) {
- if (movePlayers && !getBukkitWorld().getPlayers().isEmpty()) {
- for (Player player : getBukkitWorld().getPlayers()) {
- player.teleport(Utils.getSpawnLocation());
+ if (isWorldGenerated()) {
+ if(isWorldLoaded()) {
+ if (movePlayers && !getBukkitWorld().getPlayers().isEmpty()) {
+ for (Player player : getBukkitWorld().getPlayers()) {
+ player.teleport(Utils.getSpawnLocation());
+ }
}
- }
- try {
- if (plot.getStatus() == Status.completed && getBukkitWorld().getPlayers().isEmpty()) {
- deleteWorld();
- return true;
- }
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
+ Bukkit.unloadWorld(getBukkitWorld(), true);
+ return !isWorldLoaded();
}
-
- Bukkit.getScheduler().scheduleSyncDelayedTask(PlotSystem.getPlugin(), (() ->
- Bukkit.unloadWorld(getBukkitWorld(), true)), 60L);
- return !isWorldLoaded();
- }
- return true;
+ return true;
+ } else Bukkit.getLogger().log(Level.WARNING, "Could not unload world " + worldName + " because it is not generated!");
+ return false;
}
@Override
- public boolean teleportPlayer(Player player) {
- Location spawnLocation;
- if (loadWorld() && (spawnLocation = getSpawnPoint()) != null) {
- try {
- player.sendMessage(Utils.getInfoMessageFormat(LangUtil.get(player, LangPaths.Message.Info.TELEPORTING_PLOT, String.valueOf(plot.getID()))));
-
- player.teleport(spawnLocation);
- player.playSound(player.getLocation(), Utils.TeleportSound, 1, 1);
- player.setAllowFlight(true);
- player.setFlying(true);
-
- Utils.updatePlayerInventorySlots(player);
-
- PlotHandler.sendLinkMessages(plot, player);
+ public boolean teleportPlayer(@NotNull Player player) {
+ if (loadWorld()) {
+ Location spawnLocation = plot != null ? getSpawnPoint(plot.getCenter()) : getBukkitWorld().getSpawnLocation();
+ // Set spawn point 1 block above the highest block at the spawn location
+ spawnLocation.setY(getBukkitWorld().getHighestBlockYAt((int) spawnLocation.getX(), (int) spawnLocation.getZ()) + 1);
- if(plot.getPlotOwner().getUUID().equals(player.getUniqueId())) {
- plot.setLastActivity(false);
- }
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
- }
+ player.teleport(spawnLocation);
return true;
- } else player.sendMessage(Utils.getErrorMessageFormat("Could not load plot world. Please try again!"));
+ } else Bukkit.getLogger().log(Level.WARNING, "Could not teleport player " + player.getName() + " to world " + worldName + "!");
return false;
}
@Override
- public Location getSpawnPoint() {
- if (getBukkitWorld() != null) {
- Location spawnLocation = new Location(plot.getWorld().getBukkitWorld(),
- PlotManager.getPlotCenter().getX() + 0.5,
- 30,
- PlotManager.getPlotCenter().getZ() + 0.5,
- -90,
- 90);
- // Set spawn point 1 block above the highest center point
- spawnLocation.setY(plot.getWorld().getBukkitWorld().getHighestBlockYAt((int) spawnLocation.getX(), (int) spawnLocation.getZ()) + 1);
- return spawnLocation;
+ public Location getSpawnPoint(Vector plotVector) {
+ if (isWorldGenerated() && loadWorld()) {
+ return plotVector == null ? getBukkitWorld().getSpawnLocation() :
+ new Location(getBukkitWorld(), plotVector.getX(), plotVector.getY(), plotVector.getZ());
}
return null;
}
+ @Override
+ public int getPlotHeight() throws IOException {
+ throw new UnsupportedOperationException("No plot height set for " + getWorldName());
+ }
+
+ @Override
+ public int getPlotHeightCentered() throws IOException {
+ if (plot != null) {
+ Clipboard clipboard = FaweAPI.load(plot.getOutlinesSchematic()).getClipboard();
+ if (clipboard != null) {
+ return clipboard.getRegion().getCenter().getBlockY() - clipboard.getMinimumPoint().getBlockY();
+ }
+ }
+ return 0;
+ }
+
@Override
public World getBukkitWorld() {
- return Bukkit.getWorld(getWorldName());
+ return Bukkit.getWorld(worldName);
}
@Override
public String getWorldName() {
- return "P-" + plot.getID();
+ return worldName;
+ }
+
+ @Override
+ public String getRegionName() {
+ return worldName.toLowerCase(Locale.ROOT);
}
@Override
public ProtectedRegion getProtectedRegion() {
+ return getRegion(getRegionName() + "-1");
+ }
+
+ @Override
+ public ProtectedRegion getProtectedBuildRegion() {
+ return getRegion(getRegionName());
+ }
+
+ @Override
+ public boolean isWorldLoaded() {
+ return getBukkitWorld() != null;
+ }
+
+ @Override
+ public boolean isWorldGenerated() {
+ return mvCore.getMVWorldManager().getMVWorld(worldName) != null || mvCore.getMVWorldManager().getUnloadedWorlds().contains(worldName);
+ }
+
+ private ProtectedRegion getRegion(String regionName) {
RegionContainer container = PlotSystem.DependencyManager.getWorldGuard().getRegionContainer();
if (loadWorld()) {
RegionManager regionManager = container.get(getBukkitWorld());
if (regionManager != null) {
- return regionManager.getRegion(getWorldName().toLowerCase(Locale.ROOT));
+ return regionManager.getRegion(regionName);
} else Bukkit.getLogger().log(Level.WARNING, "Region manager is null");
}
return null;
}
- @Override
- public boolean isWorldLoaded() {
- return getBukkitWorld() != null;
+ public Plot getPlot() {
+ return plot;
}
- @Override
- public boolean isWorldGenerated() {
- return mvCore.getMVWorldManager().getMVWorld(getWorldName()) != null || mvCore.getMVWorldManager().getUnloadedWorlds().contains(getWorldName());
+
+ /**
+ * @param worldName - the name of the world
+ * @return - true if the world is a plot world
+ */
+ public static boolean isOnePlotWorld(String worldName) {
+ return worldName.toLowerCase(Locale.ROOT).startsWith("p-");
+ }
+
+ /**
+ * @param worldName - the name of the world
+ * @return - true if the world is a city plot world
+ */
+ public static boolean isCityPlotWorld(String worldName) {
+ return worldName.toLowerCase(Locale.ROOT).startsWith("c-");
+ }
+
+ /**
+ * Returns OnePlotWorld or PlotWorld (CityPlotWorld) class depending on the world name.
+ * It won't return the CityPlotWorld class because there is no use case without a plot.
+ * @param worldName - name of the world
+ * @return - plot world
+ * @param - OnePlotWorld or PlotWorld
+ */
+ @SuppressWarnings("unchecked")
+ public static T getPlotWorldByName(String worldName) throws SQLException {
+ if (isOnePlotWorld(worldName)) {
+ return new Plot(Integer.parseInt(worldName.substring(2))).getWorld();
+ } else return (T) new PlotWorld(worldName, null);
}
}
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/Invitation.java b/src/main/java/com/alpsbte/plotsystem/utils/Invitation.java
index ad2a01d9..b3c1f470 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/Invitation.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/Invitation.java
@@ -67,9 +67,9 @@ public Invitation(Player invitee, Plot plot) throws SQLException {
}
public void AcceptInvite() throws SQLException {
- Builder builder = new Builder(invitee.getUniqueId());
+ Builder builder = Builder.byUUID(invitee.getUniqueId());
if (builder.getFreeSlot() != null) {
- plot.addPlotMember(new Builder(invitee.getUniqueId()));
+ plot.addPlotMember(Builder.byUUID(invitee.getUniqueId()));
// Messages Receiver
invitee.sendMessage(Utils.getInfoMessageFormat("Invitation to " + plot.getPlotOwner().getName() + "'s plot has been accepted!"));
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/Utils.java b/src/main/java/com/alpsbte/plotsystem/utils/Utils.java
index cc808721..5fe6286c 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/Utils.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/Utils.java
@@ -30,6 +30,7 @@
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.alpsbte.plotsystem.utils.io.config.ConfigPaths;
import com.alpsbte.plotsystem.utils.items.builder.ItemBuilder;
+import com.sk89q.worldedit.BlockVector2D;
import org.bukkit.*;
import com.alpsbte.plotsystem.utils.enums.PlotDifficulty;
import me.arcaniax.hdb.api.HeadDatabaseAPI;
@@ -37,7 +38,10 @@
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
+import org.bukkit.util.Vector;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.UUID;
import java.util.logging.Level;
@@ -162,6 +166,114 @@ public static String getFormattedDifficulty(PlotDifficulty plotDifficulty) {
}
}
+ public static HashSet getLineBetweenPoints(Vector point1, Vector point2, int pointsInLine){
+ double p1X = point1.getX();
+ double p1Y = point1.getY();
+ double p1Z = point1.getZ();
+ double p2X = point2.getX();
+ double p2Y = point2.getY();
+ double p2Z = point2.getZ();
+
+ double lineAveX = (p2X-p1X)/pointsInLine;
+ double lineAveY = (p2Y-p1Y)/pointsInLine;
+ double lineAveZ = (p2Z-p1Z)/pointsInLine;
+
+ HashSet line = new HashSet<>();
+ for(int i = 0; i <= pointsInLine; i++){
+ Vector vector = new Vector(p1X + lineAveX * i, p1Y + lineAveY * i, p1Z + lineAveZ * i);
+ line.add(vector);
+ }
+ return line;
+ }
+
+ public static HashSet getLineBetweenPoints(BlockVector2D point1, BlockVector2D point2, int pointsInLine){
+ double p1X = point1.getX();
+ double p1Z = point1.getZ();
+ double p2X = point2.getX();
+ double p2Z = point2.getZ();
+
+ double lineAveX = (p2X-p1X)/pointsInLine;
+ double lineAveZ = (p2Z-p1Z)/pointsInLine;
+
+ HashSet line = new HashSet<>();
+ for(int i = 0; i <= pointsInLine; i++){
+ BlockVector2D vector = new BlockVector2D(p1X + lineAveX * i, p1Z + lineAveZ * i);
+ line.add(vector);
+ }
+ return line;
+ }
+
+ /** This function creates a list of lines from one long string.
+ * Given a max value of characters per line it will iterate through the string till the maximum chars value and then back until the start of the word (until a space symbol is reached).
+ * Then it will cut that string into an extra line.
+ * This way the function will never cut a word in half and still keep the max char value (e.g. line breaks in word)
+ *
+ * @param maxCharsPerLine: max characters per line
+ * @param lineBreaker: characters which creates a new line (e.g. \n)
+ * @return
+ */
+ public static ArrayList createMultilineFromString(String text, int maxCharsPerLine, char lineBreaker){
+ ArrayList list = new ArrayList();
+
+ // Split text at line breaker symbol, iterate through all subtexts and create all lists together to one large list.
+ String[] texts = text.split(String.valueOf(lineBreaker));
+
+ for(String subText : texts)
+ list.addAll(createMultilineFromString(subText, maxCharsPerLine));
+
+ return list;
+ }
+
+ public static ArrayList createMultilineFromString(String text, int maxCharsPerLine){
+ int i = 0;
+ ArrayList list = new ArrayList();
+ String currentText = text;
+ boolean findSpace = false;
+
+
+ // Create infinite loop with termination condition.
+ while (true){
+
+ // If current text is smaller than maxCharsPerLine, then add the rest of the text and return the list.
+ if(currentText == null || currentText.length() < maxCharsPerLine) {
+ if(currentText != null)
+ list.add(currentText);
+ return list;
+ }
+
+ // If it should iterate through the word, increase i until it hits maxCharsPerLine
+ if(!findSpace && i < maxCharsPerLine - 1){
+ i++;
+
+ // If it hit the maxCharsPerLine value, go back until it finds a space.
+ }else{
+ findSpace = true;
+
+ // If it goes back to the start without finding a space symbol, return everything.
+ if(i == 0){
+ list.add(currentText);
+ return list;
+ }
+
+ char currentSymbol = currentText.charAt(i);
+
+ // If it reaches a space symbol, split the text from start till i and add it to the list
+ if(currentSymbol == ' '){
+ String firstPart = currentText.substring(0 , i);
+ String lastPart = currentText.substring(i+1);
+
+ list.add(firstPart);
+ currentText = lastPart;
+ findSpace = false;
+ }
+
+ i--;
+ }
+
+ }
+ }
+
+
public static class CustomHead {
private final ItemStack headItem;
@@ -189,6 +301,9 @@ public ItemStack getAsItemStack() {
public static CustomHead PREVIOUS_BUTTON;
public static CustomHead GLOBE;
+ public static CustomHead PLOT_TYPE;
+ public static CustomHead FOCUS_MODE;
+ public static CustomHead CITY_INSPIRATION_MODE;
public static void loadHeadsAsync(HeadDatabaseAPI api) {
headDatabaseAPI = api;
@@ -206,6 +321,9 @@ public static void loadHeadsAsync(HeadDatabaseAPI api) {
PREVIOUS_BUTTON = new CustomHead("9226");
GLOBE = new CustomHead("49973");
+ PLOT_TYPE = new CustomHead("4159");
+ FOCUS_MODE = new CustomHead("38199");
+ CITY_INSPIRATION_MODE = new CustomHead("38094");
});
}
}
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/ftp/FTPManager.java b/src/main/java/com/alpsbte/plotsystem/utils/ftp/FTPManager.java
index 5caa7c93..e7b37a1a 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/ftp/FTPManager.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/ftp/FTPManager.java
@@ -80,7 +80,7 @@ public static CompletableFuture downloadSchematic(String ftpURL, File sche
// Get remote schematic and write it to local file
FileObject remoteSchematic = remote.resolveFile(schematic.getName());
- localSchematic.copyFrom(remoteSchematic, Selectors.SELECT_SELF);
+ if (remoteSchematic.exists()) localSchematic.copyFrom(remoteSchematic, Selectors.SELECT_SELF);
localSchematic.close();
remoteSchematic.close();
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangPaths.java b/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangPaths.java
index ddd44609..dbf6d187 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangPaths.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangPaths.java
@@ -75,6 +75,10 @@ public static final class MenuTitle {
public static final String REVIEW_PLOT = MENU_TITLES + "review-plot";
public static final String ENTER_PLAYER_NAME = MENU_TITLES + "enter-player-name";
public static final String SELECT_LANGUAGE = MENU_TITLES + "select-language";
+ public static final String SELECT_PLOT_TYPE = MENU_TITLES + "select-plot-type";
+ public static final String SELECT_FOCUS_MODE = MENU_TITLES + "select-focus-mode";
+ public static final String SELECT_INSPIRATION_MODE = MENU_TITLES + "select-local-inspiration-mode";
+ public static final String SELECT_CITY_INSPIRATION_MODE = MENU_TITLES + "select-city-inspiration-mode";
public static final String AUTO_DETECT_LANGUAGE = MENU_TITLES + "auto-detect-language";
}
@@ -101,6 +105,10 @@ public static final class MenuDescription {
public static final String SUBMIT_REVIEW = MENU_DESCRIPTIONS + "submit-review-desc";
public static final String LEAVE_PLOT = MENU_DESCRIPTIONS + "leave-plot-desc";
public static final String SELECT_LANGUAGE = MENU_DESCRIPTIONS + "select-language-desc";
+ public static final String SELECT_PLOT_TYPE = MENU_DESCRIPTIONS + "select-plot-type-desc";
+ public static final String SELECT_FOCUS_MODE = MENU_DESCRIPTIONS + "select-focus-mode-desc";
+ public static final String SELECT_INSPIRATION_MODE = MENU_DESCRIPTIONS + "select-local-inspiration-mode-desc";
+ public static final String SELECT_CITY_INSPIRATION_MODE = MENU_DESCRIPTIONS + "select-city-inspiration-mode-desc";
public static final String AUTO_DETECT_LANGUAGE = MENU_DESCRIPTIONS + "auto-detect-language-desc";
}
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangUtil.java b/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangUtil.java
index 49527525..15572086 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangUtil.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/io/language/LangUtil.java
@@ -18,13 +18,13 @@
public class LangUtil extends YamlFileFactory {
public final static LanguageFile[] languages = new LanguageFile[] {
- new LanguageFile("en_GB", 1.0),
- new LanguageFile("de_DE", 1.0, "de_AT", "de_CH"),
- new LanguageFile("fr_FR", 1.0, "fr_CA"),
- new LanguageFile("ko_KR", 1.0),
- new LanguageFile("ru_RU", 1.0, "ba_RU", "tt_RU"),
- new LanguageFile("zh_CN", 1.0),
- new LanguageFile("zh_TW", 1.0, "zh_HK"),
+ new LanguageFile("en_GB", 1.1),
+ new LanguageFile("de_DE", 1.1, "de_AT", "de_CH"),
+ new LanguageFile("fr_FR", 1.1, "fr_CA"),
+ new LanguageFile("ko_KR", 1.1),
+ new LanguageFile("ru_RU", 1.1, "ba_RU", "tt_RU"),
+ new LanguageFile("zh_CN", 1.1),
+ new LanguageFile("zh_TW", 1.1, "zh_HK"),
};
public LangUtil() {
@@ -59,7 +59,7 @@ private static LanguageFile getLanguageFileByLocale(String locale) {
}
private static String getLocaleTagByPlayer(Player player) {
- Builder builder = new Builder(player.getUniqueId());
+ Builder builder = Builder.byUUID(player.getUniqueId());
if (builder.getLanguageTag() != null) {
return builder.getLanguageTag();
} else return player.getPlayer().getLocale();
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/items/SpecialBlocks.java b/src/main/java/com/alpsbte/plotsystem/utils/items/SpecialBlocks.java
index 86b4c2f7..90b0b1ef 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/items/SpecialBlocks.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/items/SpecialBlocks.java
@@ -38,7 +38,7 @@ public class SpecialBlocks {
"§7ID: §b43:9")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack SeamlessRedSandstone = new ItemBuilder(Material.RED_SANDSTONE, 1, (byte) 2)
@@ -49,7 +49,7 @@ public class SpecialBlocks {
"§7ID: §b181:12")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack SeamlessStone = new ItemBuilder(Material.STONE, 1)
@@ -60,7 +60,7 @@ public class SpecialBlocks {
"§7ID: §b43:8")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack RedMushroom = new ItemBuilder(Material.HUGE_MUSHROOM_2, 1)
@@ -71,7 +71,7 @@ public class SpecialBlocks {
"§7ID: §b100")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack BrownMushroom = new ItemBuilder(Material.HUGE_MUSHROOM_1, 1)
@@ -82,7 +82,7 @@ public class SpecialBlocks {
"§7ID: §b99:14")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack SeamlessMushroomStem = new ItemBuilder(Material.HUGE_MUSHROOM_2, 1)
@@ -93,7 +93,7 @@ public class SpecialBlocks {
"§7ID: §b99:15")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack LightBrownMushroom = new ItemBuilder(Material.HUGE_MUSHROOM_1, 1)
@@ -104,7 +104,7 @@ public class SpecialBlocks {
"§7ID: §b99:11")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack Barrier = new ItemBuilder(Material.BARRIER, 1)
@@ -115,7 +115,7 @@ public class SpecialBlocks {
"§7ID: §b166")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack StructureVoid = new ItemBuilder(Material.STRUCTURE_VOID, 1)
@@ -126,7 +126,7 @@ public class SpecialBlocks {
"§7ID: §b217")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack BarkOakLog = new ItemBuilder(Material.LOG, 1, (byte) 0)
@@ -137,7 +137,7 @@ public class SpecialBlocks {
"§7ID: §b17:12")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack BarkBirchLog = new ItemBuilder(Material.LOG, 1, (byte) 2)
@@ -148,7 +148,7 @@ public class SpecialBlocks {
"§7ID: §b17:14")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack BarkSpruceLog = new ItemBuilder(Material.LOG, 1, (byte) 1)
@@ -159,7 +159,7 @@ public class SpecialBlocks {
"§7ID: §b17:13")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack BarkJungleLog = new ItemBuilder(Material.LOG, 1, (byte) 3)
@@ -170,7 +170,7 @@ public class SpecialBlocks {
"§7ID: §b17:15")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack BarkAcaciaLog = new ItemBuilder(Material.LOG_2, 1, (byte) 0)
@@ -181,7 +181,7 @@ public class SpecialBlocks {
"§7ID: §b162:12")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
public static ItemStack BarkDarkOakLog = new ItemBuilder(Material.LOG_2, 1, (byte) 1)
@@ -192,6 +192,6 @@ public class SpecialBlocks {
"§7ID: §b162:13")
.emptyLine()
.build())
- .setEnchantment(true)
+ .setEnchanted(true)
.build();
}
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/items/builder/ItemBuilder.java b/src/main/java/com/alpsbte/plotsystem/utils/items/builder/ItemBuilder.java
index edef5927..a8975d60 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/items/builder/ItemBuilder.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/items/builder/ItemBuilder.java
@@ -67,11 +67,13 @@ public ItemBuilder setLore(List lore) {
return this;
}
- public ItemBuilder setEnchantment(boolean setEnchanted) {
+ public ItemBuilder setEnchanted(boolean setEnchanted) {
if(setEnchanted) {
itemMeta.addEnchant(Enchantment.ARROW_DAMAGE,1,true);
+ itemMeta.addItemFlags(new ItemFlag[] { ItemFlag.HIDE_ENCHANTS });
} else {
itemMeta.removeEnchant(Enchantment.ARROW_DAMAGE);
+ itemMeta.removeItemFlags(new ItemFlag[] { ItemFlag.HIDE_ENCHANTS });
}
return this;
}
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/items/builder/LoreBuilder.java b/src/main/java/com/alpsbte/plotsystem/utils/items/builder/LoreBuilder.java
index 9fe03b07..81d41d55 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/items/builder/LoreBuilder.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/items/builder/LoreBuilder.java
@@ -50,6 +50,13 @@ public LoreBuilder addLines(String... lines) {
return this;
}
+ public LoreBuilder addLines(List lines) {
+ for (String line : lines) {
+ addLine(line);
+ }
+ return this;
+ }
+
public LoreBuilder emptyLine() {
lore.add("");
return this;
diff --git a/src/main/resources/lang/de_DE.yml b/src/main/resources/lang/de_DE.yml
index 97fb276c..a0cd7ac2 100644
--- a/src/main/resources/lang/de_DE.yml
+++ b/src/main/resources/lang/de_DE.yml
@@ -8,7 +8,7 @@
# | [Formatting] Use // for a newline
# | [Formatting] Words that are wrapped in the {number} tag are replaced afterwards
# |
-# | German translation by BlackStarHD#1333
+# | German translation by BlackStarHD#1333 and R3tuxn#7169
# -----------------------------------------------------
lang:
@@ -88,6 +88,10 @@ menu-title:
enter-player-name: "Spielername Eingeben"
select-language: "Sprache Auswählen"
auto-detect-language: "Sprache Automatisch Erkennen"
+ select-plot-type: "Plot Typ Auswählen"
+ select-focus-mode: "Focus-Mode Auswählen"
+ select-local-inspiration-mode: "Inspiration-Mode Auswählen"
+ select-city-inspiration-mode: "City-Inspiration-Mode Auswählen"
# -----------------------------------------------------
@@ -116,6 +120,10 @@ menu-description:
leave-plot-desc: "Klicke hier, um den Plot zu verlassen"
select-language-desc: "Wähle deine Sprache"
auto-detect-language-desc: "Klicke hier, um deine Sprache automatisch zu erkennen"
+ select-plot-type-desc: 'Wähle dein Plot-Typ aus'
+ select-focus-mode-desc: "Baue dein Plot auf einer schwebenden Insel in einer leeren Welt.\n\n- Keine Umgebung\n- Keine Nachbarsgrundstücke"
+ select-local-inspiration-mode-desc: "Baue dein Plot auf einer schwebenden Insel mit Umgebung, welche als Referenz dient.\n\n+ Umgebung\n- Keine Nachbarsgrundstücke"
+ select-city-inspiration-mode-desc: "Baue dein Plot auf einer schwebenden Insel mit Umgebung und den Plots anderer Spieler, welche sich in der Nähe des eigenen Plots befinden.\n\n+ Umgebung\n+ Nachbarsgrundstücke"
# -----------------------------------------------------
@@ -227,4 +235,4 @@ message:
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.1"
\ No newline at end of file
diff --git a/src/main/resources/lang/en_GB.yml b/src/main/resources/lang/en_GB.yml
index d73f3a4c..b66359e2 100644
--- a/src/main/resources/lang/en_GB.yml
+++ b/src/main/resources/lang/en_GB.yml
@@ -55,67 +55,75 @@ difficulty:
# | Menu Titles
# -----------------------------------------------------
menu-title:
- close: "Close"
- back: "Back"
- next-page: "Next Page"
- previous-page: "Previous Page"
- error: "Error"
- loading: "Loading..."
- navigator: "Navigator"
- plot-difficulty: "Plot Difficulty"
- slot: "Slot"
- builder-utilities: "Builder Utilities"
- show-plots: "Show Plots"
- settings: "Settings"
- submit: "Submit"
- teleport: "Teleport"
- abandon: "Abandon"
- undo-submit: "Undo Submit"
- manage-members: "Manage Members"
- feedback: "Feedback | Review #{0}"
- custom-heads: "Custom Heads"
- banner-maker: "Banner Maker"
- special-blocks: "Special Blocks"
- review-point: "Point"
- review-points: "Points"
- cancel: "Cancel"
- add-member-to-plot: "Add Member to Plot"
- companion: "Companion"
- player-plots: "{0}s Plots"
- leave-plot: "Leave Plot"
- review-plots: "Review Plots"
- review-plot: "Review Plot #{0}"
- enter-player-name: "Enter player name"
- select-language: "Select Language"
- auto-detect-language: "Auto-Detect Language"
+ close: 'Close'
+ back: 'Back'
+ next-page: 'Next Page'
+ previous-page: 'Previous Page'
+ error: 'Error'
+ loading: 'Loading...'
+ navigator: 'Navigator'
+ plot-difficulty: 'Plot Difficulty'
+ slot: 'Slot'
+ builder-utilities: 'Builder Utilities'
+ show-plots: 'Show Plots'
+ settings: 'Settings'
+ submit: 'Submit'
+ teleport: 'Teleport'
+ abandon: 'Abandon'
+ undo-submit: 'Undo Submit'
+ manage-members: 'Manage Members'
+ feedback: 'Feedback | Review #{0}'
+ custom-heads: 'Custom Heads'
+ banner-maker: 'Banner Maker'
+ special-blocks: 'Special Blocks'
+ review-point: 'Point'
+ review-points: 'Points'
+ cancel: 'Cancel'
+ add-member-to-plot: 'Add Member to Plot'
+ companion: 'Companion'
+ player-plots: '{0}s Plots'
+ leave-plot: 'Leave Plot'
+ review-plots: 'Review Plots'
+ review-plot: 'Review Plot #{0}'
+ enter-player-name: 'Enter player name'
+ select-language: 'Select Language'
+ auto-detect-language: 'Auto-Detect Language'
+ select-plot-type: 'Select Plot Type'
+ select-focus-mode: "Select Focus Mode"
+ select-local-inspiration-mode: "Select Inspiration Mode"
+ select-city-inspiration-mode: "Select City Inspiration Mode"
# -----------------------------------------------------
# | Menu Descriptions
# -----------------------------------------------------
menu-description:
- error-desc: "An error occurred..."
- navigator-desc: "Open the navigator menu"
- plot-difficulty-desc: "Click to Switch..."
- slot-desc: "Click on a city project to create a new plot"
- builder-utilities-desc: "Get access to custom heads, banners and special blocks"
- show-plots-desc: "Show all your plots"
- settings-desc: "Modify your user settings"
- submit-plot-desc: "Click to complete this plot and submit it to be reviewed"
- teleport-desc: "Click to teleport to the plot"
- abandon-desc: "Click to reset your plot and give it to someone else"
- undo-submit-desc: "Click to undo your submission"
- manage-members-desc: "Click to open the Plot Members menu, where you can add//and remove other players on your plot"
- feedback-desc: "Click to view your plot review feedback"
- custom-heads-desc: "Click to open the head menu to get a variety of custom heads"
- banner-maker-desc: "Click to open the banner maker menu to create your own custom banners"
- special-blocks-desc: "Click to open the special blocks menu to get a variety of inaccessible blocks"
- add-member-to-plot-desc: "Invite your friends to your plot and start building together"
- review-points-desc: "Click to select"
- submit-review-desc: "Submit selected points and mark plot as reviewed"
- leave-plot-desc: "Click to leave this plot"
- select-language-desc: "Choose your language"
- auto-detect-language-desc: "Click to automatically detect your language"
+ error-desc: 'An error occurred...'
+ navigator-desc: 'Open the navigator menu'
+ plot-difficulty-desc: 'Click to Switch...'
+ slot-desc: 'Click on a city project to create a new plot'
+ builder-utilities-desc: 'Get access to custom heads, banners and special blocks'
+ show-plots-desc: 'Show all your plots'
+ settings-desc: 'Modify your user settings'
+ submit-plot-desc: 'Click to complete this plot and submit it to be reviewed'
+ teleport-desc: 'Click to teleport to the plot'
+ abandon-desc: 'Click to reset your plot and give it to someone else'
+ undo-submit-desc: 'Click to undo your submission'
+ manage-members-desc: 'Click to open the Plot Members menu, where you can add//and remove other players on your plot'
+ feedback-desc: 'Click to view your plot review feedback'
+ custom-heads-desc: 'Click to open the head menu to get a variety of custom heads'
+ banner-maker-desc: 'Click to open the banner maker menu to create your own custom banners'
+ special-blocks-desc: 'Click to open the special blocks menu to get a variety of inaccessible blocks'
+ add-member-to-plot-desc: 'Invite your friends to your plot and start building together'
+ review-points-desc: 'Click to select'
+ submit-review-desc: 'Submit selected points and mark plot as reviewed'
+ leave-plot-desc: 'Click to leave this plot'
+ select-language-desc: 'Choose your language'
+ auto-detect-language-desc: 'Click to automatically detect your language'
+ select-plot-type-desc: 'Choose your plot type'
+ select-focus-mode-desc: "Build your plot on a floating island in the void.\n\n- No Environment\n- No neighboring plots"
+ select-local-inspiration-mode-desc: "Build on a floating island with surrounding environment as a reference.\n\n+ Environment\n- No neighboring plots"
+ select-city-inspiration-mode-desc: "Build on a floating island with surrounding environment and other players plots that got scanned near the own plot.\n\n+ Environment\n+ Neighboring plots"
# -----------------------------------------------------
@@ -227,4 +235,4 @@ message:
# NOTE: Do not change
-config-version: "1.0"
+config-version: "1.1"
diff --git a/src/main/resources/lang/fr_FR.yml b/src/main/resources/lang/fr_FR.yml
index b251a783..b6e7588a 100644
--- a/src/main/resources/lang/fr_FR.yml
+++ b/src/main/resources/lang/fr_FR.yml
@@ -88,6 +88,10 @@ menu-title:
enter-player-name: 'Entrer nom du joueur'
select-language: 'Choix de la langue'
auto-detect-language: 'Détection auto de la Langue'
+ select-plot-type: 'Select Plot Type'
+ select-focus-mode: "Select Focus Mode"
+ select-local-inspiration-mode: "Select Inspiration Mode"
+ select-city-inspiration-mode: "Select City Inspiration Mode"
# -----------------------------------------------------
@@ -116,6 +120,10 @@ menu-description:
leave-plot-desc: "Cliquez pour quitter ce tracé"
select-language-desc: "Choisissez votre langue"
auto-detect-language-desc: "Cliquez pour détecter automatiquement votre langue"
+ select-plot-type-desc: 'Choose your plot type'
+ select-focus-mode-desc: "Build your plot on a floating island in the void.\n\n- No Environment\n- No neighboring plots"
+ select-local-inspiration-mode-desc: "Build on a floating island with surrounding environment as a reference.\n\n+ Environment\n- No neighboring plots"
+ select-city-inspiration-mode-desc: "Build on a floating island with surrounding environment and other players plots that got scanned near the own plot.\n\n+ Environment\n+ Neighboring plots"
# -----------------------------------------------------
@@ -227,4 +235,4 @@ message:
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.1"
\ No newline at end of file
diff --git a/src/main/resources/lang/ko_KR.yml b/src/main/resources/lang/ko_KR.yml
index 6da3de05..335d94ad 100644
--- a/src/main/resources/lang/ko_KR.yml
+++ b/src/main/resources/lang/ko_KR.yml
@@ -88,6 +88,10 @@ menu-title:
enter-player-name: "플레이어 이름 입력하기"
select-language: "언어 설정"
auto-detect-language: "언어 감지"
+ select-plot-type: 'Select Plot Type'
+ select-focus-mode: "Select Focus Mode"
+ select-local-inspiration-mode: "Select Inspiration Mode"
+ select-city-inspiration-mode: "Select City Inspiration Mode"
# -----------------------------------------------------
@@ -116,6 +120,10 @@ menu-description:
leave-plot-desc: "클릭하여 플롯에서 나가기"
select-language-desc: "언어를 선택하세요"
auto-detect-language-desc: "클릭하여 자동으로 언어 감지"
+ select-plot-type-desc: 'Choose your plot type'
+ select-focus-mode-desc: "Build your plot on a floating island in the void.\n\n- No Environment\n- No neighboring plots"
+ select-local-inspiration-mode-desc: "Build on a floating island with surrounding environment as a reference.\n\n+ Environment\n- No neighboring plots"
+ select-city-inspiration-mode-desc: "Build on a floating island with surrounding environment and other players plots that got scanned near the own plot.\n\n+ Environment\n+ Neighboring plots"
# -----------------------------------------------------
@@ -227,4 +235,4 @@ message:
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.1"
\ No newline at end of file
diff --git a/src/main/resources/lang/ru_RU.yml b/src/main/resources/lang/ru_RU.yml
index 081889ea..acb1d3a3 100644
--- a/src/main/resources/lang/ru_RU.yml
+++ b/src/main/resources/lang/ru_RU.yml
@@ -92,6 +92,10 @@ menu-title:
enter-player-name: "Введите имя игрока"
select-language: "Выберите Язык"
auto-detect-language: "Автоматически определять Язык"
+ select-plot-type: 'Select Plot Type'
+ select-focus-mode: "Select Focus Mode"
+ select-local-inspiration-mode: "Select Inspiration Mode"
+ select-city-inspiration-mode: "Select City Inspiration Mode"
# -----------------------------------------------------
@@ -120,6 +124,10 @@ menu-description:
leave-plot-desc: "Нажмите, чтобы покинуть данный участок"
select-language-desc: "Выберите свой язык"
auto-detect-language-desc: "Нажмите, чтобы автоматически определить язык"
+ select-plot-type-desc: 'Choose your plot type'
+ select-focus-mode-desc: "Build your plot on a floating island in the void.\n\n- No Environment\n- No neighboring plots"
+ select-local-inspiration-mode-desc: "Build on a floating island with surrounding environment as a reference.\n\n+ Environment\n- No neighboring plots"
+ select-city-inspiration-mode-desc: "Build on a floating island with surrounding environment and other players plots that got scanned near the own plot.\n\n+ Environment\n+ Neighboring plots"
# -----------------------------------------------------
@@ -231,4 +239,4 @@ message:
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.1"
\ No newline at end of file
diff --git a/src/main/resources/lang/zh_CN.yml b/src/main/resources/lang/zh_CN.yml
index b904129c..4e653cd6 100644
--- a/src/main/resources/lang/zh_CN.yml
+++ b/src/main/resources/lang/zh_CN.yml
@@ -88,6 +88,10 @@ menu-title:
enter-player-name: "输入玩家名称"
select-language: "选择语言"
auto-detect-language: "自动侦测语言"
+ select-plot-type: 'Select Plot Type'
+ select-focus-mode: "Select Focus Mode"
+ select-local-inspiration-mode: "Select Inspiration Mode"
+ select-city-inspiration-mode: "Select City Inspiration Mode"
# -----------------------------------------------------
@@ -116,6 +120,10 @@ menu-description:
leave-plot-desc: "点击以离开此建地"
select-language-desc: "选择你的语言"
auto-detect-language-desc: "点击以自动侦测你的语言"
+ select-plot-type-desc: 'Choose your plot type'
+ select-focus-mode-desc: "Build your plot on a floating island in the void.\n\n- No Environment\n- No neighboring plots"
+ select-local-inspiration-mode-desc: "Build on a floating island with surrounding environment as a reference.\n\n+ Environment\n- No neighboring plots"
+ select-city-inspiration-mode-desc: "Build on a floating island with surrounding environment and other players plots that got scanned near the own plot.\n\n+ Environment\n+ Neighboring plots"
# -----------------------------------------------------
@@ -227,4 +235,4 @@ message:
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.1"
\ No newline at end of file
diff --git a/src/main/resources/lang/zh_TW.yml b/src/main/resources/lang/zh_TW.yml
index 0a468eb7..2025f7c8 100644
--- a/src/main/resources/lang/zh_TW.yml
+++ b/src/main/resources/lang/zh_TW.yml
@@ -88,6 +88,10 @@ menu-title:
enter-player-name: "輸入玩家名稱"
select-language: "選擇語言"
auto-detect-language: "自動偵測語言"
+ select-plot-type: 'Select Plot Type'
+ select-focus-mode: "Select Focus Mode"
+ select-local-inspiration-mode: "Select Inspiration Mode"
+ select-city-inspiration-mode: "Select City Inspiration Mode"
# -----------------------------------------------------
@@ -116,6 +120,10 @@ menu-description:
leave-plot-desc: "點擊以離開此建地"
select-language-desc: "選擇你的語言"
auto-detect-language-desc: "點擊以自動偵測你的語言"
+ select-plot-type-desc: 'Choose your plot type'
+ select-focus-mode-desc: "Build your plot on a floating island in the void.\n\n- No Environment\n- No neighboring plots"
+ select-local-inspiration-mode-desc: "Build on a floating island with surrounding environment as a reference.\n\n+ Environment\n- No neighboring plots"
+ select-city-inspiration-mode-desc: "Build on a floating island with surrounding environment and other players plots that got scanned near the own plot.\n\n+ Environment\n+ Neighboring plots"
# -----------------------------------------------------
@@ -227,4 +235,4 @@ message:
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.1"
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index d37a700d..15c68c45 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -3,7 +3,7 @@ version: 2.3
api-version: 1.12.2
name: Plot-System
author: R3tuxn & Cinnazeyy
-softdepend: [VoidGen, FastAsyncWorldEdit, Multiverse-Core, WorldEdit, HolographicDisplays, WorldGuard, HeadDatabase, ProtocolLib]
+softdepend: [VoidGen, FastAsyncWorldEdit, Multiverse-Core, WorldEdit, HolographicDisplays, WorldGuard, HeadDatabase, ProtocolLib, ParticleNativeAPI]
commands:
spawn: