getCityProjects(boolean onlyVisible) {
+ return getCityProjects(null, onlyVisible);
+ }
+
public static void addCityProject(Country country, String name) throws SQLException {
DatabaseConnection.createStatement("INSERT INTO plotsystem_city_projects (id, name, country_id, description, visible) VALUES (?, ?, ?, ?, ?)")
.setValue(DatabaseConnection.getTableID("plotsystem_city_projects"))
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Country.java b/src/main/java/com/alpsbte/plotsystem/core/system/Country.java
index 8d6eab39..2dd123a1 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/Country.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/Country.java
@@ -2,6 +2,7 @@
import com.alpsbte.plotsystem.core.database.DatabaseConnection;
import com.alpsbte.plotsystem.utils.Utils;
+import com.alpsbte.plotsystem.utils.enums.Continent;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
@@ -19,16 +20,19 @@ public class Country {
private String name;
private String headID;
+ private String continent;
+
public Country(int ID) throws SQLException {
this.ID = ID;
- try (ResultSet rs = DatabaseConnection.createStatement("SELECT server_id, name, head_id FROM plotsystem_countries WHERE id = ?")
+ try (ResultSet rs = DatabaseConnection.createStatement("SELECT server_id, name, head_id, continent FROM plotsystem_countries WHERE id = ?")
.setValue(this.ID).executeQuery()) {
if (rs.next()) {
this.serverID = rs.getInt(1);
this.name = rs.getString(2);
this.headID = rs.getString(3);
+ this.continent = rs.getString(4);
}
DatabaseConnection.closeResultSet(rs);
@@ -48,7 +52,33 @@ public String getName() {
}
public ItemStack getHead() {
- return Utils.getItemHead( new Utils.CustomHead(headID));
+ return Utils.getItemHead(new Utils.CustomHead(headID));
+ }
+
+ /**
+ * Get city projects that are inside of this country
+ *
+ * Might be a good idea to put this in CityProject but could work in both classes
+ *
+ * @return CityProjects inside this country
+ */
+ public List getCityProjects() {
+ try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_city_projects WHERE country_id = ?").setValue(getID()).executeQuery()) {
+ List cityProjects = new ArrayList<>();
+ while (rs.next()) {
+ cityProjects.add(new CityProject(rs.getInt(1)));
+ }
+
+ DatabaseConnection.closeResultSet(rs);
+ return cityProjects;
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }
+ return new ArrayList<>();
+ }
+
+ public Continent getContinent() {
+ return Continent.fromDatabase(continent);
}
public static List getCountries() {
@@ -66,11 +96,26 @@ public static List getCountries() {
return new ArrayList<>();
}
- public static void addCountry(int serverID, String name) throws SQLException {
- DatabaseConnection.createStatement("INSERT INTO plotsystem_countries (id, name, server_id) VALUES (?, ?, ?)")
+ public static List getCountries(Continent continent) {
+ try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_countries WHERE continent = ? ORDER BY server_id").setValue(continent.databaseEnum).executeQuery()) {
+ List countries = new ArrayList<>();
+ while (rs.next()) {
+ countries.add(new Country(rs.getInt(1)));
+ }
+
+ DatabaseConnection.closeResultSet(rs);
+ return countries;
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "A SQL error occurred!", ex);
+ }
+ return new ArrayList<>();
+ }
+
+ public static void addCountry(int serverID, String name, Continent continent) throws SQLException {
+ DatabaseConnection.createStatement("INSERT INTO plotsystem_countries (id, name, server_id, continent) VALUES (?, ?, ?, ?)")
.setValue(DatabaseConnection.getTableID("plotsystem_countries"))
.setValue(name)
- .setValue(serverID).executeUpdate();
+ .setValue(serverID).setValue(continent.databaseEnum).executeUpdate();
}
public static void removeCountry(int countryID) throws SQLException {
diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Payout.java b/src/main/java/com/alpsbte/plotsystem/core/system/Payout.java
new file mode 100644
index 00000000..8258ab5e
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/Payout.java
@@ -0,0 +1,82 @@
+/*
+ * 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;
+
+import com.alpsbte.plotsystem.core.database.DatabaseConnection;
+import com.alpsbte.plotsystem.core.holograms.ScoreLeaderboard;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class Payout {
+ private final int id;
+ private final ScoreLeaderboard.LeaderboardTimeframe timeframe;
+ private final int position;
+ private final String payoutAmount;
+
+ private Payout(int id, ScoreLeaderboard.LeaderboardTimeframe timeframe, int position, String payoutAmount) {
+ this.id = id;
+ this.timeframe = timeframe;
+ this.position = position;
+ this.payoutAmount = payoutAmount;
+ }
+
+ public static Payout getPayout(ScoreLeaderboard.LeaderboardTimeframe timeframe, int position) throws SQLException {
+ if(timeframe == ScoreLeaderboard.LeaderboardTimeframe.LIFETIME) {
+ throw new IllegalArgumentException("Invalid option LIFETIME");
+ }
+ if(position < 1 || position > 10){
+ throw new IllegalArgumentException("Illegal position " + position);
+ }
+
+ try (ResultSet rs = DatabaseConnection.createStatement("SELECT id, timeframe, position, payout_amount FROM plotsystem_payouts WHERE timeframe = ? AND position = ?")
+ .setValue(timeframe.name()).setValue(position).executeQuery()) {
+ Payout instance = null;
+
+ if (rs.next()) {
+ instance = new Payout(rs.getInt(1), ScoreLeaderboard.LeaderboardTimeframe.valueOf(rs.getString(2)), rs.getInt(3), rs.getString(4));
+ }
+
+ DatabaseConnection.closeResultSet(rs);
+ return instance;
+ }
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public ScoreLeaderboard.LeaderboardTimeframe getTimeframe() {
+ return timeframe;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public String getPayoutAmount() {
+ return payoutAmount;
+ }
+}
\ No newline at end of file
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..62d460e6 100644
--- a/src/main/java/com/alpsbte/plotsystem/core/system/Review.java
+++ b/src/main/java/com/alpsbte/plotsystem/core/system/Review.java
@@ -24,13 +24,19 @@
package com.alpsbte.plotsystem.core.system;
+import com.alpsbte.plotsystem.PlotSystem;
import com.alpsbte.plotsystem.core.database.DatabaseConnection;
import com.alpsbte.plotsystem.core.system.plot.Plot;
import com.alpsbte.plotsystem.core.system.plot.PlotManager;
+import com.alpsbte.plotsystem.utils.ChatFeedbackInput;
+import com.alpsbte.plotsystem.utils.Utils;
import com.alpsbte.plotsystem.utils.enums.Category;
import com.alpsbte.plotsystem.utils.enums.Status;
import com.alpsbte.plotsystem.utils.ftp.FTPManager;
+import com.alpsbte.plotsystem.utils.io.language.LangPaths;
+import com.alpsbte.plotsystem.utils.io.language.LangUtil;
import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
import java.io.IOException;
import java.net.URISyntaxException;
@@ -38,11 +44,14 @@
import java.nio.file.Paths;
import java.sql.*;
import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
public class Review {
+ public static HashMap awaitReviewerFeedbackList = new HashMap<>();
private final int reviewID;
@@ -93,7 +102,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);
@@ -244,7 +253,7 @@ public static void undoReview(Review review) throws SQLException {
Files.deleteIfExists(Paths.get(PlotManager.getDefaultSchematicPath(), String.valueOf(plot.getCity().getCountry().getServer().getID()), "finishedSchematics", String.valueOf(plot.getCity().getID()), plot.getID() + ".schematic"));
Server plotServer = plot.getCity().getCountry().getServer();
if (plotServer.getFTPConfiguration() != null) {
- FTPManager.deleteSchematics(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()), plot.getID() + ".schematic", true);
+ FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()), plot.getID() + ".schematic");
}
DatabaseConnection.createStatement("UPDATE plotsystem_plots SET review_id = DEFAULT(review_id) WHERE id = ?")
@@ -260,4 +269,18 @@ public static void undoReview(Review review) throws SQLException {
}
});
}
+
+ public static void checkReviewerFeedbackList() {
+ Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), () -> {
+ if (!awaitReviewerFeedbackList.isEmpty()) {
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ if (awaitReviewerFeedbackList.containsKey(player.getUniqueId()) && awaitReviewerFeedbackList.get(player.getUniqueId()).getDateTime().isBefore(LocalDateTime.now().minusMinutes(5))) {
+ awaitReviewerFeedbackList.remove(player.getUniqueId());
+ player.sendMessage(Utils.getErrorMessageFormat(LangUtil.get(player, LangPaths.Message.Error.FEEDBACK_INPUT_EXPIRED)));
+ player.playSound(player.getLocation(), Utils.ErrorSound, 1f, 1f);
+ }
+ }
+ }
+ }, 0L, 20 * 60);
+ }
}
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..95369980 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,56 +81,86 @@ 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 {
- if (plot.getWorld().isWorldGenerated() && abandonPlot(plot)) {
+ if (abandonPlot(plot)) {
try {
CompletableFuture.runAsync(() -> {
try {
@@ -131,9 +168,12 @@ public static boolean deletePlot(Plot plot) throws SQLException {
Files.deleteIfExists(Paths.get(PlotManager.getDefaultSchematicPath(), String.valueOf(plotServer.getID()), "finishedSchematics", String.valueOf(plot.getCity().getID()), plot.getID() + ".schematic"));
Files.deleteIfExists(Paths.get(PlotManager.getDefaultSchematicPath(), String.valueOf(plotServer.getID()), String.valueOf(plot.getCity().getID()), plot.getID() + ".schematic"));
+ Files.deleteIfExists(Paths.get(PlotManager.getDefaultSchematicPath(), String.valueOf(plotServer.getID()), String.valueOf(plot.getCity().getID()), plot.getID() + "-env.schematic"));
if (plotServer.getFTPConfiguration() != null) {
- FTPManager.deleteSchematics(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()), plot.getID() + ".schematic", false);
+ FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()), plot.getID() + ".schematic");
+ FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()).replaceFirst("finishedSchematics/",""), plot.getID() + ".schematic");
+ FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()).replaceFirst("finishedSchematics/",""), plot.getID() + "-env.schematic");
}
DatabaseConnection.createStatement("DELETE FROM plotsystem_plots WHERE id = ?")
@@ -184,8 +224,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 +241,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..7c302dad 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,18 @@
package com.alpsbte.plotsystem.core.system.plot;
+import com.alpsbte.plotsystem.core.system.Country;
+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.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,28 +53,96 @@
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 com.sk89q.worldguard.protection.regions.ProtectedRegion;
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;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
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,14 +160,42 @@ 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().toString() + "'", statuses)).executeQuery());
+ plots.addAll(getPlotsAsMember(builder, statuses));
+ return plots;
+ }
+
+ public static List getPlots(List countries, Status status) throws SQLException {
+ List cities = new ArrayList<>();
+ countries.forEach(c -> cities.addAll(c.getCityProjects()));
+ return getPlots(cities, status);
+ }
+
+ // 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;
}
public static List getPlots(int cityID, Status... statuses) throws SQLException {
- return listPlots(DatabaseConnection.createStatement(getStatusQuery("' AND city_project_id = '" + cityID, statuses)).executeQuery());
+ return listPlots(DatabaseConnection.createStatement(getStatusQuery(" AND city_project_id = '" + cityID + "'", statuses)).executeQuery());
+ }
+
+ public static List getPlots(List cities, Status... statuses) throws SQLException {
+ if(cities.size() == 0) {
+ return new ArrayList<>();
+ }
+ StringBuilder query = new StringBuilder(" AND (city_project_id = ");
+
+ for (int i = 0; i < cities.size(); i++) {
+ query.append(cities.get(i).getID());
+ query.append((i != cities.size() - 1) ? " OR city_project_id = " : ")");
+ }
+
+ return listPlots(DatabaseConnection.createStatement(getStatusQuery(query.toString(), statuses)).executeQuery());
}
public static List getPlots(int cityID, PlotDifficulty plotDifficulty, Status status) throws SQLException {
@@ -103,8 +209,8 @@ public static List getPlots(int cityID, PlotDifficulty plotDifficulty, Sta
private static String getStatusQuery(String additionalQuery, Status... statuses) {
StringBuilder query = new StringBuilder("SELECT id FROM plotsystem_plots WHERE status = ");
- for(int i = 0; i < statuses.length; i++) {
- query.append("'").append(statuses[i].name()).append(additionalQuery).append("'");
+ for (int i = 0; i < statuses.length; i++) {
+ query.append("'").append(statuses[i].name()).append("'").append(additionalQuery);
query.append((i != statuses.length - 1) ? " OR status = " : "");
}
return query.toString();
@@ -143,145 +249,149 @@ private static List listPlots(ResultSet rs) throws SQLException {
List plots = new ArrayList<>();
while (rs.next()) {
- plots.add(new Plot(rs.getInt(1)));
+ plots.add(new Plot(rs.getInt(1)));
}
DatabaseConnection.closeResultSet(rs);
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
+ if (plot.getPlotType() != PlotType.CITY_INSPIRATION_MODE && plot.getVersion() >= 3) {
+ AbstractPlotGenerator.pasteSchematic(null, plot.getFinishedSchematic(), new CityPlotWorld(plot), false);
+ }
+ return true;
}
- return null;
- });
+ }
}
-
- return true;
+ return false;
}
public static CompletableFuture convertTerraToPlotXZ(Plot plot, double[] terraCoords) throws IOException {
-
// Load plot outlines schematic as clipboard
- Clipboard outlinesClipboard = ClipboardFormat.SCHEMATIC.getReader(new FileInputStream(plot.getOutlinesSchematic())).read(null);
-
- // 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);
-
- Vector schematicMinPoint = Vector.toBlockPoint(
- PlotManager.getPlotCenter().getX() - outlinesClipboardCenterX + ((outlinesClipboard.getRegion().getWidth() % 2 == 0 ? 1 : 0)),
- 0,
- PlotManager.getPlotCenter().getZ() - outlinesClipboardCenterZ + ((outlinesClipboard.getRegion().getLength() % 2 == 0 ? 1 : 0))
- );
-
- Vector schematicMaxPoint = Vector.toBlockPoint(
- PlotManager.getPlotCenter().getX() + outlinesClipboardCenterX,
- 256,
- PlotManager.getPlotCenter().getZ() + outlinesClipboardCenterZ
- );
-
- // Convert terra schematic coordinates into relative plot schematic coordinates
- double[] schematicCoords = {
- terraCoords[0] - outlinesClipboard.getMinimumPoint().getX(),
- terraCoords[1] - outlinesClipboard.getMinimumPoint().getZ()
- };
-
- // Add additional plot sizes to relative plot schematic coordinates
- double[] plotCoords = {
- schematicCoords[0] + schematicMinPoint.getX(),
- schematicCoords[1] + schematicMinPoint.getZ()
- };
-
- // Return coordinates if they are in the schematic plot region
- if(new CuboidRegion(schematicMinPoint, schematicMaxPoint).contains(new Vector((int)plotCoords[0], 15, (int)plotCoords[1]))) {
- return CompletableFuture.completedFuture(plotCoords);
+ Clipboard clipboard = FaweAPI.load(plot.getOutlinesSchematic()).getClipboard();
+
+ if (clipboard != null) {
+ // Calculate min and max points of schematic
+ CuboidRegion plotRegion = getPlotAsRegion(plot);
+
+ if (plotRegion != null) {
+ // Convert terra schematic coordinates into relative plot schematic coordinates
+ double[] schematicCoords = {
+ terraCoords[0] - clipboard.getMinimumPoint().getX(),
+ terraCoords[1] - clipboard.getMinimumPoint().getZ()
+ };
+
+ // Add additional plot sizes to relative plot schematic coordinates
+ double[] plotCoords = {
+ schematicCoords[0] + plotRegion.getMinimumPoint().getX(),
+ schematicCoords[1] + plotRegion.getMinimumPoint().getZ()
+ };
+
+ // Return coordinates if they are in the schematic plot region
+ ProtectedRegion protectedPlotRegion = plot.getWorld().getProtectedRegion() != null ? plot.getWorld().getProtectedRegion() : plot.getWorld().getProtectedBuildRegion();
+ if (protectedPlotRegion.contains(new Vector((int) plotCoords[0], plot.getWorld().getPlotHeightCentered(), (int) plotCoords[1]))) {
+ return CompletableFuture.completedFuture(plotCoords);
+ }
+ }
}
- return null;
+ return null;
}
public static void checkPlotsForLastActivity() {
@@ -291,12 +401,13 @@ public static void checkPlotsForLastActivity() {
FileConfiguration config = PlotSystem.getPlugin().getConfigManager().getConfig();
long millisInDays = config.getLong(ConfigPaths.INACTIVITY_INTERVAL) * 24 * 60 * 60 * 1000; // Remove all plots which have no activity for the last x days
- for(Plot plot : plots) {
- if(plot.getLastActivity() != null && plot.getLastActivity().getTime() < (new Date().getTime() - millisInDays)) {
+ for (Plot plot : plots) {
+ if (plot.getLastActivity() != null && plot.getLastActivity().getTime() < (new Date().getTime() - millisInDays)) {
Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> {
if (PlotHandler.abandonPlot(plot)) {
Bukkit.getLogger().log(Level.INFO, "Abandoned plot #" + plot.getID() + " due to inactivity!");
- } else Bukkit.getLogger().log(Level.WARNING, "An error occurred while abandoning plot #" + plot.getID() + " due to inactivity!");
+ } else
+ Bukkit.getLogger().log(Level.WARNING, "An error occurred while abandoning plot #" + plot.getID() + " due to inactivity!");
});
}
}
@@ -311,30 +422,71 @@ public static void syncPlotSchematicFiles() {
if (config.getBoolean(ConfigPaths.SYNC_FTP_FILES_ENABLED)) {
long interval = config.getLong(ConfigPaths.SYNC_FTP_FILES_INTERVAL);
- Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), () -> {
- CityProject.getCityProjects(false).forEach(c -> {
- try {
- if (c.getCountry().getServer().getFTPConfiguration() != null) {
- List plots = PlotManager.getPlots(c.getID(), Status.unclaimed);
- plots.forEach(Plot::getOutlinesSchematic);
- }
- } catch (SQLException ex) {
- Bukkit.getLogger().log(Level.INFO, "A SQL error occurred!", ex);
+ Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), () -> CityProject.getCityProjects(false).forEach(c -> {
+ try {
+ if (c.getCountry().getServer().getFTPConfiguration() != null) {
+ List plots = PlotManager.getPlots(c.getID(), Status.unclaimed);
+ plots.forEach(Plot::getOutlinesSchematic);
}
- });
- }, 0L, 20 * interval);
+ } catch (SQLException ex) {
+ Bukkit.getLogger().log(Level.INFO, "A SQL error occurred!", ex);
+ }
+ }), 0L, 20 * interval);
}
}
- 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
+ *
+ * @return the current plot of the player
+ */
+ 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.getPlotType() == PlotType.CITY_INSPIRATION_MODE && plot.getCenter().setY(playerVector.getY()).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) {
try (ResultSet rs = DatabaseConnection.createStatement("SELECT COUNT(id) FROM plotsystem_plots WHERE id = ?")
.setValue(ID).executeQuery()) {
- if (rs.next() && rs.getInt(1) > 0){
+ if (rs.next() && rs.getInt(1) > 0) {
DatabaseConnection.closeResultSet(rs);
return true;
}
@@ -355,11 +507,11 @@ public static boolean hasPlotDifficultyScoreRequirement(Builder builder, PlotDif
public static CompletableFuture getPlotDifficultyForBuilder(int cityID, Builder builder) throws SQLException {
// Check if plot difficulties are available
boolean easyHasPlots = false, mediumHasPlots = false, hardHasPlots = false;
- if(PlotManager.getPlots(cityID, PlotDifficulty.EASY, Status.unclaimed).size() != 0) easyHasPlots = true;
- if(PlotManager.getPlots(cityID, PlotDifficulty.MEDIUM, Status.unclaimed).size() != 0) mediumHasPlots = true;
- if(PlotManager.getPlots(cityID, PlotDifficulty.HARD, Status.unclaimed).size() != 0) hardHasPlots = true;
+ if (PlotManager.getPlots(cityID, PlotDifficulty.EASY, Status.unclaimed).size() != 0) easyHasPlots = true;
+ if (PlotManager.getPlots(cityID, PlotDifficulty.MEDIUM, Status.unclaimed).size() != 0) mediumHasPlots = true;
+ if (PlotManager.getPlots(cityID, PlotDifficulty.HARD, Status.unclaimed).size() != 0) hardHasPlots = true;
- if(hardHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.HARD)) { // Return hard
+ if (hardHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.HARD)) { // Return hard
return CompletableFuture.completedFuture(PlotDifficulty.HARD);
} else if (mediumHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.MEDIUM)) { // Return medium
return CompletableFuture.completedFuture(PlotDifficulty.MEDIUM);
@@ -376,30 +528,55 @@ public static CompletableFuture getPlotDifficultyForBuilder(int
return CompletableFuture.completedFuture(PlotDifficulty.MEDIUM);
}
}
- return CompletableFuture.completedFuture(PlotDifficulty.HARD); // If nothing is available return hard (plot availability will be checked later additionally)
+ return CompletableFuture.completedFuture(null); // If nothing is available return null
}
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() || plot.getVersion() <= 2)
+ 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..9efa6126 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,37 @@
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);
- return this;
- }
-
- public PlotPermissions addReviewerPerms() {
- plotWorld.getProtectedRegion().getOwners().addGroup("staff");
- return this;
- }
-
- public PlotPermissions removeReviewerPerms() {
- plotWorld.getProtectedRegion().getOwners().removeGroup("staff");
+ if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().removePlayer(builder);
+ world.getProtectedBuildRegion().getOwners().removePlayer(builder);
+ PlotManager.clearCache(builder);
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");
+ public boolean hasBuildingPerms(UUID builder) {
+ return world.getProtectedBuildRegion().getOwners().contains(builder);
}
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..1f6aff6c 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);
+ 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()) {
+ 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..fe1fd6b4
--- /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 Math.min(MIN_WORLD_HEIGHT + getWorldHeight() + super.getPlotHeightCentered(), PlotWorld.MAX_WORLD_HEIGHT);
+ }
+
+ /**
+ * 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/ChatFeedbackInput.java b/src/main/java/com/alpsbte/plotsystem/utils/ChatFeedbackInput.java
new file mode 100644
index 00000000..c4b7afde
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/utils/ChatFeedbackInput.java
@@ -0,0 +1,47 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright © 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.utils;
+
+import com.alpsbte.plotsystem.core.system.Review;
+
+import java.time.LocalDateTime;
+
+public class ChatFeedbackInput {
+ private final Review review;
+ private final LocalDateTime dateTime;
+
+ public ChatFeedbackInput(Review review) {
+ this.review = review;
+ this.dateTime = LocalDateTime.now();
+ }
+
+ public Review getReview() {
+ return review;
+ }
+
+ public LocalDateTime getDateTime() {
+ return dateTime;
+ }
+}
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..0dd0a94e 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/Utils.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/Utils.java
@@ -25,11 +25,12 @@
package com.alpsbte.plotsystem.utils;
import com.alpsbte.plotsystem.PlotSystem;
-import com.alpsbte.plotsystem.core.menus.CompanionMenu;
+import com.alpsbte.plotsystem.core.menus.companion.CompanionMenu;
import com.alpsbte.plotsystem.core.menus.ReviewMenu;
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,12 @@
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.Arrays;
+import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
@@ -162,6 +168,132 @@ 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)
+ */
+ 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.replaceAll("//", " ").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--;
+ }
+
+ }
+ }
+
+ /**
+ * Get next enum in order of the enum
+ *
+ * @param The enum type
+ * @param haystack The enum class (YourEnum.class)
+ * @param needle Current value that you want to get the next one of
+ * @return Next enum in line
+ */
+ public static > Enum getNextEnum(Class extends Enum> haystack, T needle) {
+ List> enums = Arrays.asList(haystack.getEnumConstants());
+ return getNextListItem(enums, needle);
+ }
+
+ public static T getNextListItem(List haystack, T needle) {
+ if(!haystack.contains(needle) || haystack.indexOf(needle) + 1 >= haystack.size()) {
+ return null;
+ }
+ return haystack.get(haystack.indexOf(needle) + 1);
+ }
+
public static class CustomHead {
private final ItemStack headItem;
@@ -187,8 +319,12 @@ public ItemStack getAsItemStack() {
public static CustomHead BACK_BUTTON;
public static CustomHead NEXT_BUTTON;
public static CustomHead PREVIOUS_BUTTON;
+ public static CustomHead INFO_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;
@@ -204,9 +340,13 @@ public static void loadHeadsAsync(HeadDatabaseAPI api) {
BACK_BUTTON = new CustomHead("9226");
NEXT_BUTTON = new CustomHead("9223");
PREVIOUS_BUTTON = new CustomHead("9226");
+ INFO_BUTTON = new CustomHead("46488");
GLOBE = new CustomHead("49973");
+ PLOT_TYPE = new CustomHead("4159");
+ FOCUS_MODE = new CustomHead("38199");
+ CITY_INSPIRATION_MODE = new CustomHead("38094");
});
}
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/enums/Continent.java b/src/main/java/com/alpsbte/plotsystem/utils/enums/Continent.java
new file mode 100644
index 00000000..628db828
--- /dev/null
+++ b/src/main/java/com/alpsbte/plotsystem/utils/enums/Continent.java
@@ -0,0 +1,50 @@
+package com.alpsbte.plotsystem.utils.enums;
+
+import com.alpsbte.plotsystem.core.system.Country;
+import com.alpsbte.plotsystem.utils.io.language.LangPaths;
+import com.alpsbte.plotsystem.utils.io.language.LangUtil;
+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.bukkit.inventory.ItemStack;
+
+import java.util.Arrays;
+import java.util.List;
+
+public enum Continent {
+ EUROPE("europe", LangPaths.Continent.EUROPE),
+ ASIA("asia", LangPaths.Continent.ASIA),
+ AFRICA("africa", LangPaths.Continent.AFRICA),
+ OCEANIA("oceania", LangPaths.Continent.OCEANIA),
+ SOUTH_AMERICA("south america", LangPaths.Continent.SOUTH_AMERICA),
+ NORTH_AMERICA("north america", LangPaths.Continent.NORTH_AMERICA);
+
+ public final String databaseEnum;
+ public final String langPath;
+
+ Continent(String databaseEnum, String langPath) {
+ this.databaseEnum = databaseEnum;
+ // although LangPath.Continent keys match the enum name, you cannot get the value without reflection
+ this.langPath = langPath;
+ }
+
+ public static Continent fromDatabase(String databaseEnum) {
+ return Arrays.stream(Continent.values()).filter(c -> c.databaseEnum.equals(databaseEnum)).findFirst().orElse(null);
+ }
+
+ /**
+ * Get menu item for this continent
+ *
+ * @param player Used to translate the menu item
+ * @return Menu item
+ */
+ public ItemStack getItem(Player player) {
+ List countries = Country.getCountries(this);
+
+ return new ItemBuilder(Material.COMPASS)
+ .setName("§e§l" + LangUtil.get(player, langPath))
+ .setLore(new LoreBuilder().addLines("§6" + countries.size() + " §7" + LangUtil.get(player, LangPaths.Country.COUNTRIES)).build())
+ .build();
+ }
+}
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..8364eb35 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();
@@ -90,22 +90,11 @@ public static CompletableFuture downloadSchematic(String ftpURL, File sche
return CompletableFuture.completedFuture(null);
}
- public static CompletableFuture deleteSchematics(String ftpURL, String schematicName, boolean onlyFinished) throws FileSystemException {
+ public static CompletableFuture deleteSchematic(String ftpURL, String schematicName) throws FileSystemException {
try (StandardFileSystemManager fileManager = new StandardFileSystemManager()) {
fileManager.init();
FileObject remote, remoteSchematic;
- if (!onlyFinished) {
- remote = fileManager.resolveFile(ftpURL.replaceFirst("finishedSchematics/",""), fileOptions);
- remoteSchematic = remote.resolveFile(schematicName);
- if (remoteSchematic.exists()) {
- remoteSchematic.delete();
- if (remote.getChildren().length == 0) {
- remote.delete();
- }
- }
- }
-
remote = fileManager.resolveFile(ftpURL, fileOptions);
remoteSchematic = remote.resolveFile(schematicName);
if (remoteSchematic.exists()) {
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigPaths.java b/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigPaths.java
index 1c96ac8b..48c454a7 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigPaths.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigPaths.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
@@ -60,6 +60,9 @@ public abstract class ConfigPaths {
public static final String DISPLAY_OPTIONS_SHOW_WEEKLY = DISPLAY_OPTIONS + "show-weekly";
public static final String DISPLAY_OPTIONS_SHOW_MONTHLY = DISPLAY_OPTIONS + "show-monthly";
public static final String DISPLAY_OPTIONS_SHOW_YEARLY = DISPLAY_OPTIONS + "show-yearly";
+ public static final String DISPLAY_OPTIONS_SHOW_LIFETIME = DISPLAY_OPTIONS + "show-lifetime";
+ public static final String DISPLAY_OPTIONS_ACTION_BAR_ENABLED = DISPLAY_OPTIONS + "action-bar-enabled";
+ public static final String DISPLAY_OPTIONS_ACTION_BAR_RADIUS = DISPLAY_OPTIONS + "action-bar-radius";
// Navigator
@@ -87,4 +90,4 @@ public abstract class ConfigPaths {
// CONFIG VERSION
public static final String CONFIG_VERSION = "config-version";
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigUtil.java b/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigUtil.java
index d3cf4715..11e4b676 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigUtil.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/io/config/ConfigUtil.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
@@ -35,19 +35,19 @@
public class ConfigUtil extends YamlFileFactory {
- // Register configuration files
- private static final ConfigFile[] configs = new ConfigFile[] {
- new ConfigFile(Paths.get("config.yml"), 1.5),
- new ConfigFile(Paths.get("commands.yml"), 1.0)
+ // Register configuration files
+ private static final ConfigFile[] configs = new ConfigFile[] {
+ new ConfigFile(Paths.get("config.yml"), 1.6),
+ new ConfigFile(Paths.get("commands.yml"), 1.0)
};
- public ConfigUtil() throws ConfigNotImplementedException {
- super(configs);
+ public ConfigUtil() throws ConfigNotImplementedException {
+ super(configs);
- if (!getConfig().getFile().exists() && createFile(getConfig())) {
- throw new ConfigNotImplementedException("The config file must be configured!");
+ if (!getConfig().getFile().exists() && createFile(getConfig())) {
+ throw new ConfigNotImplementedException("The config file must be configured!");
} else if (reloadFile(getConfig()) && getConfig().getDouble(ConfigPaths.CONFIG_VERSION) != getConfig().getVersion()) {
- updateFile(getConfig());
+ updateFile(getConfig());
}
if (!getCommandsConfig().getFile().exists()) {
@@ -56,7 +56,7 @@ public ConfigUtil() throws ConfigNotImplementedException {
updateFile(getCommandsConfig());
}
- reloadFiles();
+ reloadFiles();
}
public ConfigFile getConfig() {
@@ -88,4 +88,4 @@ public int getMaxConfigWidth() {
return 400;
}
}
-}
+}
\ No newline at end of file
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..c4e14adb 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
@@ -13,6 +13,7 @@ public static final class Plot {
public static final String MEMBERS = PLOT + "members";
public static final String MEMBER = PLOT + "member";
public static final String CITY = PLOT + "city";
+ public static final String COUNTRY = PLOT + "country";
public static final String DIFFICULTY = PLOT + "difficulty";
public static final String STATUS = PLOT + "status";
public static final String SCORE = PLOT + "score";
@@ -29,10 +30,28 @@ public static final class GroupSystem {
public static final class CityProject {
private static final String CITY_PROJECT = "city-project.";
+ public static final String CITIES = CITY_PROJECT + "cities";
public static final String PROJECT_OPEN = CITY_PROJECT + "open";
public static final String PROJECT_IN_PROGRESS = CITY_PROJECT + "in-progress";
public static final String PROJECT_COMPLETED = CITY_PROJECT + "completed";
- public static final String PROJECT_NO_PLOTS = CITY_PROJECT + "no-plots-available";
+ public static final String PROJECT_PLOTS_AVAILABLE = CITY_PROJECT + "plots-available";
+ public static final String PROJECT_NO_PLOTS_AVAILABLE = CITY_PROJECT + "no-plots-available";
+ public static final String FOR_YOUR_DIFFICULTY = CITY_PROJECT + "for-your-difficulty";
+ }
+
+ public static final class Country {
+ private static final String COUNTRY = "country.";
+ public static final String COUNTRIES = COUNTRY + "countries";
+ }
+
+ public static final class Continent {
+ private static final String CONTINENT = "continent.";
+ public static final String EUROPE = CONTINENT + "europe";
+ public static final String ASIA = CONTINENT + "asia";
+ public static final String AFRICA = CONTINENT + "africa";
+ public static final String OCEANIA = CONTINENT + "oceania";
+ public static final String SOUTH_AMERICA = CONTINENT + "south-america";
+ public static final String NORTH_AMERICA = CONTINENT + "north-america";
}
public static final class Difficulty {
@@ -69,6 +88,9 @@ public static final class MenuTitle {
public static final String CANCEL = MENU_TITLES + "cancel";
public static final String ADD_MEMBER_TO_PLOT = MENU_TITLES + "add-member-to-plot";
public static final String COMPANION = MENU_TITLES + "companion";
+ public static final String COMPANION_SELECT_CONTINENT = MENU_TITLES + "companion-select-continent";
+ public static final String COMPANION_SELECT_COUNTRY = MENU_TITLES + "companion-select-country";
+ public static final String COMPANION_SELECT_CITY = MENU_TITLES + "companion-select-city";
public static final String PLAYER_PLOTS = MENU_TITLES + "player-plots";
public static final String LEAVE_PLOT = MENU_TITLES + "leave-plot";
public static final String REVIEW_PLOTS = MENU_TITLES + "review-plots";
@@ -76,6 +98,12 @@ public static final class MenuTitle {
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 AUTO_DETECT_LANGUAGE = MENU_TITLES + "auto-detect-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 FILTER_BY_COUNTRY = MENU_TITLES + "filter-by-country";
+ public static final String INFORMATION = MENU_TITLES + "information";
}
public static final class MenuDescription {
@@ -101,7 +129,13 @@ 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";
+ public static final String FILTER = MENU_DESCRIPTIONS + "filter-desc";
+ public static final String INFORMATION = MENU_DESCRIPTIONS + "information-desc";
}
public static final class Review {
@@ -110,9 +144,11 @@ public static final class Review {
public static final String REVIEW_PLOT = REVIEW + "review-plot";
public static final String MANAGE_PLOT = REVIEW + "manage-plot";
public static final String ACCEPTED = REVIEW + "accepted";
+ public static final String ABANDONED = REVIEW + "abandoned";
public static final String REJECTED = REVIEW + "rejected";
public static final String FEEDBACK = REVIEW + "feedback";
public static final String REVIEWER = REVIEW + "reviewer";
+ public static final String PLAYER_LANGUAGE = REVIEW + "player-language";
public static final class Criteria {
private static final String CRITERIA = REVIEW + "criteria.";
@@ -187,6 +223,8 @@ public static final class Info {
public static final String CREATING_PLOT = INFO + "creating-plot";
public static final String CREATED_NEW_PLOT = INFO + "created-new-plot";
public static final String CHANGED_LANGUAGE = INFO + "changed-language";
+ public static final String ENTER_FEEDBACK = INFO + "enter-feedback";
+ public static final String INPUT_EXPIRES_AFTER = INFO + "input-expires-after";
}
public static final class Error {
@@ -199,7 +237,7 @@ public static final class Error {
public static final String CAN_ONLY_SUBMIT_UNFINISHED_PLOTS = ERROR + "can-only-submit-unfinished-plots";
public static final String CAN_ONLY_UNDO_SUBMISSIONS_UNREVIEWED_PLOTS = ERROR + "can-only-undo-submissions-unreviewed-plots";
public static final String CAN_ONLY_MANAGE_MEMBERS_UNFINISHED = ERROR + "can-only-manage-members-unfinished-plots";
- public static final String CAN_ONLY_TELEPORT_TO_PLOT = ERROR + "can-only-teleport-to-plot";
+ public static final String CANNOT_TELEPORT_OUTSIDE_PLOT = ERROR + "cannot-teleport-outside-plot";
public static final String CANNOT_UNDO_REVIEW = ERROR + "cannot-undo-review";
public static final String CANNOT_SEND_FEEDBACK = ERROR + "cannot-send-feedback";
public static final String CANNOT_REVIEW_OWN_PLOT = ERROR + "cannot-review-own-plot";
@@ -220,8 +258,18 @@ public static final class Error {
public static final String NO_PLOTS_LEFT = ERROR + "no-plots-left";
public static final String PLEASE_WAIT = ERROR + "please-wait";
public static final String ALL_SLOTS_OCCUPIED = ERROR + "all-slots-occupied";
+ public static final String NO_ASSIGNMENT_AS_REVIEWER = ERROR + "no-assignment-as-reviewer";
+ public static final String FEEDBACK_INPUT_EXPIRED = ERROR + "feedback-input-expired";
}
}
+ public static final class Leaderboards {
+ private static final String LBS = "leaderboards.";
+ public static final String PAGES = LBS + "pages.";
+ public static final String ACTIONBAR_POSITION = LBS + "actionbar-position";
+ public static final String ACTIONBAR_PERCENTAGE = LBS + "actionbar-percentage";
+ public static final String NOT_ON_LEADERBOARD = LBS + "not-on-leaderboard";
+ }
+
public static final String CONFIG_VERSION = "config-version";
-}
+}
\ No newline at end of file
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..3834294b 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.2),
+ new LanguageFile("de_DE", 1.2, "de_AT", "de_CH"),
+ new LanguageFile("fr_FR", 1.2, "fr_CA"),
+ new LanguageFile("ko_KR", 1.2),
+ new LanguageFile("ru_RU", 1.2, "ba_RU", "tt_RU"),
+ new LanguageFile("zh_CN", 1.2),
+ new LanguageFile("zh_TW", 1.2, "zh_HK"),
};
public LangUtil() {
@@ -48,7 +48,7 @@ public static String get(CommandSender sender, String key, String... args) {
return getLanguageFileByLocale(sender instanceof Player ? getLocaleTagByPlayer((Player) sender) : languages[0].tag).getTranslation(key, args);
}
- private static LanguageFile getLanguageFileByLocale(String locale) {
+ public static LanguageFile getLanguageFileByLocale(String locale) {
return Arrays.stream(languages)
.filter(lang -> lang.tag.equalsIgnoreCase(locale))
.findFirst()
@@ -59,18 +59,12 @@ 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();
}
- public static void broadcast(String key) {
- for (Player player : Bukkit.getOnlinePlayers()) {
- player.sendMessage(Utils.getInfoMessageFormat(get(player, key)));
- }
- }
-
public static void broadcast(String key, String... args) {
for (Player player : Bukkit.getOnlinePlayers()) {
player.sendMessage(Utils.getInfoMessageFormat(get(player, key, args)));
diff --git a/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java b/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java
index 2c61e639..d1eaeccf 100644
--- a/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java
+++ b/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java
@@ -78,4 +78,10 @@ public static ItemStack loadingItem(Material material, byte subId, Player player
.setName("§6§l" + LangUtil.get(player, LangPaths.MenuTitle.LOADING))
.build();
}
+
+ public static ItemStack filterItem(Player langPlayer) {
+ return new ItemBuilder(Material.HOPPER, 1)
+ .setName("§6§l" + LangUtil.get(langPlayer, LangPaths.MenuTitle.FILTER_BY_COUNTRY))
+ .build();
+ }
}
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/defaultConfig.yml b/src/main/resources/defaultConfig.yml
index 3771e757..7facd767 100644
--- a/src/main/resources/defaultConfig.yml
+++ b/src/main/resources/defaultConfig.yml
@@ -64,13 +64,16 @@ holograms:
z: 0
# Switch hologram statistics between different time stamps
-# [interval] -> default: 5 seconds
+# [interval] -> default: 10 seconds
display-options:
- interval: 5
+ interval: 10
show-daily: false
show-weekly: true
show-monthly: true
show-yearly: false
+ show-lifetime: false
+ action-bar-enabled: true
+ action-bar-radius: 30
# -----------------------------------------------------
@@ -98,4 +101,4 @@ shortlink:
host: https://your.shortlink.host
# NOTE: Do not change
-config-version: 1.5
\ No newline at end of file
+config-version: 1.6
\ No newline at end of file
diff --git a/src/main/resources/lang/de_DE.yml b/src/main/resources/lang/de_DE.yml
index 97fb276c..61ba3a9a 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:
@@ -25,6 +25,7 @@ plot:
members: "Plot Mitglieder"
member: "Plot Mitglied"
city: "Stadt"
+ country: "Land"
difficulty: "Schwierigkeitsgrad"
status: "Status"
score: "Punktestand"
@@ -39,10 +40,30 @@ plot:
# | City Projects
# -----------------------------------------------------
city-project:
+ cities: "Städte"
open: "Offene Plots"
in-progress: "Plots in Arbeit"
completed: "Abgeschlossene Plots"
- no-plots-available: "Keine Plots verfügbar"
+ plots-available: 'Plots Verfügbar'
+ no-plots-available: "Keine Plots Verfügbar"
+ for-your-difficulty: "({0} für deinen Schwierigkeitsgrad)"
+
+# -----------------------------------------------------
+# | Countries
+# -----------------------------------------------------
+country:
+ countries: "Länder"
+
+# -----------------------------------------------------
+# | Continents
+# -----------------------------------------------------
+continent:
+ europe: "Europa"
+ asia: "Asien"
+ africa: "Afrika"
+ oceania: "Ozeanien"
+ south-america: "Südamerika"
+ north-america: "Nordamerika"
# -----------------------------------------------------
# | Difficulty
@@ -81,6 +102,9 @@ menu-title:
cancel: "Abbrechen"
add-member-to-plot: "Mitglied zum Plot Hinzufügen"
companion: "Companion"
+ companion-select-continent: 'Wähle Ein Kontinent'
+ companion-select-country: 'Wähle Ein Land'
+ companion-select-city: 'Wähle Eine Stadt'
player-plots: "{0}s Plots"
leave-plot: "Plot Verlassen"
review-plots: "Plots Bewerten"
@@ -88,7 +112,12 @@ 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"
+ filter-by-country: "Nach Land Filtern"
+ information: "Info"
# -----------------------------------------------------
# | Menu Descriptions
@@ -100,7 +129,7 @@ menu-description:
slot-desc: "Klicke auf eine Stadt, um einen neuen Plot zu erstellen"
builder-utilities-desc: "Erhalte Zugang zu benutzerdefinierten Köpfen, Bannern und speziellen Blöcken"
show-plots-desc: "Alle deine Plots anzeigen"
- settings-desc: "Bearbeite deine Benutzer-Einstellungen"
+ settings-desc: "Bearbeite deine Benutzereinstellungen"
submit-plot-desc: "Klicke hier, um diesen Plot abzuschließen und ihn zur Bewertung einzureichen"
teleport-desc: "Klicke hier, um dich zum Plot zu teleportieren"
abandon-desc: "Klicke hier, um deinen Plot zurückzusetzen und ihn jemand anderem zu geben"
@@ -116,7 +145,12 @@ 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"
+ filter-desc: "Alle Anzeigen"
+ information-desc: "Ein Plot kann maximal 20 Punkte erhalten. Erhält das Plot weniger als 8 Punkte oder eine Kategorie 0 Punkte, wird das Plot abgelehnt und der Builder bekommt das Plot zurück, um es zu verbessern. Bei 0 Punkten wird das Plot gelöscht."
# -----------------------------------------------------
# | Review
@@ -126,9 +160,11 @@ review:
manage-plot: "Plot Verwalten"
manage-and-review-plots: "Plots Verwalten & Bewerten"
accepted: "Angenommen"
+ abandoned: "Gelöscht"
rejected: "Abgelehnt"
feedback: "Feedback"
reviewer: "Reviewer"
+ player-language: "Spielersprache"
criteria:
accuracy: "Genauigkeit"
accuracy-desc: "Wie akkurat ist das Gebäude?////- Sieht aus wie in RL//- Korrekte Umrisse//- Korrekte Höhen//- Ist vollständig"
@@ -139,7 +175,6 @@ review:
technique: "Technik"
technique-desc: "Welche Bautechniken wurden verwendet und wie kreativ sind sie?////- World-Edit//- Spezialblöcke"
-
# -----------------------------------------------------
# | Notes
# -----------------------------------------------------
@@ -177,7 +212,7 @@ message:
abandoned-plot: "§aPlot mit ID §6#{0}§a gelöscht!"
finished-plot: "§a§6{1}§a hat den Plot §6#{0}§a fertiggestellt!"
plot-marked-as-reviewed: "§aPlot §6#{0}§a von §6{1}§a wurde als geprüft markiert!"
- plot-rejected: "§aPlot §6#{0}§a von §6{1}§a wurde abgelehnt! Verwende den Befehl §6/sendFeedback §a um ein Feedback zu hinterlassen!"
+ plot-rejected: "§aPlot §6#{0}§a von §6{1}§a wurde abgelehnt!"
undid-submission: "§aDie Einreichung des Plots §6#{0}§a wurde rückgängig gemacht!"
undid-review: "§aDie Bewertung des Plots §6#{0}§a von §6#{1}§a wurde rückgängig gemacht!"
reviewed-plot: "§aDein Plot §6#{0}§a wurde bewertet!"
@@ -196,6 +231,8 @@ message:
creating-plot: "§aErstelle neuen Plot..."
created-new-plot: "§aEin neuer Plot§a wurde für §6{0}§a erstellt!"
changed-language: "§aAlle Systemnachrichten sind nun auf §6{0}§a!"
+ enter-feedback: "Bitte gebe eine Bewertung des Plots für den Spieler im Chat ein."
+ input-expires-after: "§9Die Chat-Eingabe läuft nach §6{0} §9Minuten ab."
error:
plot-does-not-exist: "Dieser Plot existiert nicht!"
plot-either-unclaimed-or-unreviewed: "Dieser Plot ist entweder unbeansprucht oder wurde noch nicht bewertet!"
@@ -204,7 +241,7 @@ message:
can-only-submit-unfinished-plots: "Du kannst nur unfertige Plots abgeben!"
can-only-undo-submissions-unreviewed-plots: "Du kannst nur Einreichungen von unbewerteten Plots rückgängig machen!"
can-only-manage-members-unfinished-plots: "Du kannst nur Mitglieder von unfertigen Plots verwalten!"
- can-only-tpll-to-plot: "Du kannst /tpll nur auf einem Plot verwenden!"
+ cannot-teleport-outside-plot: "Du kannst dich nicht ausserhalb des Plotes teleportieren!"
cannot-undo-review: "Du kannst eine Bewertung nicht rückgängig machen, wenn du sie nicht selbst erstellt hast!"
cannot-send-feedback: "Du kannst auf einen Plot kein Feedback geben, wenn du ihn nicht selbst bewertet hast!"
cannot-review-own-plot: "Du kannst deine eigenen Plots nicht bewerten!"
@@ -223,8 +260,19 @@ message:
no-plots-left: "Für diese Stadt gibt es keine freien Plots mehr. Bitte wähle einen anderen Ort."
please-wait: "Bitte warte ein paar Sekunden, bevor du einen weiteren neuen Plot erstellst!"
all-slots-occupied: "Alle deine Slots sind belegt! Bitte stelle deine aktuellen Plots fertig, bevor du einen neuen erstellst."
+ no-assignment-as-reviewer: "Du wurdest keinem Build Team als Reviewer zugewiesen."
+ feedback-input-expired: "Die Chat-Eingabe ist abgelaufen! Nutze §7/editfeedback §cum das Feedback zu bearbeiten."
-
+leaderboards:
+ pages:
+ DAILY: "Heute"
+ WEEKLY: "Woche"
+ MONTHLY: "Monat"
+ YEARLY: "Jahr"
+ LIFETIME: "Gesamt"
+ actionbar-position: "Position #{0}"
+ actionbar-percentage: "Top {0}%"
+ not-on-leaderboard: "Nicht auf Leaderboard"
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.2"
\ 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..1b424906 100644
--- a/src/main/resources/lang/en_GB.yml
+++ b/src/main/resources/lang/en_GB.yml
@@ -25,6 +25,7 @@ plot:
members: "Plot Members"
member: "Plot Member"
city: "City"
+ country: "Country"
difficulty: "Difficulty"
status: "Status"
score: "Score"
@@ -39,10 +40,30 @@ plot:
# | City Projects
# -----------------------------------------------------
city-project:
+ cities: "Cities"
open: "Plots Open"
in-progress: "Plots In Progress"
completed: "Plots Completed"
+ plots-available: 'Plots Available'
no-plots-available: "No Plots Available"
+ for-your-difficulty: "({0} for your difficulty)"
+
+# -----------------------------------------------------
+# | Countries
+# -----------------------------------------------------
+country:
+ countries: "Countries"
+
+# -----------------------------------------------------
+# | Continents
+# -----------------------------------------------------
+continent:
+ europe: "Europe"
+ asia: "Asia"
+ africa: "Africa"
+ oceania: "Oceania"
+ south-america: "South America"
+ north-america: "North America"
# -----------------------------------------------------
# | Difficulty
@@ -55,68 +76,81 @@ 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'
+ companion-select-continent: 'Select A Continent'
+ companion-select-country: 'Select A Country'
+ companion-select-city: 'Select A City'
+ 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'
+ filter-by-country: "Filter By Country"
+ information: "Info"
# -----------------------------------------------------
# | 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"
+ filter-desc: "Show All"
+ information-desc: "A plot can receive a maximum of 20 points. If the plot receives less than 8 points or one category has 0 points, the plot is rejected and the builder gets the plot back to improve it. If the plot receives 0 points, it gets abandoned."
# -----------------------------------------------------
# | Review
@@ -127,8 +161,10 @@ review:
manage-and-review-plots: "Manage & Review Plots"
accepted: "Accepted"
rejected: "Rejected"
+ abandoned: "Abandoned"
feedback: "Feedback"
reviewer: "Reviewer"
+ player-language: "Player Language"
criteria:
accuracy: "Accuracy"
accuracy-desc: "How accurate is the building?////- Looks like in RL//- Correct outlines//- Correct height//- Is completed"
@@ -139,7 +175,6 @@ review:
technique: "Technique"
technique-desc: "What building techniques have been used and how creative are they?////- World-Edit//- Special Blocks"
-
# -----------------------------------------------------
# | Notes
# -----------------------------------------------------
@@ -177,7 +212,7 @@ message:
abandoned-plot: "§aAbandoned plot with ID §6#{0}§a!"
finished-plot: "§aPlot §6#{0}§a by §6{1}§a has been finished!"
plot-marked-as-reviewed: "§aPlot §6#{0}§a by §6{1}§a has been marked as reviewed!"
- plot-rejected: "§aPlot §6#{0}§a by §6{1}§a has been rejected! Send feedback using §6/sendFeedback §a!"
+ plot-rejected: "§aPlot §6#{0}§a by §6{1}§a has been rejected!"
undid-submission: "§aUndid submission of plot §6#{0}§a!"
undid-review: "§aUndid review of plot §6#{0}§a by §6#{1}§a!"
reviewed-plot: "§aYour plot §6#{0}§a has been reviewed!"
@@ -196,6 +231,8 @@ message:
creating-plot: "§aCreating new plot..."
created-new-plot: "§aCreated new plot§a for §6{0}§a!"
changed-language: "§aChanged your language to §6{0}§a!"
+ enter-feedback: "Please enter a feedback for the player in the chat."
+ input-expires-after: "§9Chat input expires after §6{0} §9minutes."
error:
plot-does-not-exist: "This plot does not exist!"
plot-either-unclaimed-or-unreviewed: "This plot is either unclaimed or has not been reviewed yet!"
@@ -204,7 +241,7 @@ message:
can-only-submit-unfinished-plots: "You can only submit unfinished plots!"
can-only-undo-submissions-unreviewed-plots: "You can only undo submissions of unreviewed plots!"
can-only-manage-members-unfinished-plots: "You can only manage members of unfinished plots!"
- can-only-tpll-to-plot: "You can only use /tpll on a plot!"
+ cannot-teleport-outside-plot: "You cannot teleport outside the plot!"
cannot-undo-review: "You cannot undo a review that you have not reviewed yourself!"
cannot-send-feedback: "You cannot send feedback to a plot that you have not reviewed yourself!"
cannot-review-own-plot: "You cannot review your own plot!"
@@ -223,8 +260,19 @@ message:
no-plots-left: "This city project does not have any more plots left. Please select another project."
please-wait: "Please wait a few seconds before creating a new plot!"
all-slots-occupied: "All your slots are occupied! Please finish your current plots before creating a new one."
+ no-assignment-as-reviewer: "You have not been assigned to a build team as a reviewer."
+ feedback-input-expired: "The chat input has expired! Use §7/editfeedback §cto edit the feedback."
-
+leaderboards:
+ pages:
+ DAILY: "Daily"
+ WEEKLY: "Weekly"
+ MONTHLY: "Monthly"
+ YEARLY: "Yearly"
+ LIFETIME: "Lifetime"
+ actionbar-position: "Position #{0}"
+ actionbar-percentage: "Top {0}%"
+ not-on-leaderboard: "Not on Leaderboard"
# NOTE: Do not change
-config-version: "1.0"
+config-version: "1.2"
diff --git a/src/main/resources/lang/fr_FR.yml b/src/main/resources/lang/fr_FR.yml
index b251a783..ec114aba 100644
--- a/src/main/resources/lang/fr_FR.yml
+++ b/src/main/resources/lang/fr_FR.yml
@@ -25,6 +25,7 @@ plot:
members: 'Membres du Plot'
member: 'Membre du Plot'
city: 'City'
+ country: "Country"
difficulty: 'Difficulté'
status: 'Statut'
score: 'Score'
@@ -39,10 +40,30 @@ plot:
# | City Projects
# -----------------------------------------------------
city-project:
+ cities: "Cities"
open: 'Plots Ouvert'
in-progress: 'Plots En Progrès'
completed: 'Plots Complété'
+ plots-available: 'Plots Available'
no-plots-available: 'Aucun Plots Disponibles'
+ for-your-difficulty: "({0} for your difficulty)"
+
+# -----------------------------------------------------
+# | Countries
+# -----------------------------------------------------
+country:
+ countries: "Countries"
+
+# -----------------------------------------------------
+# | Continents
+# -----------------------------------------------------
+continent:
+ europe: "Europe"
+ asia: "Asia"
+ africa: "Africa"
+ oceania: "Oceania"
+ south-america: "South America"
+ north-america: "North America"
# -----------------------------------------------------
# | Difficulty
@@ -81,6 +102,9 @@ menu-title:
cancel: 'Annuler'
add-member-to-plot: 'Ajouter Membre au Plot'
companion: 'Compagnon'
+ companion-select-continent: 'Select A Continent'
+ companion-select-country: 'Select A Country'
+ companion-select-city: 'Select A City'
player-plots: '{0}s Plots'
leave-plot: 'Quitter Plot'
review-plots: 'Review Plots'
@@ -88,7 +112,12 @@ 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"
+ filter-by-country: "Filter By Country"
+ information: "Info"
# -----------------------------------------------------
# | Menu Descriptions
@@ -116,7 +145,12 @@ 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"
+ filter-desc: "Show All"
+ information-desc: "A plot can receive a maximum of 20 points. If the plot receives less than 8 points or one category has 0 points, the plot is rejected and the builder gets the plot back to improve it. If the plot receives 0 points, it gets abandoned."
# -----------------------------------------------------
# | Review
@@ -126,9 +160,11 @@ review:
manage-plot: "Gérer le tracé"
manage-and-review-plots: "Gérer et réviser les tracés"
accepted: "Accepté"
+ abandoned: "Abandoned"
rejected: "Refusé"
feedback: "Commentaires"
reviewer: "Relecteur"
+ player-language: "Player Language"
criteria:
accuracy: "Précision"
accuracy-desc: "Quelle est la précision du bâtiment?////- Ressemble à RL//- Contours corrects//- Hauteur correcte//- Est terminé"
@@ -139,7 +175,6 @@ review:
technique: "Technique"
technique-desc: "Quelles techniques de construction ont été utilisées et à quel point sont-elles créatives?////- World-Edit//- Blocs spéciaux"
-
# -----------------------------------------------------
# | Notes
# -----------------------------------------------------
@@ -174,13 +209,13 @@ message:
teleporting-plot: "§aTéléportation pour plot §6#{0}§a..."
teleporting-spawn: "§aTéléportation pour spawn..."
teleporting-tpll: "§aTéléportation au §6{0}§a, §6{1}§a..."
- abandon-plot: "§aParcelle abandonnée avec ID §6#{0}§a!"
- done-plot: "§aLe tracé §6#{0}§a par §6{1}§a est terminé!"
+ abandoned-plot: "§aParcelle abandonnée avec ID §6#{0}§a!"
+ finished-plot: "§aLe tracé §6#{0}§a par §6{1}§a est terminé!"
plot-marked-as-reviewed: "§aLe terrain §6#{0}§a par §6{1}§a a été marqué comme révisé!"
- plot-rejected: "§aLe tracé §6#{0}§a par §6{1}§a a été rejeté! Envoyez des commentaires en utilisant §6/sendFeedback §a!"
+ plot-rejected: "§aLe tracé §6#{0}§a par §6{1}§a a été rejeté!"
undid-submission: "§aUndid soumission du complot §6#{0}§a!"
undid-review: "§aUndid review of plot §6#{0}§a by §6#{1}§a!"
- review-plot: "§aVotre parcelle §6#{0}§a a été revue!"
+ reviewed-plot: "§aVotre parcelle §6#{0}§a a été revue!"
unreviewed-plot: "§aIl y a §6{0}§a un complot non révisé!"
unreviewed-plots: "§aIl y a §6{0}§a des parcelles non revues!"
unfinished-plot: "§aVous avez §6{0}§a un terrain inachevé!"
@@ -188,7 +223,7 @@ message:
enabled-build-permissions: "§aPermissions de construction activées pour les examinateurs sur le tracé §6#{0}§a!"
disabled-build-permissions: "§aAutorisations de construction désactivées pour les examinateurs sur le tracé §6#{0}§a!"
updated-plot-feedback: "§aFeedback for plot §6#{0}§a has been updated!"
- remove-plot-member: "§aSupprimé §6{0}§a du tracé §6#{1}§a!"
+ removed-plot-member: "§aSupprimé §6{0}§a du tracé §6#{1}§a!"
left-plot: "§aTracé de gauche §6#{0}§a!"
plot-will-get-abandoned-warning: "§c§lATTENTION: §cCette parcelle sera automatiquement abandonnée!"
plot-will-get-rejected-warning: "§c§lATTENTION: §cCette parcelle sera rejetée!"
@@ -196,6 +231,8 @@ message:
creating-plot: "§aCréation d'un nouveau tracé..."
created-new-plot: "§aCréé un nouveau tracé§a pour §6{0}§a!"
changed-language: "§aChangement de langue en §6{0}§a!"
+ enter-feedback: "Please enter a feedback for the player in the chat."
+ input-expires-after: "§9Chat input expires after §6{0} §9minutes."
error:
plot-does-not-exist: "Ce complot n'existe pas!"
plot-either-unclaimed-or-unreviewed: "Cette parcelle est soit non réclamée, soit n'a pas encore été examinée!"
@@ -204,10 +241,10 @@ message:
can-only-submit-unfinished-plots: "Vous ne pouvez soumettre que des tracés inachevés!"
can-only-undo-submissions-unreviewed-plots: "Vous ne pouvez annuler que les soumissions de parcelles non révisées!"
can-only-manage-members-unfinished-plots: "Vous ne pouvez gérer que les membres des parcelles inachevées!"
- can-only-tpll-to-plot: "Vous ne pouvez utiliser /tpll que sur un tracé!"
- can-undo-review: "Vous ne pouvez pas annuler une révision que vous n'avez pas révisée vous-même!"
- cant-send-feedback: "Vous ne pouvez pas envoyer de commentaires à un tracé que vous n'avez pas révisé vous-même!"
- can-review-own-plot: "Vous ne pouvez pas réviser votre propre intrigue!"
+ cannot-teleport-outside-plot: "Vous ne pouvez utiliser /tpll que sur un tracé!"
+ cannot-undo-review: "Vous ne pouvez pas annuler une révision que vous n'avez pas révisée vous-même!"
+ cannot-send-feedback: "Vous ne pouvez pas envoyer de commentaires à un tracé que vous n'avez pas révisé vous-même!"
+ cannot-review-own-plot: "Vous ne pouvez pas réviser votre propre intrigue!"
player-has-no-permissions: "Vous n'avez pas la permission de faire ça!"
player-has-no-invitations: "Vous n'avez aucune invitation!"
player-is-not-allowed: "Vous n'êtes pas autorisé à faire ça!"
@@ -223,8 +260,19 @@ message:
no-plots-left: "Ce projet de ville n'a plus de parcelles restantes. Veuillez sélectionner un autre projet."
please-wait: "Veuillez patienter quelques secondes avant de créer un nouveau tracé!"
all-slots-occupied: "Tous vos slots sont occupés! Veuillez terminer vos tracés actuels avant d'en créer un nouveau."
+ no-assignment-as-reviewer: "You have not been assigned to a build team as a reviewer."
+ feedback-input-expired: "The chat input has expired! Use §7/editfeedback §cto edit the feedback."
-
+leaderboards:
+ pages:
+ DAILY: "Daily"
+ WEEKLY: "Weekly"
+ MONTHLY: "Monthly"
+ YEARLY: "Yearly"
+ LIFETIME: "Lifetime"
+ actionbar-position: "Position #{0}"
+ actionbar-percentage: "Top {0}%"
+ not-on-leaderboard: "Not on leaderboard"
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.2"
\ 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..214bcde4 100644
--- a/src/main/resources/lang/ko_KR.yml
+++ b/src/main/resources/lang/ko_KR.yml
@@ -25,6 +25,7 @@ plot:
members: "플롯 멤버들"
member: "플롯 멤버"
city: "도시"
+ country: "Country"
difficulty: "난이도"
status: "상태"
score: "점수"
@@ -39,10 +40,30 @@ plot:
# | City Projects
# -----------------------------------------------------
city-project:
+ cities: "Cities"
open: "개의 빈 플롯"
in-progress: "개의 진행 중인 플롯"
completed: "개의 완성된 플롯"
+ plots-available: 'Plots Available'
no-plots-available: "건축할 수 있는 플롯이 없음"
+ for-your-difficulty: "({0} for your difficulty)"
+
+# -----------------------------------------------------
+# | Countries
+# -----------------------------------------------------
+country:
+ countries: "Countries"
+
+# -----------------------------------------------------
+# | Continents
+# -----------------------------------------------------
+continent:
+ europe: "Europe"
+ asia: "Asia"
+ africa: "Africa"
+ oceania: "Oceania"
+ south-america: "South America"
+ north-america: "North America"
# -----------------------------------------------------
# | Difficulty
@@ -81,6 +102,9 @@ menu-title:
cancel: "취소"
add-member-to-plot: "플롯에 멤버 추가하기"
companion: "메뉴"
+ companion-select-continent: 'Select A Continent'
+ companion-select-country: 'Select A Country'
+ companion-select-city: 'Select A City'
player-plots: "{0}님의 플롯"
leave-plot: "플롯 떠나기"
review-plots: "플롯 리뷰하기"
@@ -88,7 +112,12 @@ 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"
+ filter-by-country: "Filter By Country"
+ information: "Info"
# -----------------------------------------------------
# | Menu Descriptions
@@ -116,7 +145,12 @@ 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"
+ filter-desc: "Show All"
+ information-desc: "A plot can receive a maximum of 20 points. If the plot receives less than 8 points or one category has 0 points, the plot is rejected and the builder gets the plot back to improve it. If the plot receives 0 points, it gets abandoned."
# -----------------------------------------------------
# | Review
@@ -126,9 +160,11 @@ review:
manage-plot: "플롯 관리하기"
manage-and-review-plots: "플롯 리뷰 / 관리하기"
accepted: "승낙됨"
+ abandoned: "Abandoned"
rejected: "거절됨"
feedback: "피드백"
reviewer: "검토자"
+ player-language: "Player Language"
criteria:
accuracy: "정확도"
accuracy-desc: "얼마나 정확하게 건축되었나요?////- 현실과의 유사성//- 올바른 외곽선//- 올바른 높이//- 완성도"
@@ -139,7 +175,6 @@ review:
technique: "기법"
technique-desc: "사용된 건축 기법들은 무엇이고 얼마나 창의적인가요?////- 월드에딧//- 특수 블록"
-
# -----------------------------------------------------
# | Notes
# -----------------------------------------------------
@@ -177,7 +212,7 @@ message:
abandoned-plot: "§aID §6#{0}§a의 플롯을 버렸습니다!"
finished-plot: "§6{1}§a님의 플롯 §6#{0}§a(이)가 완성되었습니다!"
plot-marked-as-reviewed: "§6{1}§a님의 플롯 §6#{0}§a(이)가 리뷰되었습니다!"
- plot-rejected: "§6{1}§a님의 플롯 §6#{0}§a(이)가 거절되었습니다. §6/sendFeedback <텍스트>§a 명령어로 피드백을 보내세요!"
+ plot-rejected: "§6{1}§a님의 플롯 §6#{0}§a(이)가 거절되었습니다."
undid-submission: "§a플롯 §6#{0}§a의 제출을 취소하였습니다!"
undid-review: "§6{1}§a님의 플롯 §6#{0}§a의 리뷰를 취소하였습니다!"
reviewed-plot: "§a당신의 플롯 §6#{0}§a(이)가 리뷰되었습니다!"
@@ -196,6 +231,8 @@ message:
creating-plot: "§a새로운 플롯 생성 중..."
created-new-plot: "§6{0}§a님의 플롯을 생성하였습니다!"
changed-language: "§a언어를 §6{0}§a(으)로 변경하였습니다!"
+ enter-feedback: "Please enter a feedback for the player in the chat."
+ input-expires-after: "§9Chat input expires after §6{0} §9minutes."
error:
plot-does-not-exist: "존재하지 않는 플롯입니다!"
plot-either-unclaimed-or-unreviewed: "아직 소유되거나 검토되지 않은 플롯입니다!"
@@ -204,7 +241,7 @@ message:
can-only-submit-unfinished-plots: "미완성된 플롯만 제출하실 수 있습니다!"
can-only-undo-submissions-unreviewed-plots: "이미 리뷰된 플롯의 제출을 취소하실 수 없습니다!"
can-only-manage-members-unfinished-plots: "멤버 관리는 미완성된 플롯에서만 가능합니다!"
- can-only-tpll-to-plot: "플롯에서는 /tpll만 사용할 수 있습니다!"
+ cannot-teleport-outside-plot: "플롯에서는 /tpll만 사용할 수 있습니다!"
cannot-undo-review: "오직 자신의 리뷰만 취소할 수 있습니다!"
cannot-send-feedback: "오직 자신이 리뷰한 플롯에만 피드백을 보낼 수 있습니다!"
cannot-review-own-plot: "자신의 플롯은 검토할 수 없습니다!"
@@ -223,8 +260,19 @@ message:
no-plots-left: "이 도시 프로젝트에 남아있는 플롯이 없습니다. 다른 프로젝트를 선택해주세요."
please-wait: "새 플롯이 생성될 때까지 기다려주세요!"
all-slots-occupied: "슬롯이 모두 꽉 찼습니다! 새 플롯을 생성하기 전에 현재 남아있는 플롯을 먼저 완성해주세요."
+ no-assignment-as-reviewer: "You have not been assigned to a build team as a reviewer."
+ feedback-input-expired: "The chat input has expired! Use §7/editfeedback §cto edit the feedback."
-
+leaderboards:
+ pages:
+ DAILY: "Daily"
+ WEEKLY: "Weekly"
+ MONTHLY: "Monthly"
+ YEARLY: "Yearly"
+ LIFETIME: "Lifetime"
+ actionbar-position: "Position #{0}"
+ actionbar-percentage: "Top {0}%"
+ not-on-leaderboard: "Not on leaderboard"
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.2"
\ 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..2d136e69 100644
--- a/src/main/resources/lang/ru_RU.yml
+++ b/src/main/resources/lang/ru_RU.yml
@@ -15,7 +15,6 @@ lang:
name: "Русский (Россия)"
head-id: "4406"
-
# -----------------------------------------------------
# | Plot
# -----------------------------------------------------
@@ -26,6 +25,7 @@ plot:
members: "Участник собственности"
member: "Участник Участка"
city: "Город"
+ country: "Country"
difficulty: "Сложность"
status: "Статус"
score: "Оценка"
@@ -36,16 +36,34 @@ plot:
empty-member-slot: "Пустое место для участника"
shared-by-members: "(разделен {0} участниками)"
-
# -----------------------------------------------------
# | City Projects
# -----------------------------------------------------
city-project:
+ cities: "Cities"
open: "Свободных Участков"
in-progress: "Участков в Процессе Постройки"
completed: "Завершённых Участков"
+ plots-available: 'Plots Available'
no-plots-available: "Доступных Участков Нет"
+ for-your-difficulty: "({0} for your difficulty)"
+
+# -----------------------------------------------------
+# | Countries
+# -----------------------------------------------------
+country:
+ countries: "Countries"
+# -----------------------------------------------------
+# | Continents
+# -----------------------------------------------------
+continent:
+ europe: "Europe"
+ asia: "Asia"
+ africa: "Africa"
+ oceania: "Oceania"
+ south-america: "South America"
+ north-america: "North America"
# -----------------------------------------------------
# | Difficulty
@@ -54,7 +72,6 @@ difficulty:
automatic: "Автоматическая"
score-multiplier: "Множитель Оценки"
-
# -----------------------------------------------------
# | Menu Titles
# -----------------------------------------------------
@@ -85,6 +102,9 @@ menu-title:
cancel: "Отменить"
add-member-to-plot: "Добавить Участника к Участку"
companion: "Компаньонка"
+ companion-select-continent: 'Select A Continent'
+ companion-select-country: 'Select A Country'
+ companion-select-city: 'Select A City'
player-plots: "{0} Участков"
leave-plot: "Покинуть Участок"
review-plots: "Оценить Участки"
@@ -92,7 +112,12 @@ 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"
+ filter-by-country: "Filter By Country"
+ information: "Info"
# -----------------------------------------------------
# | Menu Descriptions
@@ -120,7 +145,12 @@ 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"
+ filter-desc: "Show All"
+ information-desc: "A plot can receive a maximum of 20 points. If the plot receives less than 8 points or one category has 0 points, the plot is rejected and the builder gets the plot back to improve it. If the plot receives 0 points, it gets abandoned."
# -----------------------------------------------------
# | Review
@@ -130,9 +160,11 @@ review:
manage-plot: "Управлять участком"
manage-and-review-plots: "Управление и Оценка Участков"
accepted: "Одобрено"
+ abandoned: "Abandoned"
rejected: "Отклонено"
feedback: "Отзыв"
reviewer: "Оценщик"
+ player-language: "Player Language"
criteria:
accuracy: "Точность Воссоздания"
accuracy-desc: "Насколько точно исполнено здание?////- Выглядит как в настоящей жизни//- Правильные контуры//- Правильная высота//- Полностью завершен"
@@ -143,7 +175,6 @@ review:
technique: "Техника"
technique-desc: "Какие строительные техники были применены и насколько они креативны?////- World-Edit//- Специальные Блоки"
-
# -----------------------------------------------------
# | Notes
# -----------------------------------------------------
@@ -181,7 +212,7 @@ message:
abandoned-plot: "§aПокидание участка с ID §6#{0}§a!"
finished-plot: "§aУчасток §6#{0}§a построенный §6{1}§a был завершён!"
plot-marked-as-reviewed: "§aУчасток §6#{0}§a построенный §6{1}§aбыл помечена как оценённый!!"
- plot-rejected: "§aУчасток §6#{0}§a построенный §6{1}§a был отклонен! Отправьте отзыв через §6/sendFeedback §a!"
+ plot-rejected: "§aУчасток §6#{0}§a построенный §6{1}§a был отклонен!"
undid-submission: "§aОтмена отправки участка §6#{0}§a!"
undid-review: "§aОтмена оценки участка §6#{0}§a построенным §6#{1}§a!"
reviewed-plot: "§aВаш участок §6#{0}§a был оценён!"
@@ -200,6 +231,8 @@ message:
creating-plot: "§aСоздание нового участка..."
created-new-plot: "§aСоздан новый участок§a для §6{0}§a!"
changed-language: "§aВаш язык изменён на §6{0}§a!"
+ enter-feedback: "Please enter a feedback for the player in the chat."
+ input-expires-after: "§9Chat input expires after §6{0} §9minutes."
error:
plot-does-not-exist: "Этот участок не существует!"
plot-either-unclaimed-or-unreviewed: "Этот участок не занят либо ещё не был оценён!!"
@@ -208,7 +241,7 @@ message:
can-only-submit-unfinished-plots: "Вы только можете отправить незавёршенные участки!Y!"
can-only-undo-submissions-unreviewed-plots: "Вы только можете отменить заявки незавершённых участков!"
can-only-manage-members-unfinished-plots: "Вы только можете управлять участниками незавершённых участков!"
- can-only-tpll-to-plot: "Вы только можете использовать /tpll на участке!"
+ cannot-teleport-outside-plot: "Вы только можете использовать /tpll на участке!"
cannot-undo-review: "Вы не можете отменить оценку которую выставляли не вы!"
cannot-send-feedback: "Вы не можете отправить отзыв к участку который оценивали не вы!"
cannot-review-own-plot: "Вы не можете оценить свой участок!"
@@ -227,8 +260,19 @@ message:
no-plots-left: "У этого градостроительного проекта больше не осталось участков. Пожалуйста, выберите другой проект."
please-wait: "Пожалуйста, подождите несколько секунд перед созданием нового участка!"
all-slots-occupied: "Все ваши слоты заняты! Пожалуйста, завершите текущие участки, прежде чем создавать новый."
+ no-assignment-as-reviewer: "You have not been assigned to a build team as a reviewer."
+ feedback-input-expired: "The chat input has expired! Use §7/editfeedback §cto edit the feedback."
-
+leaderboards:
+ pages:
+ DAILY: "Daily"
+ WEEKLY: "Weekly"
+ MONTHLY: "Monthly"
+ YEARLY: "Yearly"
+ LIFETIME: "Lifetime"
+ actionbar-position: "Position #{0}"
+ actionbar-percentage: "Top {0}%"
+ not-on-leaderboard: "Not on leaderboard"
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.2"
\ 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..46bb0f16 100644
--- a/src/main/resources/lang/zh_CN.yml
+++ b/src/main/resources/lang/zh_CN.yml
@@ -25,6 +25,7 @@ plot:
members: "建地成员"
member: "建地成员"
city: "城市"
+ country: "Country"
difficulty: "难度"
status: "状态"
score: "积分"
@@ -39,10 +40,30 @@ plot:
# | City Projects
# -----------------------------------------------------
city-project:
+ cities: "Cities"
open: "开启建地"
in-progress: "进行中建地"
completed: "已完成建地"
+ plots-available: 'Plots Available'
no-plots-available: "无可用建地"
+ for-your-difficulty: "({0} for your difficulty)"
+
+# -----------------------------------------------------
+# | Countries
+# -----------------------------------------------------
+country:
+ countries: "Countries"
+
+# -----------------------------------------------------
+# | Continents
+# -----------------------------------------------------
+continent:
+ europe: "Europe"
+ asia: "Asia"
+ africa: "Africa"
+ oceania: "Oceania"
+ south-america: "South America"
+ north-america: "North America"
# -----------------------------------------------------
# | Difficulty
@@ -81,6 +102,9 @@ menu-title:
cancel: "取消"
add-member-to-plot: "添加成员到建地"
companion: "伙伴"
+ companion-select-continent: 'Select A Continent'
+ companion-select-country: 'Select A Country'
+ companion-select-city: 'Select A City'
player-plots: "{0}块建地"
leave-plot: "离开建地"
review-plots: "审核建地"
@@ -88,7 +112,12 @@ 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"
+ filter-by-country: "Filter By Country"
+ information: "Info"
# -----------------------------------------------------
# | Menu Descriptions
@@ -116,7 +145,12 @@ 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"
+ filter-desc: "Show All"
+ information-desc: "A plot can receive a maximum of 20 points. If the plot receives less than 8 points or one category has 0 points, the plot is rejected and the builder gets the plot back to improve it. If the plot receives 0 points, it gets abandoned."
# -----------------------------------------------------
# | Review
@@ -126,9 +160,11 @@ review:
manage-plot: "管理建地"
manage-and-review-plots: "管理与审核建地"
accepted: "接受"
+ abandoned: "Abandoned"
rejected: "驳回"
feedback: "回馈"
reviewer: "审核员"
+ player-language: "Player Language"
criteria:
accuracy: "准确性"
accuracy-desc: "建筑的精确度如何? ////- 看起来像在真实世界//- 正确的轮廓//- 正确的高度//- 完成了"
@@ -139,7 +175,6 @@ review:
technique: "技巧"
technique-desc: "使用了什么建筑技巧,它们的创意如何? ////- World-Edit//- 特殊方块"
-
# -----------------------------------------------------
# | Notes
# -----------------------------------------------------
@@ -177,7 +212,7 @@ message:
abandoned-plot: "§a有ID之废弃建地 §6#{0}§a!"
finished-plot: "§a §6{1}§a 的建地 §6#{0}§a 已完成! "
plot-marked-as-reviewed: "§a §6{1}§a 的建地 §6#{0}§a 已标记供审核! "
- plot-rejected: "§a §6{1}§a 的建地 §6#{0}§a 已被驳回!使用 §6/sendFeedback §a发送回馈! "
+ plot-rejected: "§a §6{1}§a 的建地 §6#{0}§a 已被驳回!"
undid-submission: "§a尚未提交的建地 §6#{0}§a! "
undid-review: "§a尚未审核的建地 §6#{0}§a by §6#{1}§a! "
reviewed-plot: "§a你的建地 §6#{0}§a 已被审核! "
@@ -196,6 +231,8 @@ message:
creating-plot: "§a创建新建地..."
created-new-plot: "§a创建新建地§a 为 §6{0}§a! "
changed-language: "§a将你的语言变更为 §6{0}§a! "
+ enter-feedback: "Please enter a feedback for the player in the chat."
+ input-expires-after: "§9Chat input expires after §6{0} §9minutes."
error:
plot-does-not-exist: "此建地不存在! "
plot-either-unclaimed-or-unreviewed: "此建地无人认领或尚未审核! "
@@ -204,7 +241,7 @@ message:
can-only-submit-unfinished-plots: "你只能提交尚未完成的建地! "
can-only-undo-submissions-unreviewed-plots: "你只能撤回尚未审核的建地! "
can-only-manage-members-unfinished-plots: "你只能管理尚未完成建地的成员! "
- can-only-tpll-to-plot: "你在建地上只能使用 /tpll ! "
+ cannot-teleport-outside-plot: "你在建地上只能使用 /tpll ! "
cannot-undo-review: "你无法撤回你自己未审核过的审核! "
cannot-send-feedback: "你无法发送你自己未审核过的回馈! "
cannot-review-own-plot: "你无法审核你所有的建地! "
@@ -223,8 +260,19 @@ message:
no-plots-left: "此城市计画区没有剩余更多建地了。请选择其他计画区。"
please-wait: "请稍后再创建一个新的建地!"
all-slots-occupied: "你的所有槽位都被占用了!请在创建新的建地之前先完成您当前的建地。"
+ no-assignment-as-reviewer: "You have not been assigned to a build team as a reviewer."
+ feedback-input-expired: "The chat input has expired! Use §7/editfeedback §cto edit the feedback."
-
+leaderboards:
+ pages:
+ DAILY: "Daily"
+ WEEKLY: "Weekly"
+ MONTHLY: "Monthly"
+ YEARLY: "Yearly"
+ LIFETIME: "Lifetime"
+ actionbar-position: "Position #{0}"
+ actionbar-percentage: "Top {0}%"
+ not-on-leaderboard: "Not on leaderboard"
# NOTE: Do not change
-config-version: "1.0"
\ No newline at end of file
+config-version: "1.2"
\ 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..4389700a 100644
--- a/src/main/resources/lang/zh_TW.yml
+++ b/src/main/resources/lang/zh_TW.yml
@@ -25,6 +25,7 @@ plot:
members: "建地成員"
member: "建地成員"
city: "城市"
+ country: "Country"
difficulty: "難度"
status: "狀態"
score: "積分"
@@ -39,10 +40,30 @@ plot:
# | City Projects
# -----------------------------------------------------
city-project:
+ cities: "Cities"
open: "開啟建地"
in-progress: "進行中建地"
completed: "已完成建地"
+ plots-available: 'Plots Available'
no-plots-available: "無可用建地"
+ for-your-difficulty: "({0} for your difficulty)"
+
+# -----------------------------------------------------
+# | Countries
+# -----------------------------------------------------
+country:
+ countries: "Countries"
+
+# -----------------------------------------------------
+# | Continents
+# -----------------------------------------------------
+continent:
+ europe: "Europe"
+ asia: "Asia"
+ africa: "Africa"
+ oceania: "Oceania"
+ south-america: "South America"
+ north-america: "North America"
# -----------------------------------------------------
# | Difficulty
@@ -81,6 +102,9 @@ menu-title:
cancel: "取消"
add-member-to-plot: "添加成員到建地"
companion: "夥伴"
+ companion-select-continent: 'Select A Continent'
+ companion-select-country: 'Select A Country'
+ companion-select-city: 'Select A City'
player-plots: "{0}塊建地"
leave-plot: "離開建地"
review-plots: "審核建地"
@@ -88,7 +112,12 @@ 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"
+ filter-by-country: "Filter By Country"
+ information: "Info"
# -----------------------------------------------------
# | Menu Descriptions
@@ -116,7 +145,12 @@ 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"
+ filter-desc: "Show All"
+ information-desc: "A plot can receive a maximum of 20 points. If the plot receives less than 8 points or one category has 0 points, the plot is rejected and the builder gets the plot back to improve it. If the plot receives 0 points, it gets abandoned."
# -----------------------------------------------------
# | Review
@@ -126,9 +160,11 @@ review:
manage-plot: "管理建地"
manage-and-review-plots: "管理與審核建地"
accepted: "接受"
+ abandoned: "Abandoned"
rejected: "駁回"
feedback: "回饋"
reviewer: "審核員"
+ player-language: "Player Language"
criteria:
accuracy: "準確性"
accuracy-desc: "建築的精確度如何?////- 看起來像在真實世界//- 正確的輪廓//- 正確的高度//- 完成了"
@@ -139,7 +175,6 @@ review:
technique: "技巧"
technique-desc: "使用了什麼建築技巧,它們的創意如何?////- World-Edit//- 特殊方塊"
-
# -----------------------------------------------------
# | Notes
# -----------------------------------------------------
@@ -177,7 +212,7 @@ message:
abandoned-plot: "§a有ID之廢棄建地 §6#{0}§a!"
finished-plot: "§a §6{1}§a 的建地 §6#{0}§a 已完成!"
plot-marked-as-reviewed: "§a §6{1}§a 的建地 §6#{0}§a 已標記供審核!"
- plot-rejected: "§a §6{1}§a 的建地 §6#{0}§a 已被駁回! 使用 §6/sendFeedback §a發送回饋!"
+ plot-rejected: "§a §6{1}§a 的建地 §6#{0}§a 已被駁回!"
undid-submission: "§a尚未提交的建地 §6#{0}§a!"
undid-review: "§a尚未審核的建地 §6#{0}§a by §6#{1}§a!"
reviewed-plot: "§a你的建地 §6#{0}§a 已被審核!"
@@ -196,6 +231,8 @@ message:
creating-plot: "§a創建新建地..."
created-new-plot: "§a創建新建地§a 為 §6{0}§a!"
changed-language: "§a將你的語言變更為 §6{0}§a!"
+ enter-feedback: "Please enter a feedback for the player in the chat."
+ input-expires-after: "§9Chat input expires after §6{0} §9minutes."
error:
plot-does-not-exist: "此建地不存在!"
plot-either-unclaimed-or-unreviewed: "此建地無人認領或尚未審核!"
@@ -204,7 +241,7 @@ message:
can-only-submit-unfinished-plots: "你只能提交尚未完成的建地!"
can-only-undo-submissions-unreviewed-plots: "你只能撤回尚未審核的建地!"
can-only-manage-members-unfinished-plots: "你只能管理尚未完成建地的成員!"
- can-only-tpll-to-plot: "你在建地上只能使用 /tpll !"
+ cannot-teleport-outside-plot: "你在建地上只能使用 /tpll !"
cannot-undo-review: "你無法撤回你自己未審核過的審核!"
cannot-send-feedback: "你無法發送你自己未審核過的回饋!"
cannot-review-own-plot: "你無法審核你所有的建地!"
@@ -223,8 +260,19 @@ message:
no-plots-left: "此城市計畫區沒有剩餘更多建地了。請選擇其他計畫區。"
please-wait: "請稍後再創建一個新的建地!"
all-slots-occupied: "你的所有槽位都被占用了!請在創建新的建地之前先完成您當前的建地。"
+ no-assignment-as-reviewer: "You have not been assigned to a build team as a reviewer."
+ feedback-input-expired: "The chat input has expired! Use §7/editfeedback