diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java index 23a869023..67704d95f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java @@ -490,6 +490,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl TaskManager.getPlatformImplementation().taskRepeat(this::unload, TaskTime.seconds(1L)); try { singleWorldListener = injector().getInstance(SingleWorldListener.class); + Bukkit.getPluginManager().registerEvents(singleWorldListener, this); } catch (Exception e) { e.printStackTrace(); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java index e8ebba87c..f7601c880 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java @@ -31,6 +31,7 @@ import com.google.inject.Singleton; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.assistedinject.FactoryProvider; import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.bukkit.listener.SingleWorldListener; import com.plotsquared.bukkit.player.BukkitPlayerManager; import com.plotsquared.bukkit.queue.BukkitChunkCoordinator; import com.plotsquared.bukkit.queue.BukkitQueueCoordinator; @@ -104,6 +105,11 @@ public class BukkitModule extends AbstractModule { bind(SchematicHandler.class).to(BukkitSchematicHandler.class); if (Settings.Enabled_Components.WORLDS) { bind(PlotAreaManager.class).to(SinglePlotAreaManager.class); + try { + bind(SingleWorldListener.class).toInstance(new SingleWorldListener()); + } catch (Exception e) { + e.printStackTrace(); + } } else { bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/SingleWorldListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/SingleWorldListener.java index aa76b8364..6f78034a2 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/SingleWorldListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/SingleWorldListener.java @@ -29,7 +29,6 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.util.ReflectionUtils; -import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.event.EventHandler; @@ -37,7 +36,6 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.world.ChunkEvent; import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.plugin.java.JavaPlugin; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -49,24 +47,29 @@ public class SingleWorldListener implements Listener { private Method methodGetHandleChunk; private Field mustSave; + private boolean isTrueForNotSave = true; - public SingleWorldListener(JavaPlugin plugin) throws Exception { + public SingleWorldListener() throws Exception { ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk"); ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle").getRealMethod(); try { - this.mustSave = classChunk.getField("mustSave").getRealField(); + if (PlotSquared.platform().serverVersion()[1] == 13) { + this.mustSave = classChunk.getField("mustSave").getRealField(); + this.isTrueForNotSave = false; + } else { + this.mustSave = classChunk.getField("mustNotSave").getRealField(); + } } catch (NoSuchFieldException e) { e.printStackTrace(); } - Bukkit.getPluginManager().registerEvents(this, plugin); } public void markChunkAsClean(Chunk chunk) { try { Object nmsChunk = methodGetHandleChunk.invoke(chunk); if (mustSave != null) { - this.mustSave.set(nmsChunk, false); + this.mustSave.set(nmsChunk, isTrueForNotSave); } } catch (Throwable e) { e.printStackTrace(); @@ -101,8 +104,7 @@ public class SingleWorldListener implements Listener { int separator = 0; for (int i = 0; i < len; i++) { switch (worldName.charAt(i)) { - case ',': - case ';': + case '_': separator++; break; case '-': diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java index 65ea1e795..418b77c2d 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java @@ -32,6 +32,7 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.WorldCreator; import org.bukkit.WorldType; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -63,7 +64,7 @@ import java.util.List; } protected void setGenerator(@Nullable final String worldName, @Nullable final String generator) { - if (generator == null || worldName != null && worldName.contains(".")) { + if (generator == null) { return; } File file = new File("bukkit.yml").getAbsoluteFile(); diff --git a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java index 36fac50f3..6a92cbb90 100644 --- a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java @@ -37,6 +37,8 @@ import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.world.SinglePlot; +import com.plotsquared.core.plot.world.SinglePlotArea; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.PlotExpression; @@ -250,7 +252,12 @@ public class MainCommand extends Command { .equals(area) || Permissions.hasPermission(player, Permission.PERMISSION_ADMIN) || Permissions.hasPermission(player, Permission.PERMISSION_ADMIN_AREA_SUDO)) && !newPlot.isDenied(player.getUUID())) { - Location newLoc = newPlot.getCenterSynchronous(); + final Location newLoc; + if (newPlot.getArea() instanceof SinglePlotArea) { + newLoc = newPlot.isLoaded() ? newPlot.getCenterSynchronous() : Location.at("", 0, 0, 0); + } else { + newLoc = newPlot.getCenterSynchronous(); + } if (player.canTeleport(newLoc)) { // Save meta try (final MetaDataAccess locationMetaDataAccess diff --git a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java index 3a866a752..e9424db70 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -293,7 +293,7 @@ public class PlotListener { .sendTitle(TranslatableCaption.of("titles.title_entered_plot"), TranslatableCaption.of("titles.title_entered_plot_sub"), Templates.of("x", lastPlot.getId().getX()), Templates.of("z", lastPlot.getId().getY()), - Templates.of("world", Objects.requireNonNull(plot.getWorldName(), "Unknown")), + Templates.of("world", Objects.requireNonNull(plot.getArea().getId(), "Unknown")), Templates.of("greeting", greeting), Templates.of("alias", plot.getAlias()), Templates.of("owner", user)); UUID uuid = plot.getOwner(); diff --git a/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java b/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java index 041abadfb..cd3868a9b 100644 --- a/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java @@ -40,6 +40,7 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotWeather; import com.plotsquared.core.plot.world.PlotAreaManager; +import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.util.EventDispatcher; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.regions.CuboidRegion; @@ -78,7 +79,7 @@ public class ConsolePlayer extends PlotPlayer { area = null; } Location location; - if (area != null) { + if (area != null && !(plotAreaManager instanceof SinglePlotAreaManager)) { CuboidRegion region = area.getRegion(); location = Location.at(area.getWorldName(), region.getMinimumPoint().getX() + region.getMaximumPoint().getX() / 2, 0, diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index a71167a79..1455025ea 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -39,6 +39,7 @@ import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.events.Result; import com.plotsquared.core.events.TeleportCause; +import com.plotsquared.core.generator.HybridPlotWorld; import com.plotsquared.core.listener.PlotListener; import com.plotsquared.core.location.BlockLoc; import com.plotsquared.core.location.Direction; @@ -58,6 +59,8 @@ import com.plotsquared.core.plot.flag.implementations.KeepFlag; import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag; import com.plotsquared.core.plot.flag.types.DoubleFlag; import com.plotsquared.core.plot.schematic.Schematic; +import com.plotsquared.core.plot.world.SinglePlot; +import com.plotsquared.core.plot.world.SinglePlotManager; import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.MathMan; @@ -1285,10 +1288,6 @@ public class Plot { Location bot = corners[1]; Location location = Location.at(this.getWorldName(), MathMan.average(bot.getX(), top.getX()), MathMan.average(bot.getY(), top.getY()), MathMan.average(bot.getZ(), top.getZ())); - if (!isLoaded()) { - result.accept(location); - return; - } this.worldUtil.getHighestBlock(getWorldName(), location.getX(), location.getZ(), y -> { int height = y; if (area.allowSigns()) { @@ -1307,11 +1306,11 @@ public class Plot { Location[] corners = getCorners(); Location top = corners[0]; Location bot = corners[1]; + if (!isLoaded()) { + return Location.at("", 0, this.getArea() instanceof HybridPlotWorld ? ((HybridPlotWorld)this.getArea()).PLOT_HEIGHT + 1 : 4, 0); + } Location location = Location.at(this.getWorldName(), MathMan.average(bot.getX(), top.getX()), MathMan.average(bot.getY(), top.getY()), MathMan.average(bot.getZ(), top.getZ())); - if (!isLoaded()) { - return location; - } int y = this.worldUtil.getHighestBlockSynchronous(getWorldName(), location.getX(), location.getZ()); if (area.allowSigns()) { y = Math.max(y, getManager().getSignLoc(this).getY()); @@ -1369,12 +1368,12 @@ public class Plot { return this.getDefaultHomeSynchronous(true); } else { Location bottom = this.getBottomAbs(); + if (!isLoaded()) { + return Location.at("", 0, this.getArea() instanceof HybridPlotWorld ? ((HybridPlotWorld)this.getArea()).PLOT_HEIGHT + 1 : 4, 0); + } Location location = Location .at(bottom.getWorldName(), bottom.getX() + home.getX(), bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(), home.getPitch()); - if (!isLoaded()) { - return location; - } if (!this.worldUtil.getBlockSynchronous(location).getBlockType().getMaterial().isAir()) { location = location.withY( Math.max(1 + this.worldUtil.getHighestBlockSynchronous(this.getWorldName(), location.getX(), location.getZ()), bottom.getY())); @@ -1393,14 +1392,14 @@ public class Plot { if (home == null || home.getX() == 0 && home.getZ() == 0) { this.getDefaultHome(result); } else { + if (!isLoaded()) { + result.accept(Location.at("", 0, this.getArea() instanceof HybridPlotWorld ? ((HybridPlotWorld)this.getArea()).PLOT_HEIGHT + 1 : 4, 0)); + return; + } Location bottom = this.getBottomAbs(); Location location = Location .at(bottom.getWorldName(), bottom.getX() + home.getX(), bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(), home.getPitch()); - if (!isLoaded()) { - result.accept(location); - return; - } this.worldUtil.getBlock(location, block -> { if (!block.getBlockType().getMaterial().isAir()) { this.worldUtil.getHighestBlock(this.getWorldName(), location.getX(), location.getZ(), @@ -1473,6 +1472,10 @@ public class Plot { public void getDefaultHome(boolean member, Consumer result) { Plot plot = this.getBasePlot(false); + if (!isLoaded()) { + result.accept(Location.at("", 0, this.getArea() instanceof HybridPlotWorld ? ((HybridPlotWorld)this.getArea()).PLOT_HEIGHT + 1 : 4, 0)); + return; + } PlotLoc loc = member ? area.getDefaultHome() : area.getNonmemberHome(); if (loc != null) { int x; diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotId.java b/Core/src/main/java/com/plotsquared/core/plot/PlotId.java index df43526cd..71755ef50 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotId.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotId.java @@ -87,7 +87,7 @@ public final class PlotId { * @return Plot ID, or {@code null} if none could be parsed */ @Nullable public static PlotId fromStringOrNull(@Nonnull final String string) { - final String[] parts = string.split("[;,.]"); + final String[] parts = string.split("[;_,.]"); if (parts.length < 2) { return null; } @@ -221,6 +221,17 @@ public final class PlotId { return this.getX() + ";" + this.getY(); } + /** + * Get a String representation of the plot ID where the + * components are separated by a specified string + * + * @param separator Separator + * @return {@code x + separator + y} + */ + @Nonnull public String toSeparatedString(String separator) { + return this.getX() + separator + this.getY(); + } + /** * Get a String representation of the plot ID where the * components are separated by "," diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlot.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlot.java index 80f6dc2b8..32aeaa950 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlot.java @@ -60,7 +60,7 @@ public class SinglePlot extends Plot { } @Override public String getWorldName() { - return getId().getX() + "." + getId().getY(); + return getId().toSeparatedString("_"); } @Override public SinglePlotArea getArea() { diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java index b62b4582f..821674be9 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java @@ -87,7 +87,7 @@ public class SinglePlotArea extends GridPlotWorld { } public void loadWorld(final PlotId id) { - String worldName = id.getX() + "." + id.getY(); + String worldName = id.toSeparatedString("_"); if (PlotSquared.platform().worldUtil().isWorld(worldName)) { return; } @@ -106,12 +106,17 @@ public class SinglePlotArea extends GridPlotWorld { File oldFile = new File(container, id.toCommaSeparatedString()); if (oldFile.exists()) { oldFile.renameTo(destination); + } else { + oldFile = new File(container, id.toSeparatedString(".")); + if (oldFile.exists()) { + oldFile.renameTo(destination); + } } } // Duplicate 0;0 if (builder.plotAreaType() != PlotAreaType.NORMAL) { if (!destination.exists()) { - File src = new File(container, "0.0"); + File src = new File(container, "0_0"); if (src.exists()) { if (!destination.exists()) { destination.mkdirs(); @@ -140,7 +145,7 @@ public class SinglePlotArea extends GridPlotWorld { try { TaskManager.getPlatformImplementation().sync(() -> { - final String name = id.getX() + "." + id.getY(); + final String name = id.toSeparatedString("_"); if (!PlotSquared.platform().worldUtil().isWorld(name)) { PlotSquared.platform().setupUtils().setupWorld(builder); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotAreaManager.java index 686cf2f03..201f5b448 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotAreaManager.java @@ -85,7 +85,7 @@ import javax.inject.Inject; } case 1: if ((c <= '/') || (c >= ':')) { - if (c == '.') { + if (c == '_') { mode = 2; continue; } diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java index f0159f395..ba0a61c3e 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java @@ -57,11 +57,11 @@ public class SinglePlotManager extends PlotManager { } @Override public Location getPlotBottomLocAbs(@Nonnull final PlotId plotId) { - return Location.at(plotId.toCommaSeparatedString(), -30000000, 0, -30000000); + return Location.at(plotId.toSeparatedString("_"), -30000000, 0, -30000000); } @Override public Location getPlotTopLocAbs(@Nonnull final PlotId plotId) { - return Location.at(plotId.toCommaSeparatedString(), 30000000, 0, 30000000); + return Location.at(plotId.toSeparatedString("_"), 30000000, 0, 30000000); } @Override public boolean clearPlot(@Nonnull Plot plot, final Runnable whenDone, @Nullable PlotPlayer actor, @Nullable QueueCoordinator queue) {