diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java index f29a4f0ee..e686c9c3f 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java @@ -20,6 +20,7 @@ import com.github.intellectualsites.plotsquared.bukkit.util.BukkitTaskManager; import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil; import com.github.intellectualsites.plotsquared.bukkit.util.Metrics; import com.github.intellectualsites.plotsquared.bukkit.util.SetGenCB; +import com.github.intellectualsites.plotsquared.bukkit.util.UpdateUtility; import com.github.intellectualsites.plotsquared.bukkit.util.block.BukkitLocalQueue; import com.github.intellectualsites.plotsquared.bukkit.uuid.DefaultUUIDWrapper; import com.github.intellectualsites.plotsquared.bukkit.uuid.FileUUIDHandler; @@ -37,10 +38,9 @@ import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper; import com.github.intellectualsites.plotsquared.plot.generator.HybridGen; import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils; import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator; +import com.github.intellectualsites.plotsquared.plot.listener.PlotListener; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotArea; -import com.github.intellectualsites.plotsquared.plot.object.PlotAreaTerrainType; -import com.github.intellectualsites.plotsquared.plot.object.PlotAreaType; import com.github.intellectualsites.plotsquared.plot.object.PlotId; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.SetupObject; @@ -49,8 +49,21 @@ import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManag import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager; import com.github.intellectualsites.plotsquared.plot.object.worlds.SingleWorldGenerator; -import com.github.intellectualsites.plotsquared.plot.util.*; -import com.github.intellectualsites.plotsquared.bukkit.util.UpdateUtility; +import com.github.intellectualsites.plotsquared.plot.util.ChatManager; +import com.github.intellectualsites.plotsquared.plot.util.ChunkManager; +import com.github.intellectualsites.plotsquared.plot.util.ConsoleColors; +import com.github.intellectualsites.plotsquared.plot.util.EconHandler; +import com.github.intellectualsites.plotsquared.plot.util.InventoryUtil; +import com.github.intellectualsites.plotsquared.plot.util.MainUtil; +import com.github.intellectualsites.plotsquared.plot.util.PremiumVerification; +import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils; +import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler; +import com.github.intellectualsites.plotsquared.plot.util.SetupUtils; +import com.github.intellectualsites.plotsquared.plot.util.StringMan; +import com.github.intellectualsites.plotsquared.plot.util.TaskManager; +import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler; +import com.github.intellectualsites.plotsquared.plot.util.UUIDHandlerImplementation; +import com.github.intellectualsites.plotsquared.plot.util.WorldUtil; import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider; import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper; import com.sk89q.worldedit.WorldEdit; @@ -586,6 +599,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain final PlayerEvents main = new PlayerEvents(); getServer().getPluginManager().registerEvents(main, this); getServer().getPluginManager().registerEvents(new EntitySpawnListener(), this); + PlotListener.startRunnable(); } @Override public void registerForceFieldEvents() { diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/generator/BukkitAugmentedGenerator.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/generator/BukkitAugmentedGenerator.java index 03b0c8123..63f0a5054 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/generator/BukkitAugmentedGenerator.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/generator/BukkitAugmentedGenerator.java @@ -27,6 +27,6 @@ public class BukkitAugmentedGenerator extends BlockPopulator { @Override public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) { - AugmentedUtils.generate(world.getName(), source.getX(), source.getZ(), null); + AugmentedUtils.generate(source, world.getName(), source.getX(), source.getZ(), null); } } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java index bf4fc32eb..6d481d955 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java @@ -776,7 +776,7 @@ public class PlayerEvents extends PlotListener implements Listener { // to is identical to the plot's home location, and untrusted-visit is true // i.e. untrusted-visit can override deny-teleport // this is acceptable, because otherwise it wouldn't make sense to have both flags set - if (!result && !(plot.getFlag(UntrustedVisitFlag.class) && plot.getHome() + if (!result && !(plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous() .equals(BukkitUtil.getLocationFull(to)))) { MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, Captions.PERMISSION_ADMIN_ENTRY_DENIED); @@ -2353,6 +2353,7 @@ public class PlayerEvents extends PlotListener implements Listener { TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName()); PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); pp.unregister(); + PlotListener.logout(pp.getUUID()); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/placeholders/Placeholders.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/placeholders/Placeholders.java index d9436ed7f..d8608463f 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/placeholders/Placeholders.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/placeholders/Placeholders.java @@ -162,7 +162,7 @@ public class Placeholders extends PlaceholderExpansion { if (pl.getCurrentPlot() == null) { return ""; } - return plot.getBiome() + ""; + return plot.getBiomeSynchronous() + ""; } default: break; diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java index 93a381fe4..83ee0aaf3 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java @@ -1,5 +1,6 @@ package com.github.intellectualsites.plotsquared.bukkit.util; +import com.github.intellectualsites.plotsquared.bukkit.BukkitMain; import com.github.intellectualsites.plotsquared.bukkit.object.entity.EntityWrapper; import com.github.intellectualsites.plotsquared.bukkit.object.entity.ReplicatingEntityWrapper; import com.github.intellectualsites.plotsquared.plot.PlotSquared; @@ -43,6 +44,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Semaphore; import static com.google.common.base.Preconditions.checkNotNull; @@ -114,9 +116,28 @@ public class BukkitChunkManager extends ChunkManager { @Override public Set getChunkChunks(String world) { Set chunks = super.getChunkChunks(world); - for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) { - BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5); - chunks.add(loc); + if (Bukkit.isPrimaryThread()) { + for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) { + BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5); + chunks.add(loc); + } + } else { + final Semaphore semaphore = new Semaphore(1); + try { + PlotSquared.debug("Attempting to make an asynchronous call to getLoadedChunks." + + " Will halt the calling thread until completed."); + semaphore.acquire(); + Bukkit.getScheduler().runTask(BukkitMain.getPlugin(BukkitMain.class), () -> { + for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) { + BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5); + chunks.add(loc); + } + semaphore.release(); + }); + semaphore.acquireUninterruptibly(); + } catch (final Exception e) { + e.printStackTrace(); + } } return chunks; } @@ -285,111 +306,112 @@ public class BukkitChunkManager extends ChunkManager { int zzb = z << 4; int xxt = xxb + 15; int zzt = zzb + 15; - Chunk chunkObj = worldObj.getChunkAt(x, z); - if (!chunkObj.load(false)) { - continue; - } - final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false); - if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { + PaperLib.getChunkAtAsync(worldObj, x, z, false).thenAccept(chunkObj -> { + if (chunkObj == null) { + return; + } + final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false); + if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { + AugmentedUtils.bypass(ignoreAugment, + () -> queue.regenChunkSafe(chunk.getX(), chunk.getZ())); + return; + } + boolean checkX1 = false; + + int xxb2; + + if (x == bcx) { + xxb2 = p1x - 1; + checkX1 = true; + } else { + xxb2 = xxb; + } + boolean checkX2 = false; + int xxt2; + if (x == tcx) { + xxt2 = p2x + 1; + checkX2 = true; + } else { + xxt2 = xxt; + } + boolean checkZ1 = false; + int zzb2; + if (z == bcz) { + zzb2 = p1z - 1; + checkZ1 = true; + } else { + zzb2 = zzb; + } + boolean checkZ2 = false; + int zzt2; + if (z == tcz) { + zzt2 = p2z + 1; + checkZ2 = true; + } else { + zzt2 = zzt; + } + final ContentMap map = new ContentMap(); + if (checkX1) { + map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); // + } + if (checkX2) { + map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); // + } + if (checkZ1) { + map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); // + } + if (checkZ2) { + map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); // + } + if (checkX1 && checkZ1) { + map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); // + } + if (checkX2 && checkZ1) { + map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ? + } + if (checkX1 && checkZ2) { + map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ? + } + if (checkX2 && checkZ2) { + map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); // + } + CuboidRegion currentPlotClear = + RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); + map.saveEntitiesOut(chunkObj, currentPlotClear); AugmentedUtils.bypass(ignoreAugment, - () -> queue.regenChunkSafe(chunk.getX(), chunk.getZ())); - continue; - } - boolean checkX1 = false; - - int xxb2; - - if (x == bcx) { - xxb2 = p1x - 1; - checkX1 = true; - } else { - xxb2 = xxb; - } - boolean checkX2 = false; - int xxt2; - if (x == tcx) { - xxt2 = p2x + 1; - checkX2 = true; - } else { - xxt2 = xxt; - } - boolean checkZ1 = false; - int zzb2; - if (z == bcz) { - zzb2 = p1z - 1; - checkZ1 = true; - } else { - zzb2 = zzb; - } - boolean checkZ2 = false; - int zzt2; - if (z == tcz) { - zzt2 = p2z + 1; - checkZ2 = true; - } else { - zzt2 = zzt; - } - final ContentMap map = new ContentMap(); - if (checkX1) { - map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); // - } - if (checkX2) { - map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); // - } - if (checkZ1) { - map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); // - } - if (checkZ2) { - map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); // - } - if (checkX1 && checkZ1) { - map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); // - } - if (checkX2 && checkZ1) { - map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ? - } - if (checkX1 && checkZ2) { - map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ? - } - if (checkX2 && checkZ2) { - map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); // - } - CuboidRegion currentPlotClear = - RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); - map.saveEntitiesOut(chunkObj, currentPlotClear); - AugmentedUtils.bypass(ignoreAugment, - () -> setChunkInPlotArea(null, new RunnableVal() { - @Override public void run(ScopedLocalBlockQueue value) { - Location min = value.getMin(); - int bx = min.getX(); - int bz = min.getZ(); - for (int x1 = 0; x1 < 16; x1++) { - for (int z1 = 0; z1 < 16; z1++) { - PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1); - BaseBlock[] ids = map.allBlocks.get(plotLoc); - if (ids != null) { - for (int y = 0; y < Math.min(128, ids.length); y++) { - BaseBlock id = ids[y]; - if (id != null) { - value.setBlock(x1, y, z1, id); - } else { - value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState()); + () -> setChunkInPlotArea(null, new RunnableVal() { + @Override public void run(ScopedLocalBlockQueue value) { + Location min = value.getMin(); + int bx = min.getX(); + int bz = min.getZ(); + for (int x1 = 0; x1 < 16; x1++) { + for (int z1 = 0; z1 < 16; z1++) { + PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1); + BaseBlock[] ids = map.allBlocks.get(plotLoc); + if (ids != null) { + for (int y = 0; y < Math.min(128, ids.length); y++) { + BaseBlock id = ids[y]; + if (id != null) { + value.setBlock(x1, y, z1, id); + } else { + value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState()); + } } - } - for (int y = Math.min(128, ids.length); - y < ids.length; y++) { - BaseBlock id = ids[y]; - if (id != null) { - value.setBlock(x1, y, z1, id); + for (int y = Math.min(128, ids.length); + y < ids.length; y++) { + BaseBlock id = ids[y]; + if (id != null) { + value.setBlock(x1, y, z1, id); + } } } } } } - } - }, world, chunk)); - //map.restoreBlocks(worldObj, 0, 0); - map.restoreEntities(worldObj, 0, 0); + }, world, chunk)); + //map.restoreBlocks(worldObj, 0, 0); + map.restoreEntities(worldObj, 0, 0); + }); } if (!chunks.isEmpty()) { TaskManager.runTaskLater(this, 1); diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitUtil.java index bd77facdb..87fc5c92b 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitUtil.java @@ -1,5 +1,6 @@ package com.github.intellectualsites.plotsquared.bukkit.util; +import com.github.intellectualsites.plotsquared.bukkit.BukkitMain; import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer; import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.config.Captions; @@ -7,7 +8,6 @@ import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; -import com.github.intellectualsites.plotsquared.plot.object.schematic.PlotItem; import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import com.github.intellectualsites.plotsquared.plot.util.MathMan; import com.github.intellectualsites.plotsquared.plot.util.StringComparison; @@ -20,8 +20,10 @@ import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockState; +import io.papermc.lib.PaperLib; import lombok.NonNull; import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.World; @@ -33,18 +35,17 @@ import org.bukkit.block.data.Directional; import org.bukkit.block.data.type.WallSign; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashSet; -import java.util.UUID; import java.util.List; import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.IntConsumer; @SuppressWarnings({"unused", "WeakerAccess"}) @@ -104,17 +105,6 @@ public class BukkitUtil extends WorldUtil { return getPlot(player.getLocation()); } - /** - * Get home location. - * - * @param plot Plot that you want to get the location for - * @return plot bottom location - * @see Plot - */ - public static org.bukkit.Location getHomeLocation(Plot plot) { - return BukkitUtil.getLocation(plot.getHome()); - } - /** * Get the PlotPlayer for an offline player. * @@ -219,7 +209,6 @@ public class BukkitUtil extends WorldUtil { * * @param player the recipient of the message * @param caption the message - * @see MainUtil#sendMessage(com.github.intellectualsites.plotsquared.commands.CommandCaller, Captions, String...) */ public static void sendMessage(Player player, Captions caption) { MainUtil.sendMessage(BukkitUtil.getPlayer(player), caption); @@ -303,11 +292,43 @@ public class BukkitUtil extends WorldUtil { return getWorld(worldName) != null; } - @Override public BiomeType getBiome(String world, int x, int z) { + @Override public void getBiome(String world, int x, int z, final Consumer result) { + ensureLoaded(world, x, z, chunk -> + result.accept(BukkitAdapter.adapt(getWorld(world).getBiome(x, z)))); + } + + @Override public BiomeType getBiomeSynchronous(String world, int x, int z) { return BukkitAdapter.adapt(getWorld(world).getBiome(x, z)); } - @Override public int getHighestBlock(@NonNull final String world, final int x, final int z) { + @Override public void getHighestBlock(@NonNull final String world, final int x, final int z, + final IntConsumer result) { + ensureLoaded(world, x, z, chunk -> { + final World bukkitWorld = getWorld(world); + // Skip top and bottom block + int air = 1; + for (int y = bukkitWorld.getMaxHeight() - 1; y >= 0; y--) { + Block block = bukkitWorld.getBlockAt(x, y, z); + Material type = block.getType(); + if (type.isSolid()) { + if (air > 1) { + result.accept(y); + return; + } + air = 0; + } else { + if (block.isLiquid()) { + result.accept(y); + return; + } + air++; + } + } + result.accept(bukkitWorld.getMaxHeight() - 1); + }); + } + + @Override public int getHighestBlockSynchronous(String world, int x, int z) { final World bukkitWorld = getWorld(world); // Skip top and bottom block int air = 1; @@ -329,7 +350,17 @@ public class BukkitUtil extends WorldUtil { return bukkitWorld.getMaxHeight() - 1; } - @Override @Nullable public String[] getSign(@NonNull final Location location) { + @Override public void getSign(@NonNull final Location location, final Consumer result) { + ensureLoaded(location, chunk -> { + final Block block = chunk.getWorld().getBlockAt(getLocation(location)); + if (block.getState() instanceof Sign) { + Sign sign = (Sign) block.getState(); + result.accept(sign.getLines()); + } + }); + } + + @Override @Nullable public String[] getSignSynchronous(@NonNull final Location location) { Block block = getWorld(location.getWorld()) .getBlockAt(location.getX(), location.getY(), location.getZ()); return TaskManager.IMP.sync(new RunnableVal() { @@ -365,60 +396,42 @@ public class BukkitUtil extends WorldUtil { @Override @SuppressWarnings("deprecation") public void setSign(@NonNull final String worldName, final int x, final int y, final int z, @NonNull final String[] lines) { - final World world = getWorld(worldName); - final Block block = world.getBlockAt(x, y, z); - // block.setType(Material.AIR); - final Material type = block.getType(); - if (type != Material.LEGACY_SIGN && type != Material.LEGACY_WALL_SIGN) { - BlockFace facing = BlockFace.EAST; - if (world.getBlockAt(x, y, z + 1).getType().isSolid()) { - facing = BlockFace.NORTH; - } else if (world.getBlockAt(x + 1, y, z).getType().isSolid()) { - facing = BlockFace.WEST; - } else if (world.getBlockAt(x, y, z - 1).getType().isSolid()) { - facing = BlockFace.SOUTH; + ensureLoaded(worldName, x, z, chunk -> { + final World world = getWorld(worldName); + final Block block = world.getBlockAt(x, y, z); + // block.setType(Material.AIR); + final Material type = block.getType(); + if (type != Material.LEGACY_SIGN && type != Material.LEGACY_WALL_SIGN) { + BlockFace facing = BlockFace.EAST; + if (world.getBlockAt(x, y, z + 1).getType().isSolid()) { + facing = BlockFace.NORTH; + } else if (world.getBlockAt(x + 1, y, z).getType().isSolid()) { + facing = BlockFace.WEST; + } else if (world.getBlockAt(x, y, z - 1).getType().isSolid()) { + facing = BlockFace.SOUTH; + } + if (PlotSquared.get().IMP.getServerVersion()[1] == 13) { + block.setType(Material.valueOf("WALL_SIGN"), false); + } else { + block.setType(Material.valueOf("OAK_WALL_SIGN"), false); + } + if (!(block.getBlockData() instanceof WallSign)) { + PlotSquared.debug(block.getBlockData().getAsString()); + throw new RuntimeException("Something went wrong generating a sign"); + } + final Directional sign = (Directional) block.getBlockData(); + sign.setFacing(facing); + block.setBlockData(sign, false); } - if (PlotSquared.get().IMP.getServerVersion()[1] == 13) { - block.setType(Material.valueOf("WALL_SIGN"), false); - } else { - block.setType(Material.valueOf("OAK_WALL_SIGN"), false); + final org.bukkit.block.BlockState blockstate = block.getState(); + if (blockstate instanceof Sign) { + final Sign sign = (Sign) blockstate; + for (int i = 0; i < lines.length; i++) { + sign.setLine(i, lines[i]); + } + sign.update(true); } - if (!(block.getBlockData() instanceof WallSign)) { - PlotSquared.debug(block.getBlockData().getAsString()); - throw new RuntimeException("Something went wrong generating a sign"); - } - final Directional sign = (Directional) block.getBlockData(); - sign.setFacing(facing); - block.setBlockData(sign, false); - } - final org.bukkit.block.BlockState blockstate = block.getState(); - if (blockstate instanceof Sign) { - final Sign sign = (Sign) blockstate; - for (int i = 0; i < lines.length; i++) { - sign.setLine(i, lines[i]); - } - sign.update(true); - } - } - - @Override - public boolean addItems(@NonNull final String worldName, @NonNull final PlotItem items) { - final World world = getWorld(worldName); - final Block block = world.getBlockAt(items.x, items.y, items.z); - final org.bukkit.block.BlockState state = block.getState(); - if (state instanceof InventoryHolder) { - InventoryHolder holder = (InventoryHolder) state; - Inventory inv = holder.getInventory(); - for (int i = 0; i < items.types.length; i++) { - // ItemStack item = new ItemStack(LegacyMappings.fromLegacyId(items.id[i]).getMaterial(), items.amount[i], items.data[i]); - ItemStack item = - new ItemStack(BukkitAdapter.adapt(items.types[i]), items.amount[i]); - inv.addItem(item); - } - state.update(true); - return true; - } - return false; + }); } @Override public boolean isBlockSolid(@NonNull final BlockState block) { @@ -471,7 +484,15 @@ public class BukkitUtil extends WorldUtil { return new BukkitWorld(Bukkit.getWorld(world)); } - @Override public BlockState getBlock(@NonNull final Location location) { + @Override public void getBlock(@NonNull final Location location, final Consumer result) { + ensureLoaded(location, chunk -> { + final World world = getWorld(location.getWorld()); + final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ()); + result.accept(BukkitAdapter.asBlockType(block.getType()).getDefaultState()); + }); + } + + @Override public BlockState getBlockSynchronous(@NonNull final Location location) { final World world = getWorld(location.getWorld()); final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ()); return BukkitAdapter.asBlockType(block.getType()).getDefaultState(); @@ -496,4 +517,24 @@ public class BukkitUtil extends WorldUtil { @Override public void setFoodLevel(PlotPlayer player, int foodLevel) { Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel); } + + private static void ensureLoaded(final String world, final int x, final int z, final Consumer chunkConsumer) { + PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true).thenAccept(chunk -> + ensureMainThread(chunkConsumer, chunk)); + } + + private static void ensureLoaded(final Location location, final Consumer chunkConsumer) { + PaperLib.getChunkAtAsync(getLocation(location), true).thenAccept(chunk -> + ensureMainThread(chunkConsumer, chunk)); + } + + private static void ensureMainThread(final Consumer consumer, final T value) { + if (Bukkit.isPrimaryThread()) { + consumer.accept(value); + } else { + Bukkit.getScheduler().runTask(BukkitMain.getPlugin(BukkitMain.class), () -> + consumer.accept(value)); + } + } + } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/OfflinePlayerUtil.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/OfflinePlayerUtil.java index a4ee94f80..dd7edf83f 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/OfflinePlayerUtil.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/OfflinePlayerUtil.java @@ -12,9 +12,11 @@ import java.util.UUID; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.callConstructor; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.callMethod; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getCbClass; +import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getField; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getNmsClass; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getUtilClass; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeConstructor; +import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeField; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeMethod; public class OfflinePlayerUtil { @@ -67,11 +69,26 @@ public class OfflinePlayerUtil { return callConstructor(c, worldServer); } + public static Object getWorldServerNew() { + Object server = getMinecraftServer(); + Class minecraftServerClass = getNmsClass("MinecraftServer"); + Class dimensionManager = getNmsClass("DimensionManager"); + Object overworld = getField(makeField(dimensionManager, "OVERWORLD"), null); + Method getWorldServer = makeMethod(minecraftServerClass, "getWorldServer", dimensionManager); + return callMethod(getWorldServer, server, overworld); + } + private static Object getWorldServer() { Object server = getMinecraftServer(); Class minecraftServerClass = getNmsClass("MinecraftServer"); Method getWorldServer = makeMethod(minecraftServerClass, "getWorldServer", int.class); - return callMethod(getWorldServer, server, 0); + Object o; + try { + o = callMethod(getWorldServer, server, 0); + } catch (final RuntimeException e) { + o = getWorldServerNew(); + } + return o; } //NMS Utils diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java index 663d6144b..d27dce58d 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java @@ -18,6 +18,7 @@ import com.sk89q.worldedit.world.block.BlockState; import io.papermc.lib.PaperLib; import lombok.NonNull; import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Biome; @@ -25,6 +26,7 @@ import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; public class BukkitLocalQueue extends BasicLocalBlockQueue { @@ -88,7 +90,7 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { @Override public final void setComponents(LocalChunk lc) throws ExecutionException, InterruptedException { setBaseBlocks(lc); - if (setBiome()) { + if (setBiome() && lc.biomes != null) { setBiomes(lc); } } @@ -98,40 +100,59 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { if (worldObj == null) { throw new NullPointerException("World cannot be null."); } - PaperLib.getChunkAtAsync(worldObj, localChunk.getX(), localChunk.getZ(), true) - .thenAccept(chunk -> { - for (int layer = 0; layer < localChunk.baseblocks.length; layer++) { - BaseBlock[] blocksLayer = localChunk.baseblocks[layer]; - if (blocksLayer != null) { - for (int j = 0; j < blocksLayer.length; j++) { - if (blocksLayer[j] != null) { - BaseBlock block = blocksLayer[j]; - int x = MainUtil.x_loc[layer][j]; - int y = MainUtil.y_loc[layer][j]; - int z = MainUtil.z_loc[layer][j]; + final Consumer chunkConsumer = chunk -> { + for (int layer = 0; layer < localChunk.baseblocks.length; layer++) { + BaseBlock[] blocksLayer = localChunk.baseblocks[layer]; + if (blocksLayer != null) { + for (int j = 0; j < blocksLayer.length; j++) { + if (blocksLayer[j] != null) { + BaseBlock block = blocksLayer[j]; + int x = MainUtil.x_loc[layer][j]; + int y = MainUtil.y_loc[layer][j]; + int z = MainUtil.z_loc[layer][j]; - BlockData blockData = BukkitAdapter.adapt(block); + BlockData blockData = BukkitAdapter.adapt(block); - Block existing = chunk.getBlock(x, y, z); - if (BukkitBlockUtil.get(existing).equals(block) && existing - .getBlockData().matches(blockData)) { - continue; - } + Block existing = chunk.getBlock(x, y, z); + final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData()); + if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing + .getBlockData().matches(blockData)) { + continue; + } - existing.setType(BukkitAdapter.adapt(block.getBlockType()), false); - existing.setBlockData(blockData, false); - if (block.hasNbtData()) { - CompoundTag tag = block.getNbtData(); - StateWrapper sw = new StateWrapper(tag); + existing.setType(BukkitAdapter.adapt(block.getBlockType()), false); + existing.setBlockData(blockData, false); + if (block.hasNbtData()) { + CompoundTag tag = block.getNbtData(); + StateWrapper sw = new StateWrapper(tag); - sw.restoreTag(worldObj.getName(), existing.getX(), - existing.getY(), existing.getZ()); - } + sw.restoreTag(worldObj.getName(), existing.getX(), + existing.getY(), existing.getZ()); } } } } - }); + } + }; + if (isForceSync()) { + chunkConsumer.accept(getChunk(worldObj, localChunk)); + } else { + PaperLib.getChunkAtAsync(worldObj, localChunk.getX(), localChunk.getZ(), true).thenAccept(chunkConsumer); + } + } + + private Chunk getChunk(final World world, final LocalChunk localChunk) { + Chunk chunk = null; + if (this.getChunkObject() != null && this.getChunkObject() instanceof Chunk) { + chunk = (Chunk) this.getChunkObject(); + } + if (chunk == null) { + chunk = world.getChunkAt(localChunk.getX(), localChunk.getZ()); + } + if (!chunk.isLoaded()) { + chunk.load(true); + } + return chunk; } private void setMaterial(@NonNull final BlockState plotBlock, @NonNull final Block block) { @@ -148,7 +169,10 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { if (worldObj == null) { throw new NullPointerException("World cannot be null."); } - PaperLib.getChunkAtAsync(worldObj, lc.getX(), lc.getZ(), true).thenAccept(chunk -> { + if (lc.biomes == null) { + throw new NullPointerException("Biomes cannot be null."); + } + final Consumer chunkConsumer = chunk -> { for (int x = 0; x < lc.biomes.length; x++) { BiomeType[] biomeZ = lc.biomes[x]; if (biomeZ != null) { @@ -157,13 +181,18 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { BiomeType biomeType = biomeZ[z]; Biome biome = BukkitAdapter.adapt(biomeType); - worldObj - .setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, biome); + worldObj.setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, + biome); } } } } - }); + }; + if (this.isForceSync()) { + chunkConsumer.accept(getChunk(worldObj, lc)); + } else { + PaperLib.getChunkAtAsync(worldObj, lc.getX(), lc.getZ(), true).thenAccept(chunkConsumer); + } } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java index 92e7b9de6..e00faa4b6 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java @@ -147,7 +147,7 @@ public class Area extends SubCommand { ChunkManager.largeRegionTask(world, region, new RunnableVal() { @Override public void run(BlockVector2 value) { - AugmentedUtils.generate(world, value.getX(), + AugmentedUtils.generate(null, world, value.getX(), value.getZ(), null); } }, null); @@ -445,7 +445,7 @@ public class Area extends SubCommand { new RunnableVal() { @Override public void run(BlockVector2 value) { AugmentedUtils - .generate(area.getWorldName(), value.getX(), value.getZ(), null); + .generate(null, area.getWorldName(), value.getX(), value.getZ(), null); } }, () -> player.sendMessage("Regen complete")); return true; @@ -471,16 +471,18 @@ public class Area extends SubCommand { Location center; if (area.getType() != PlotAreaType.PARTIAL) { center = WorldUtil.IMP.getSpawn(area.getWorldName()); + player.teleport(center, TeleportCause.COMMAND); } else { CuboidRegion region = area.getRegion(); center = new Location(area.getWorldName(), region.getMinimumPoint().getX() + (region.getMaximumPoint().getX() - region.getMinimumPoint().getX()) / 2, 0, region.getMinimumPoint().getZ() + (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ()) / 2); - center.setY(1 + WorldUtil.IMP - .getHighestBlock(area.getWorldName(), center.getX(), center.getZ())); + WorldUtil.IMP.getHighestBlock(area.getWorldName(), center.getX(), center.getZ(), y -> { + center.setY(1 + y); + player.teleport(center, TeleportCause.COMMAND); + }); } - player.teleport(center, TeleportCause.COMMAND); return true; case "delete": case "remove": diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Auto.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Auto.java index 1d9709e7a..a04540168 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Auto.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Auto.java @@ -8,9 +8,7 @@ import com.github.intellectualsites.plotsquared.plot.config.Settings; import com.github.intellectualsites.plotsquared.plot.database.DBFunc; import com.github.intellectualsites.plotsquared.plot.events.PlayerAutoPlotEvent; import com.github.intellectualsites.plotsquared.plot.events.PlotAutoMergeEvent; -import com.github.intellectualsites.plotsquared.plot.events.PlotMergeEvent; import com.github.intellectualsites.plotsquared.plot.events.Result; -import com.github.intellectualsites.plotsquared.plot.object.Direction; import com.github.intellectualsites.plotsquared.plot.object.Expression; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotArea; @@ -19,6 +17,7 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotId; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; import com.github.intellectualsites.plotsquared.plot.object.TeleportCause; +import com.github.intellectualsites.plotsquared.plot.util.AutoClaimFinishTask; import com.github.intellectualsites.plotsquared.plot.util.EconHandler; import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import com.github.intellectualsites.plotsquared.plot.util.Permissions; @@ -42,7 +41,7 @@ public class Auto extends SubCommand { return id.getNextId(step); } - private static boolean checkAllowedPlots(PlotPlayer player, PlotArea plotarea, + public static boolean checkAllowedPlots(PlotPlayer player, PlotArea plotarea, @Nullable Integer allowedPlots, int sizeX, int sizeZ) { if (allowedPlots == null) { allowedPlots = player.getAllowedPlots(); @@ -94,7 +93,7 @@ public class Auto extends SubCommand { final String schematic) { Set plots = player.getPlots(); if (!plots.isEmpty()) { - plots.iterator().next().teleportPlayer(player, TeleportCause.COMMAND); + plots.iterator().next().teleportPlayer(player, TeleportCause.COMMAND, result -> {}); } else { autoClaimSafe(player, area, start, schematic); } @@ -126,31 +125,7 @@ public class Auto extends SubCommand { player.setMeta(Auto.class.getName(), true); autoClaimFromDatabase(player, area, start, new RunnableVal() { @Override public void run(final Plot plot) { - TaskManager.IMP.sync(new RunnableVal() { - @Override public void run(Object ignore) { - player.deleteMeta(Auto.class.getName()); - if (plot == null) { - MainUtil.sendMessage(player, Captions.NO_FREE_PLOTS); - return; - } - - if (checkAllowedPlots(player, area, allowedPlots, 1, 1)) { - plot.claim(player, true, schematic, false); - if (area.isAutoMerge()) { - PlotMergeEvent event = PlotSquared.get().getEventDispatcher() - .callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player); - if (event.getEventResult() == Result.DENY) { - sendMessage(player, Captions.EVENT_DENIED, "Auto merge"); - } else { - plot.autoMerge(event.getDir(), event.getMax(), player.getUUID(), - true); - } - } - } else { - DBFunc.delete(plot); - } - } - }); + TaskManager.IMP.sync(new AutoClaimFinishTask(player, plot, area, allowedPlots, schematic)); } }); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java index 2a5aa6a66..8c79e3515 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java @@ -555,7 +555,7 @@ public class Cluster extends SubCommand { return false; } } - player.teleport(cluster.getHome(), TeleportCause.COMMAND); + cluster.getHome(home -> player.teleport(home, TeleportCause.COMMAND)); return MainUtil.sendMessage(player, Captions.CLUSTER_TELEPORTING); } case "i": diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Debug.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Debug.java index ad1fc6d2e..339d33c5c 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Debug.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Debug.java @@ -4,8 +4,10 @@ import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; +import com.github.intellectualsites.plotsquared.plot.util.ChunkManager; import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import com.github.intellectualsites.plotsquared.plot.util.StringMan; +import com.github.intellectualsites.plotsquared.plot.util.TaskManager; import java.util.Map; @@ -23,9 +25,16 @@ public class Debug extends SubCommand { MainUtil.sendMessage(player, "Key: " + meta.getKey() + " Value: " + meta.getValue().toString() + " , "); } - ; } } + if (args.length > 0 && "loadedchunks".equalsIgnoreCase(args[0])) { + final long start = System.currentTimeMillis(); + MainUtil.sendMessage(player, "Fetching loaded chunks..."); + TaskManager.runTaskAsync(() -> MainUtil.sendMessage(player,"Loaded chunks: " + + ChunkManager.manager.getChunkChunks(player.getLocation().getWorld()).size() + "(" + (System.currentTimeMillis() - start) + "ms) using thread: " + + Thread.currentThread().getName())); + return true; + } if ((args.length > 0) && args[0].equalsIgnoreCase("msg")) { StringBuilder msg = new StringBuilder(); for (Captions caption : Captions.values()) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugClaimTest.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugClaimTest.java index e1585a399..1331255f7 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugClaimTest.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugClaimTest.java @@ -71,7 +71,7 @@ public class DebugClaimTest extends SubCommand { Location location = manager.getSignLoc(plot); BlockVector2 chunk = BlockVector2.at(location.getX() >> 4, location.getZ() >> 4); ChunkManager.manager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> { - String[] lines = WorldUtil.IMP.getSign(location); + String[] lines = WorldUtil.IMP.getSignSynchronous(location); if (lines != null) { String line = lines[2]; if (line != null && line.length() > 2) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Like.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Like.java index e1751696e..b3af59f13 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Like.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Like.java @@ -47,7 +47,7 @@ public class Like extends SubCommand { for (final Plot plot : plots) { if ((!Settings.Done.REQUIRED_FOR_RATINGS || DoneFlag.isDone(plot)) && plot .isBasePlot() && (!plot.getLikes().containsKey(uuid))) { - plot.teleportPlayer(player, TeleportCause.COMMAND); + plot.teleportPlayer(player, TeleportCause.COMMAND, result -> {}); MainUtil.sendMessage(player, Captions.RATE_THIS); return true; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java index 1727d6890..9727303ef 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java @@ -208,7 +208,7 @@ public class MainCommand extends Command { .equals(area) || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN) || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_SUDO_AREA)) && !newPlot.isDenied(player.getUUID())) { - Location newLoc = newPlot.getCenter(); + Location newLoc = newPlot.getCenterSynchronous(); if (player.canTeleport(newLoc)) { // Save meta location = player.getMeta(PlotPlayer.META_LOCATION); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Middle.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Middle.java index 9cc828f21..83b8236ed 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Middle.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Middle.java @@ -24,7 +24,7 @@ public class Middle extends SubCommand { if (plot == null) { return sendMessage(player, Captions.NOT_IN_PLOT); } - player.teleport(plot.getCenter(), TeleportCause.COMMAND); + plot.getCenter(center -> player.teleport(center, TeleportCause.COMMAND)); return true; } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java index 88f455e7d..43c89f8ab 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java @@ -61,7 +61,7 @@ public class Rate extends SubCommand { if ((!Settings.Done.REQUIRED_FOR_RATINGS || DoneFlag.isDone(p)) && p .isBasePlot() && (!p.getRatings().containsKey(uuid)) && !p .isAdded(uuid)) { - p.teleportPlayer(player, TeleportCause.COMMAND); + p.teleportPlayer(player, TeleportCause.COMMAND, result -> {}); MainUtil.sendMessage(player, Captions.RATE_THIS); return true; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Target.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Target.java index 6d9f618e2..7a449f7f1 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Target.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Target.java @@ -32,7 +32,7 @@ public class Target extends SubCommand { if (StringMan.isEqualIgnoreCaseToAny(args[0], "near", "nearest")) { int distance = Integer.MAX_VALUE; for (Plot plot : PlotSquared.get().getPlots(location.getWorld())) { - double current = plot.getCenter().getEuclideanDistanceSquared(location); + double current = plot.getCenterSynchronous().getEuclideanDistanceSquared(location); if (current < distance) { distance = (int) current; target = plot; @@ -45,7 +45,7 @@ public class Target extends SubCommand { } else if ((target = MainUtil.getPlotFromString(player, args[0], true)) == null) { return false; } - player.setCompassTarget(target.getCenter()); + target.getCenter(player::setCompassTarget); MainUtil.sendMessage(player, Captions.COMPASS_TARGET); return true; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Visit.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Visit.java index f9057307a..8916bf9b1 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Visit.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Visit.java @@ -153,13 +153,14 @@ public class Visit extends Command { return CompletableFuture.completedFuture(false); } } - confirm.run(this, () -> { - if (plot.teleportPlayer(player, TeleportCause.COMMAND)) { + confirm.run(this, () -> + plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { + if (result) { whenDone.run(Visit.this, CommandResult.SUCCESS); } else { whenDone.run(Visit.this, CommandResult.FAILURE); } - }, () -> whenDone.run(Visit.this, CommandResult.FAILURE)); + }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); return CompletableFuture.completedFuture(true); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java index 50701b098..319bca775 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java @@ -352,5 +352,7 @@ public class Settings extends Config { public static boolean EXTERNAL_PLACEHOLDERS = true; @Comment("Make road regeneration persistent across restarts") public static boolean PERSISTENT_ROAD_REGEN = false; + @Comment("Try to guess plot owners from sign data. This may decrease server performance") + public static boolean GUESS_PLOT_OWNER = false; } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java index 3aa7759ba..d1b023193 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java @@ -69,6 +69,7 @@ import com.github.intellectualsites.plotsquared.plot.flags.implementations.Untru import com.github.intellectualsites.plotsquared.plot.flags.implementations.UseFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleBreakFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleCapFlag; +import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehiclePlaceFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleUseFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VillagerInteractFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VineGrowFlag; @@ -138,6 +139,7 @@ public final class GlobalFlagContainer extends FlagContainer { this.addFlag(TamedAttackFlag.TAMED_ATTACK_FALSE); this.addFlag(TamedInteractFlag.TAMED_INTERACT_FALSE); this.addFlag(VehicleBreakFlag.VEHICLE_BREAK_FALSE); + this.addFlag(VehiclePlaceFlag.VEHICLE_PLACE_FALSE); this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE); this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE); this.addFlag(VineGrowFlag.VINE_GROW_TRUE); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/AugmentedUtils.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/AugmentedUtils.java index 9b915ec01..97d5af43d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/AugmentedUtils.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/AugmentedUtils.java @@ -11,11 +11,15 @@ import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue; import com.github.intellectualsites.plotsquared.plot.util.block.ScopedLocalBlockQueue; import com.github.intellectualsites.plotsquared.plot.util.world.RegionUtil; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -29,7 +33,7 @@ public class AugmentedUtils { enabled = true; } - public static boolean generate(@NotNull final String world, final int chunkX, final int chunkZ, + public static boolean generate(@Nullable Object chunkObject, @NotNull final String world, final int chunkX, final int chunkZ, LocalBlockQueue queue) { if (!enabled) { return false; @@ -54,6 +58,7 @@ public class AugmentedUtils { // Mask if (queue == null) { queue = GlobalBlockQueue.IMP.getNewQueue(world, false); + queue.setChunkObject(chunkObject); } LocalBlockQueue primaryMask; // coordinates @@ -102,7 +107,7 @@ public class AugmentedUtils { for (int y = 1; y < 128; y++) { queue.setBlock(rx, y, rz, air); } - canPlace[x][z] = can; + canPlace[x][z] = true; has = true; } } @@ -119,6 +124,24 @@ public class AugmentedUtils { return false; } + @Override public boolean setBlock(int x, int y, int z, BaseBlock id) { + try { + if (canPlace[x - blockX][z - blockZ]) { + return super.setBlock(x, y, z, id); + } + } catch (final Exception e) { + PlotSquared.debug(String.format("Failed to set block at: %d;%d;%d (to = %s) with offset %d;%d." + + " Translated to: %d;%d", x, y, z, id, blockX, blockZ, x - blockX, z - blockZ)); + throw e; + } + return false; + } + + @Override public boolean setBlock(int x, int y, int z, Pattern pattern) { + final BlockVector3 blockVector3 = BlockVector3.at(x + blockX, y, z + blockZ); + return this.setBlock(x, y, z, pattern.apply(blockVector3)); + } + @Override public boolean setBiome(int x, int y, BiomeType biome) { return super.setBiome(x, y, biome); } @@ -134,13 +157,18 @@ public class AugmentedUtils { } toReturn = true; } - ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(secondaryMask, - new Location(area.getWorldName(), blockX, 0, blockZ), - new Location(area.getWorldName(), blockX + 15, 255, blockZ + 15)); + primaryMask.setChunkObject(chunkObject); + primaryMask.setForceSync(true); + secondaryMask.setChunkObject(chunkObject); + secondaryMask.setForceSync(true); + + ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(secondaryMask, new Location(world, blockX, 0, blockZ), + new Location(world, blockX + 15, 255, blockZ + 15)); generator.generateChunk(scoped, area); generator.populateChunk(scoped, area); } if (queue != null) { + queue.setForceSync(true); queue.flush(); } return toReturn; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/ClassicPlotManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/ClassicPlotManager.java index 63615956e..780ae14ae 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/ClassicPlotManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/ClassicPlotManager.java @@ -5,6 +5,7 @@ import com.github.intellectualsites.plotsquared.plot.object.BlockBucket; import com.github.intellectualsites.plotsquared.plot.object.Direction; import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Plot; +import com.github.intellectualsites.plotsquared.plot.object.PlotAreaTerrainType; import com.github.intellectualsites.plotsquared.plot.object.PlotId; import com.github.intellectualsites.plotsquared.plot.util.MathMan; import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue; @@ -150,6 +151,12 @@ public class ClassicPlotManager extends SquarePlotManager { if (classicPlotWorld.ROAD_WIDTH == 0) { return false; } + // When using full vanilla generation, don't generate the walls + if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) { + // Return true because the method actually did what it's intended to in this case, + // which is absolutely nothing + return true; + } Plot plot = classicPlotWorld.getPlotAbs(plotId); Location bottom = plot.getBottomAbs(); Location top = plot.getExtendedTopAbs(); @@ -206,6 +213,12 @@ public class ClassicPlotManager extends SquarePlotManager { if (classicPlotWorld.ROAD_WIDTH == 0) { return false; } + // When using full vanilla generation, don't generate the walls + if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) { + // Return true because the method actually did what it's intended to in this case, + // which is absolutely nothing + return true; + } Plot plot = classicPlotWorld.getPlotAbs(plotId); Location bot = plot.getExtendedBottomAbs() .subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0, @@ -253,6 +266,12 @@ public class ClassicPlotManager extends SquarePlotManager { if (classicPlotWorld.ROAD_WIDTH == 0) { return false; } + // When using full vanilla generation, don't generate the walls + if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) { + // Return true because the method actually did what it's intended to in this case, + // which is absolutely nothing + return true; + } Plot plot = classicPlotWorld.getPlotAbs(plotId); Location bot = plot.getExtendedBottomAbs() .subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0, diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotManager.java index 2fb06cc15..bf7e84062 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotManager.java @@ -179,8 +179,8 @@ public class HybridPlotManager extends ClassicPlotManager { Location pos2 = plot.getExtendedTopAbs(); // If augmented final boolean canRegen = - (hybridPlotWorld.getType() == PlotAreaType.NORMAL) - && (hybridPlotWorld.getTerrain() == PlotAreaTerrainType.NONE) && REGENERATIVE_CLEAR; + (hybridPlotWorld.getType() == PlotAreaType.AUGMENTED) + && (hybridPlotWorld.getTerrain() != PlotAreaTerrainType.NONE) && REGENERATIVE_CLEAR; // The component blocks final Pattern plotfloor = hybridPlotWorld.TOP_BLOCK.toPattern(); final Pattern filling = hybridPlotWorld.MAIN_BLOCK.toPattern(); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java index 7986883a1..128913f45 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java @@ -363,7 +363,7 @@ public abstract class HybridUtils { } HybridUtils.UPDATE = true; Set regions = new HashSet<>(); - regions.add(ChunkManager.getRegion(plot.getCenter())); + regions.add(ChunkManager.getRegion(plot.getCenterSynchronous())); return scheduleRoadUpdate(plot.getArea(), regions, extend, new HashSet<>()); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java index 17d857ed2..ef21ef332 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java @@ -66,6 +66,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import java.util.stream.Collectors; import static com.github.intellectualsites.plotsquared.plot.commands.SubCommand.sendMessage; @@ -1041,10 +1042,6 @@ public class Plot { if (!isLoaded()) { return; } - if (!PlotSquared.get().isMainThread(Thread.currentThread())) { - TaskManager.runTask(() -> Plot.this.setSign(name)); - return; - } PlotManager manager = this.area.getPlotManager(); if (this.area.allowSigns()) { Location location = manager.getSignLoc(this); @@ -1057,9 +1054,7 @@ public class Plot { "%plr%", name), Captions.OWNER_SIGN_LINE_4.formatted().replaceAll("%id%", id).replaceAll( "%plr%", name)}; - WorldUtil.IMP - .setSign(this.getWorldName(), location.getX(), location.getY(), location.getZ(), - lines); + WorldUtil.IMP.setSign(this.getWorldName(), location.getX(), location.getY(), location.getZ(), lines); } } @@ -1325,7 +1320,32 @@ public class Plot { return this.unlinkPlot(true, true); } - public Location getCenter() { + public void getCenter(final Consumer result) { + Location[] corners = getCorners(); + Location top = corners[0]; + Location bot = corners[1]; + Location location = + new Location(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; + } + WorldUtil.IMP.getHighestBlock(getWorldName(), location.getX(), location.getZ(), y -> { + int height = y; + if (area.allowSigns()) { + height = Math.max(y, getManager().getSignLoc(this).getY()); + } + location.setY(1 + height); + result.accept(location); + }); + } + + /** + * @deprecated May cause synchronous chunk loads + */ + @Deprecated + public Location getCenterSynchronous() { Location[] corners = getCorners(); Location top = corners[0]; Location bot = corners[1]; @@ -1335,7 +1355,7 @@ public class Plot { if (!isLoaded()) { return location; } - int y = WorldUtil.IMP.getHighestBlock(getWorldName(), location.getX(), location.getZ()); + int y = WorldUtil.IMP.getHighestBlockSynchronous(getWorldName(), location.getX(), location.getZ()); if (area.allowSigns()) { y = Math.max(y, getManager().getSignLoc(this).getY()); } @@ -1343,28 +1363,54 @@ public class Plot { return location; } - public Location getSide() { + /** + * @deprecated May cause synchronous chunk loads + */ + @Deprecated + public Location getSideSynchronous() { CuboidRegion largest = getLargestRegion(); int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1) + largest.getMinimumPoint().getX(); int z = largest.getMinimumPoint().getZ() - 1; PlotManager manager = getManager(); - int y = isLoaded() ? WorldUtil.IMP.getHighestBlock(getWorldName(), x, z) : 62; + int y = isLoaded() ? WorldUtil.IMP.getHighestBlockSynchronous(getWorldName(), x, z) : 62; if (area.allowSigns() && (y <= 0 || y >= 255)) { y = Math.max(y, manager.getSignLoc(this).getY() - 1); } return new Location(getWorldName(), x, y + 1, z); } + public void getSide(Consumer result) { + CuboidRegion largest = getLargestRegion(); + int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1) + + largest.getMinimumPoint().getX(); + int z = largest.getMinimumPoint().getZ() - 1; + PlotManager manager = getManager(); + if (isLoaded()) { + WorldUtil.IMP.getHighestBlock(getWorldName(), x, z, y -> { + int height = y; + if (area.allowSigns() && (y <= 0 || y >= 255)) { + height = Math.max(y, manager.getSignLoc(this).getY() - 1); + } + result.accept(new Location(getWorldName(), x, height + 1, z)); + }); + } else { + int y = 62; + if (area.allowSigns()) { + y = Math.max(y, manager.getSignLoc(this).getY() - 1); + } + result.accept(new Location(getWorldName(), x, y + 1, z)); + } + } + /** - * Return the home location for the plot - * - * @return Home location + * @deprecated May cause synchronous chunk loading */ - public Location getHome() { + @Deprecated + public Location getHomeSynchronous() { BlockLoc home = this.getPosition(); if (home == null || home.getX() == 0 && home.getZ() == 0) { - return this.getDefaultHome(true); + return this.getDefaultHomeSynchronous(true); } else { Location bottom = this.getBottomAbs(); Location location = new Location(bottom.getWorld(), bottom.getX() + home.getX(), @@ -1373,15 +1419,46 @@ public class Plot { if (!isLoaded()) { return location; } - if (!WorldUtil.IMP.getBlock(location).getBlockType().getMaterial().isAir()) { + if (!WorldUtil.IMP.getBlockSynchronous(location).getBlockType().getMaterial().isAir()) { location.setY(Math.max(1 + WorldUtil.IMP - .getHighestBlock(this.getWorldName(), location.getX(), location.getZ()), + .getHighestBlockSynchronous(this.getWorldName(), location.getX(), location.getZ()), bottom.getY())); } return location; } } + /** + * Return the home location for the plot + */ + public void getHome(final Consumer result) { + BlockLoc home = this.getPosition(); + if (home == null || home.getX() == 0 && home.getZ() == 0) { + this.getDefaultHome(result); + } else { + Location bottom = this.getBottomAbs(); + Location location = new Location(bottom.getWorld(), bottom.getX() + home.getX(), + bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(), + home.getPitch()); + if (!isLoaded()) { + result.accept(location); + return; + } + WorldUtil.IMP.getBlock(location, block -> { + if (!block.getBlockType().getMaterial().isAir()) { + WorldUtil.IMP + .getHighestBlock(this.getWorldName(), location.getX(), location.getZ(), y -> { + location.setY(Math.max(1 + y, + bottom.getY())); + result.accept(location); + }); + } else { + result.accept(location); + } + }); + } + } + /** * Sets the home location * @@ -1406,11 +1483,15 @@ public class Plot { * * @return Location */ - public Location getDefaultHome() { - return getDefaultHome(false); + public void getDefaultHome(Consumer result) { + getDefaultHome(false, result); } - public Location getDefaultHome(boolean member) { + /** + * @deprecated May cause synchronous chunk loads + */ + @Deprecated + public Location getDefaultHomeSynchronous(final boolean member) { Plot plot = this.getBasePlot(false); PlotLoc loc = member ? area.getDefaultHome() : area.getNonmemberHome(); if (loc != null) { @@ -1430,12 +1511,47 @@ public class Plot { z = bot.getZ() + loc.getZ(); } int y = loc.getY() < 1 ? - (isLoaded() ? WorldUtil.IMP.getHighestBlock(plot.getWorldName(), x, z) + 1 : 63) : + (isLoaded() ? WorldUtil.IMP.getHighestBlockSynchronous(plot.getWorldName(), x, z) + 1 : 63) : loc.getY(); return new Location(plot.getWorldName(), x, y, z); } // Side - return plot.getSide(); + return plot.getSideSynchronous(); + } + + public void getDefaultHome(boolean member, Consumer result) { + Plot plot = this.getBasePlot(false); + PlotLoc loc = member ? area.getDefaultHome() : area.getNonmemberHome(); + if (loc != null) { + int x; + int z; + if (loc.getX() == Integer.MAX_VALUE && loc.getZ() == Integer.MAX_VALUE) { + // center + CuboidRegion largest = plot.getLargestRegion(); + x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() + >> 1) + largest.getMinimumPoint().getX(); + z = (largest.getMaximumPoint().getZ() >> 1) - (largest.getMinimumPoint().getZ() + >> 1) + largest.getMinimumPoint().getZ(); + } else { + // specific + Location bot = plot.getBottomAbs(); + x = bot.getX() + loc.getX(); + z = bot.getZ() + loc.getZ(); + } + if (loc.getY() < 1) { + if (isLoaded()) { + WorldUtil.IMP.getHighestBlock(plot.getWorldName(), x, z, y -> + result.accept(new Location(plot.getWorldName(), x, y + 1, z))); + } else { + result.accept(new Location(plot.getWorldName(), x, 63, z)); + } + } else { + result.accept(new Location(plot.getWorldName(), x, loc.getY(), z)); + } + return; + } + // Side + plot.getSide(result); } public double getVolume() { @@ -1611,7 +1727,7 @@ public class Plot { setSign(player.getName()); MainUtil.sendMessage(player, Captions.CLAIMED); if (teleport && Settings.Teleport.ON_CLAIM) { - teleportPlayer(player, TeleportCause.COMMAND); + teleportPlayer(player, TeleportCause.COMMAND, result -> {}); } PlotArea plotworld = getArea(); if (plotworld.isSchematicOnClaim()) { @@ -1711,9 +1827,18 @@ public class Plot { * * @return the name of the biome */ - public BiomeType getBiome() { - Location location = this.getCenter(); - return WorldUtil.IMP.getBiome(location.getWorld(), location.getX(), location.getZ()); + public void getBiome(Consumer result) { + this.getCenter(location -> + WorldUtil.IMP.getBiome(location.getWorld(), location.getX(), location.getZ(), result)); + } + + /** + * @deprecated May cause synchronous chunk loads + */ + @Deprecated + public BiomeType getBiomeSynchronous() { + final Location location = this.getCenterSynchronous(); + return WorldUtil.IMP.getBiomeSynchronous(location.getWorld(), location.getX(), location.getZ()); } //TODO Better documentation needed. @@ -2205,9 +2330,6 @@ public class Plot { /** * Gets the set home location or 0,0,0 if no location is set
* - Does not take the default home location into account - * - * @return - * @see #getHome() */ public BlockLoc getPosition() { return this.getSettings().getPosition(); @@ -2246,7 +2368,7 @@ public class Plot { if (this.hasOwner()) { return this.owner; } - if (!this.area.allowSigns()) { + if (!this.area.allowSigns() || !Settings.Enabled_Components.GUESS_PLOT_OWNER) { return null; } try { @@ -2255,7 +2377,7 @@ public class Plot { @Override public void run(String[] value) { ChunkManager.manager .loadChunk(location.getWorld(), location.getBlockVector2(), false); - this.value = WorldUtil.IMP.getSign(location); + this.value = WorldUtil.IMP.getSignSynchronous(location); } }); if (lines == null) { @@ -2876,8 +2998,8 @@ public class Plot { * @param player the player * @return if the teleport succeeded */ - public boolean teleportPlayer(final PlotPlayer player) { - return teleportPlayer(player, TeleportCause.PLUGIN); + public void teleportPlayer(final PlotPlayer player, Consumer result) { + teleportPlayer(player, TeleportCause.PLUGIN, result); } /** @@ -2887,41 +3009,43 @@ public class Plot { * @param cause the cause of the teleport * @return if the teleport succeeded */ - public boolean teleportPlayer(final PlotPlayer player, TeleportCause cause) { + public void teleportPlayer(final PlotPlayer player, TeleportCause cause, Consumer resultConsumer) { Plot plot = this.getBasePlot(false); Result result = PlotSquared.get().getEventDispatcher().callTeleport(player, player.getLocation(), plot).getEventResult(); if (result == Result.DENY) { sendMessage(player, Captions.EVENT_DENIED, "Teleport"); - return false; + resultConsumer.accept(false); + return; } - final Location location; - if (this.area.isHomeAllowNonmember() || plot.isAdded(player.getUUID())) { - location = this.getHome(); - } else { - location = this.getDefaultHome(false); - } - if (Settings.Teleport.DELAY == 0 || Permissions - .hasPermission(player, "plots.teleport.delay.bypass")) { - MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT); - player.teleport(location, cause); - return true; - } - MainUtil.sendMessage(player, Captions.TELEPORT_IN_SECONDS, Settings.Teleport.DELAY + ""); - final String name = player.getName(); - TaskManager.TELEPORT_QUEUE.add(name); - TaskManager.runTaskLater(() -> { - if (!TaskManager.TELEPORT_QUEUE.contains(name)) { - MainUtil.sendMessage(player, Captions.TELEPORT_FAILED); - return; - } - TaskManager.TELEPORT_QUEUE.remove(name); - if (player.isOnline()) { + final Consumer locationConsumer = location -> { + if (Settings.Teleport.DELAY == 0 || Permissions.hasPermission(player, "plots.teleport.delay.bypass")) { MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT); player.teleport(location, cause); + resultConsumer.accept(true); + return; } - }, Settings.Teleport.DELAY * 20); - return true; + MainUtil.sendMessage(player, Captions.TELEPORT_IN_SECONDS, Settings.Teleport.DELAY + ""); + final String name = player.getName(); + TaskManager.TELEPORT_QUEUE.add(name); + TaskManager.runTaskLater(() -> { + if (!TaskManager.TELEPORT_QUEUE.contains(name)) { + MainUtil.sendMessage(player, Captions.TELEPORT_FAILED); + return; + } + TaskManager.TELEPORT_QUEUE.remove(name); + if (player.isOnline()) { + MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT); + player.teleport(location, cause); + } + }, Settings.Teleport.DELAY * 20); + resultConsumer.accept(true); + }; + if (this.area.isHomeAllowNonmember() || plot.isAdded(player.getUUID())) { + this.getHome(locationConsumer); + } else { + this.getDefaultHome(false, locationConsumer); + } } /** diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotAreaTerrainType.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotAreaTerrainType.java index b78b5a2a9..5bbc79b1e 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotAreaTerrainType.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotAreaTerrainType.java @@ -32,7 +32,7 @@ public enum PlotAreaTerrainType { .collect(Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity())); public static Optional fromString(String typeString) { - return Optional.ofNullable(types.get(typeString)); + return Optional.ofNullable(types.get(typeString.toLowerCase())); } @Deprecated diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java index 108439edd..ba877017c 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java @@ -7,6 +7,7 @@ import com.sk89q.worldedit.regions.CuboidRegion; import java.util.HashSet; import java.util.UUID; +import java.util.function.Consumer; public class PlotCluster { public PlotArea area; @@ -86,8 +87,6 @@ public class PlotCluster { /** * Get the area (in plots). - * - * @return */ public int getArea() { return (1 + this.pos2.x - this.pos1.x) * (1 + this.pos2.y - this.pos1.y); @@ -125,26 +124,31 @@ public class PlotCluster { + this.pos2.y; } - public Location getHome() { + public void getHome(Consumer result) { BlockLoc home = this.settings.getPosition(); - Location toReturn; + Consumer locationConsumer = toReturn -> { + MainUtil.getHighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ(), max -> { + if (max > toReturn.getY()) { + toReturn.setY(1 + max); + } + result.accept(toReturn); + }); + }; if (home.getY() == 0) { // default pos Plot center = getCenterPlot(); - toReturn = center.getHome(); - if (toReturn.getY() == 0) { - PlotManager manager = this.area.getPlotManager(); - Location location = manager.getSignLoc(center); - toReturn.setY(location.getY()); - } + center.getHome(location -> { + Location toReturn = location; + if (toReturn.getY() == 0) { + PlotManager manager = this.area.getPlotManager(); + Location locationSign = manager.getSignLoc(center); + toReturn.setY(locationSign.getY()); + } + locationConsumer.accept(toReturn); + }); } else { - toReturn = getClusterBottom().add(home.getX(), home.getY(), home.getZ()); + locationConsumer.accept(getClusterBottom().add(home.getX(), home.getY(), home.getZ())); } - int max = MainUtil.getHeighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ()); - if (max > toReturn.getY()) { - toReturn.setY(1 + max); - } - return toReturn; } public PlotId getCenterPlotId() { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java index f971d798e..bf6d1816e 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java @@ -628,19 +628,17 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { }); } else if (!PlotSquared.get().isMainThread(Thread.currentThread())) { if (getMeta("teleportOnLogin", true)) { - if (plot.teleportPlayer(PlotPlayer.this)) { - TaskManager.runTask(() -> { - if (getMeta("teleportOnLogin", true)) { - if (plot.isLoaded()) { - teleport(location); - sendMessage(CaptionUtility.format(PlotPlayer.this, - Captions.TELEPORTED_TO_PLOT.getTranslated()) - + " (quitLoc-unloaded) (" + plotX + "," + plotZ - + ")"); - } + plot.teleportPlayer(PlotPlayer.this, result -> TaskManager.runTask(() -> { + if (getMeta("teleportOnLogin", true)) { + if (plot.isLoaded()) { + teleport(location); + sendMessage(CaptionUtility.format(PlotPlayer.this, + Captions.TELEPORTED_TO_PLOT.getTranslated()) + + " (quitLoc-unloaded) (" + plotX + "," + plotZ + + ")"); } - }); - } + } + })); } } } catch (Throwable e) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java index c5207ca0a..ef29f37c2 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java @@ -1,14 +1,11 @@ package com.github.intellectualsites.plotsquared.plot.object.worlds; -import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; import com.github.intellectualsites.plotsquared.plot.object.BlockLoc; import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotId; -import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; -import com.github.intellectualsites.plotsquared.plot.object.TeleportCause; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; @@ -18,6 +15,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.function.Consumer; public class SinglePlot extends Plot { private Set regions = Collections.singleton( @@ -51,17 +49,8 @@ public class SinglePlot extends Plot { return (SinglePlotArea) super.getArea(); } - public boolean teleportPlayer(final PlotPlayer player, TeleportCause cause) { - if (isLoaded()) { - return super.teleportPlayer(player, cause); - } else { - Captions.NOT_LOADED.send(player); - return false; - } - } - - @Override public Location getSide() { - return getCenter(); + @Override public void getSide(Consumer result) { + getCenter(result); } @Override protected boolean isLoaded() { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/AutoClaimFinishTask.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/AutoClaimFinishTask.java new file mode 100644 index 000000000..c0fc30302 --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/AutoClaimFinishTask.java @@ -0,0 +1,50 @@ +package com.github.intellectualsites.plotsquared.plot.util; + +import com.github.intellectualsites.plotsquared.plot.PlotSquared; +import com.github.intellectualsites.plotsquared.plot.commands.Auto; +import com.github.intellectualsites.plotsquared.plot.config.Captions; +import com.github.intellectualsites.plotsquared.plot.database.DBFunc; +import com.github.intellectualsites.plotsquared.plot.events.PlotMergeEvent; +import com.github.intellectualsites.plotsquared.plot.events.Result; +import com.github.intellectualsites.plotsquared.plot.object.Direction; +import com.github.intellectualsites.plotsquared.plot.object.Plot; +import com.github.intellectualsites.plotsquared.plot.object.PlotArea; +import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; +import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; +import lombok.RequiredArgsConstructor; + +import static com.github.intellectualsites.plotsquared.plot.util.MainUtil.sendMessage; + +@RequiredArgsConstructor public final class AutoClaimFinishTask extends RunnableVal { + + private final PlotPlayer player; + private final Plot plot; + private final PlotArea area; + private final int allowedPlots; + private final String schematic; + + @Override public void run(Object value) { + player.deleteMeta(Auto.class.getName()); + if (plot == null) { + sendMessage(player, Captions.NO_FREE_PLOTS); + return; + } + + if (Auto.checkAllowedPlots(player, area, allowedPlots, 1, 1)) { + plot.claim(player, true, schematic, false); + if (area.isAutoMerge()) { + PlotMergeEvent event = PlotSquared.get().getEventDispatcher() + .callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player); + if (event.getEventResult() == Result.DENY) { + sendMessage(player, Captions.EVENT_DENIED, "Auto merge"); + } else { + plot.autoMerge(event.getDir(), event.getMax(), player.getUUID(), + true); + } + } + } else { + DBFunc.delete(plot); + } + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventDispatcher.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventDispatcher.java index 1b81a1468..b8de72882 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventDispatcher.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventDispatcher.java @@ -185,7 +185,7 @@ public class EventDispatcher { final Plot plot = player.getCurrentPlot(); if (Settings.Teleport.ON_LOGIN && plot != null && !(plot .getArea() instanceof SinglePlotArea)) { - TaskManager.runTask(() -> plot.teleportPlayer(player)); + TaskManager.runTask(() -> plot.teleportPlayer(player, result -> {})); MainUtil.sendMessage(player, CaptionUtility.format(player, Captions.TELEPORTED_TO_ROAD.getTranslated()) + " (on-login) " + "(" + plot.getId().x + ";" + plot.getId().y + ")"); @@ -195,7 +195,7 @@ public class EventDispatcher { public void doRespawnTask(final PlotPlayer player) { final Plot plot = player.getCurrentPlot(); if (Settings.Teleport.ON_DEATH && plot != null) { - TaskManager.runTask(() -> plot.teleportPlayer(player)); + TaskManager.runTask(() -> plot.teleportPlayer(player, result -> {})); MainUtil.sendMessage(player, Captions.TELEPORTED_TO_ROAD); } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java index a8f24ae4b..26281d7a8 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java @@ -56,6 +56,7 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.function.Function; +import java.util.function.IntConsumer; import java.util.function.IntFunction; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -232,7 +233,7 @@ public class MainUtil { */ public static boolean resetBiome(PlotArea area, Location pos1, Location pos2) { BiomeType biome = area.getPlotBiome(); - if (!Objects.equals(WorldUtil.IMP.getBiome(area.getWorldName(), (pos1.getX() + pos2.getX()) / 2, + if (!Objects.equals(WorldUtil.IMP.getBiomeSynchronous(area.getWorldName(), (pos1.getX() + pos2.getX()) / 2, (pos1.getZ() + pos2.getZ()) / 2), biome)) { MainUtil.setBiome(area.getWorldName(), pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), biome); @@ -589,18 +590,15 @@ public class MainUtil { /** * Get the highest block at a location. - * - * @param world - * @param x - * @param z - * @return */ - public static int getHeighestBlock(String world, int x, int z) { - int result = WorldUtil.IMP.getHighestBlock(world, x, z); - if (result == 0) { - return 63; - } - return result; + public static void getHighestBlock(String world, int x, int z, IntConsumer result) { + WorldUtil.IMP.getHighestBlock(world, x, z, highest -> { + if (highest == 0) { + result.accept(63); + } else { + result.accept(highest); + } + }); } /** @@ -752,116 +750,118 @@ public class MainUtil { /** * Format a string with plot information. * - * @param info + * @param iInfo * @param plot * @param player * @param full * @param whenDone */ - public static void format(String info, final Plot plot, PlotPlayer player, final boolean full, + public static void format(final String iInfo, final Plot plot, PlotPlayer player, final boolean full, final RunnableVal whenDone) { int num = plot.getConnectedPlots().size(); String alias = !plot.getAlias().isEmpty() ? plot.getAlias() : Captions.NONE.getTranslated(); Location bot = plot.getCorners()[0]; - BiomeType biome = WorldUtil.IMP.getBiome(plot.getWorldName(), bot.getX(), bot.getZ()); - String trusted = getPlayerList(plot.getTrusted()); - String members = getPlayerList(plot.getMembers()); - String denied = getPlayerList(plot.getDenied()); - String seen; - if (Settings.Enabled_Components.PLOT_EXPIRY && ExpireManager.IMP != null) { - if (plot.isOnline()) { - seen = Captions.NOW.getTranslated(); - } else { - int time = (int) (ExpireManager.IMP.getAge(plot) / 1000); - if (time != 0) { - seen = MainUtil.secToTime(time); + WorldUtil.IMP.getBiome(plot.getWorldName(), bot.getX(), bot.getZ(), biome -> { + String info = iInfo; + String trusted = getPlayerList(plot.getTrusted()); + String members = getPlayerList(plot.getMembers()); + String denied = getPlayerList(plot.getDenied()); + String seen; + if (Settings.Enabled_Components.PLOT_EXPIRY && ExpireManager.IMP != null) { + if (plot.isOnline()) { + seen = Captions.NOW.getTranslated(); } else { - seen = Captions.UNKNOWN.getTranslated(); - } - } - } else { - seen = Captions.NEVER.getTranslated(); - } - - String description = plot.getFlag(DescriptionFlag.class); - if (description.isEmpty()) { - description = Captions.PLOT_NO_DESCRIPTION.getTranslated(); - } - - StringBuilder flags = new StringBuilder(); - Collection> flagCollection = plot.getApplicableFlags(true); - if (flagCollection.isEmpty()) { - flags.append(Captions.NONE.getTranslated()); - } else { - String prefix = " "; - for (final PlotFlag flag : flagCollection) { - Object value; - if (flag instanceof DoubleFlag && !Settings.General.SCIENTIFIC) { - value = FLAG_DECIMAL_FORMAT.format(flag.getValue()); - } else { - value = flag.toString(); - } - flags.append(prefix).append(CaptionUtility.format(player, Captions.PLOT_FLAG_LIST.getTranslated(), - flag.getName(), CaptionUtility.formatRaw(player, value.toString(), ""))); - prefix = ", "; - } - } - boolean build = plot.isAdded(player.getUUID()); - String owner = plot.getOwners().isEmpty() ? "unowned" : getPlayerList(plot.getOwners()); - if (plot.getArea() != null) { - info = info.replace("%area%", plot.getArea().getWorldName() + - (plot.getArea().getId() == null ? "" : "(" + plot.getArea().getId() + ")")); - } else { - info = info.replace("%area%", Captions.NONE.getTranslated()); - } - info = info.replace("%id%", plot.getId().toString()); - info = info.replace("%alias%", alias); - info = info.replace("%num%", String.valueOf(num)); - info = info.replace("%desc%", description); - info = info.replace("%biome%", biome.toString().toLowerCase()); - info = info.replace("%owner%", owner); - info = info.replace("%members%", members); - info = info.replace("%player%", player.getName()); - info = info.replace("%trusted%", trusted); - info = info.replace("%helpers%", members); - info = info.replace("%denied%", denied); - info = info.replace("%seen%", seen); - info = info.replace("%flags%", flags); - info = info.replace("%build%", String.valueOf(build)); - if (info.contains("%rating%")) { - final String newInfo = info; - TaskManager.runTaskAsync(() -> { - String info1; - if (Settings.Ratings.USE_LIKES) { - info1 = newInfo.replaceAll("%rating%", - String.format("%.0f%%", Like.getLikesPercentage(plot) * 100D)); - } else { - int max = 10; - if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES - .isEmpty()) { - max = 8; - } - if (full && Settings.Ratings.CATEGORIES != null - && Settings.Ratings.CATEGORIES.size() > 1) { - double[] ratings = MainUtil.getAverageRatings(plot); - String rating = ""; - String prefix = ""; - for (int i = 0; i < ratings.length; i++) { - rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String - .format("%.1f", ratings[i]); - prefix = ","; - } - info1 = newInfo.replaceAll("%rating%", rating); + int time = (int) (ExpireManager.IMP.getAge(plot) / 1000); + if (time != 0) { + seen = MainUtil.secToTime(time); } else { - info1 = newInfo.replaceAll("%rating%", - String.format("%.1f", plot.getAverageRating()) + '/' + max); + seen = Captions.UNKNOWN.getTranslated(); } } - whenDone.run(info1); - }); - return; - } - whenDone.run(info); + } else { + seen = Captions.NEVER.getTranslated(); + } + + String description = plot.getFlag(DescriptionFlag.class); + if (description.isEmpty()) { + description = Captions.PLOT_NO_DESCRIPTION.getTranslated(); + } + + StringBuilder flags = new StringBuilder(); + Collection> flagCollection = plot.getApplicableFlags(true); + if (flagCollection.isEmpty()) { + flags.append(Captions.NONE.getTranslated()); + } else { + String prefix = " "; + for (final PlotFlag flag : flagCollection) { + Object value; + if (flag instanceof DoubleFlag && !Settings.General.SCIENTIFIC) { + value = FLAG_DECIMAL_FORMAT.format(flag.getValue()); + } else { + value = flag.toString(); + } + flags.append(prefix).append(CaptionUtility.format(player, Captions.PLOT_FLAG_LIST.getTranslated(), + flag.getName(), CaptionUtility.formatRaw(player, value.toString(), ""))); + prefix = ", "; + } + } + boolean build = plot.isAdded(player.getUUID()); + String owner = plot.getOwners().isEmpty() ? "unowned" : getPlayerList(plot.getOwners()); + if (plot.getArea() != null) { + info = info.replace("%area%", plot.getArea().getWorldName() + + (plot.getArea().getId() == null ? "" : "(" + plot.getArea().getId() + ")")); + } else { + info = info.replace("%area%", Captions.NONE.getTranslated()); + } + info = info.replace("%id%", plot.getId().toString()); + info = info.replace("%alias%", alias); + info = info.replace("%num%", String.valueOf(num)); + info = info.replace("%desc%", description); + info = info.replace("%biome%", biome.toString().toLowerCase()); + info = info.replace("%owner%", owner); + info = info.replace("%members%", members); + info = info.replace("%player%", player.getName()); + info = info.replace("%trusted%", trusted); + info = info.replace("%helpers%", members); + info = info.replace("%denied%", denied); + info = info.replace("%seen%", seen); + info = info.replace("%flags%", flags); + info = info.replace("%build%", String.valueOf(build)); + if (info.contains("%rating%")) { + final String newInfo = info; + TaskManager.runTaskAsync(() -> { + String info1; + if (Settings.Ratings.USE_LIKES) { + info1 = newInfo.replaceAll("%rating%", + String.format("%.0f%%", Like.getLikesPercentage(plot) * 100D)); + } else { + int max = 10; + if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES + .isEmpty()) { + max = 8; + } + if (full && Settings.Ratings.CATEGORIES != null + && Settings.Ratings.CATEGORIES.size() > 1) { + double[] ratings = MainUtil.getAverageRatings(plot); + String rating = ""; + String prefix = ""; + for (int i = 0; i < ratings.length; i++) { + rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String + .format("%.1f", ratings[i]); + prefix = ","; + } + info1 = newInfo.replaceAll("%rating%", rating); + } else { + info1 = newInfo.replaceAll("%rating%", + String.format("%.1f", plot.getAverageRating()) + '/' + max); + } + } + whenDone.run(info1); + }); + return; + } + whenDone.run(info); + }); } public static boolean deleteDirectory(File directory) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/ObjectTaskRunnable.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/ObjectTaskRunnable.java new file mode 100644 index 000000000..ba404d1cb --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/ObjectTaskRunnable.java @@ -0,0 +1,28 @@ +package com.github.intellectualsites.plotsquared.plot.util; + +import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; +import lombok.RequiredArgsConstructor; + +import java.util.Iterator; + +@RequiredArgsConstructor public class ObjectTaskRunnable implements Runnable { + + private final Iterator iterator; + private final RunnableVal task; + private final Runnable whenDone; + + @Override public void run() { + long start = System.currentTimeMillis(); + boolean hasNext; + while ((hasNext = iterator.hasNext()) && System.currentTimeMillis() - start < 5) { + task.value = iterator.next(); + task.run(); + } + if (!hasNext) { + TaskManager.runTaskLater(whenDone, 1); + } else { + TaskManager.runTaskLater(this, 1); + } + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/RuntimeExceptionRunnableVal.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/RuntimeExceptionRunnableVal.java new file mode 100644 index 000000000..81acddc9f --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/RuntimeExceptionRunnableVal.java @@ -0,0 +1,28 @@ +package com.github.intellectualsites.plotsquared.plot.util; + +import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; +import lombok.RequiredArgsConstructor; + +import java.util.concurrent.atomic.AtomicBoolean; + +@RequiredArgsConstructor public class RuntimeExceptionRunnableVal extends RunnableVal { + + private final RunnableVal function; + private final AtomicBoolean running; + + @Override public void run(RuntimeException value) { + try { + function.run(); + } catch (RuntimeException e) { + this.value = e; + } catch (Throwable neverHappens) { + neverHappens.printStackTrace(); + } finally { + running.set(false); + } + synchronized (function) { + function.notifyAll(); + } + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java index 7492644d3..650451260 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java @@ -178,8 +178,7 @@ public abstract class SchematicHandler { if (pw instanceof ClassicPlotWorld) { y_offset_actual = yOffset + ((ClassicPlotWorld) pw).PLOT_HEIGHT; } else { - y_offset_actual = yOffset + 1 + MainUtil - .getHeighestBlock(plot.getWorldName(), + y_offset_actual = yOffset + 1 + WorldUtil.IMP.getHighestBlockSynchronous(plot.getWorldName(), region.getMinimumPoint().getX() + 1, region.getMinimumPoint().getZ() + 1); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/TaskManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/TaskManager.java index f6e86cd92..a20e80f6e 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/TaskManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/TaskManager.java @@ -93,21 +93,7 @@ public abstract class TaskManager { public static void objectTask(Collection objects, final RunnableVal task, final Runnable whenDone) { final Iterator iterator = objects.iterator(); - TaskManager.runTask(new Runnable() { - @Override public void run() { - long start = System.currentTimeMillis(); - boolean hasNext; - while ((hasNext = iterator.hasNext()) && System.currentTimeMillis() - start < 5) { - task.value = iterator.next(); - task.run(); - } - if (!hasNext) { - TaskManager.runTaskLater(whenDone, 1); - } else { - TaskManager.runTaskLater(this, 1); - } - } - }); + TaskManager.runTask(new ObjectTaskRunnable<>(iterator, task, whenDone)); } public T sync(final RunnableVal function) { @@ -120,22 +106,7 @@ public abstract class TaskManager { return function.value; } final AtomicBoolean running = new AtomicBoolean(true); - RunnableVal run = new RunnableVal() { - @Override public void run(RuntimeException value) { - try { - function.run(); - } catch (RuntimeException e) { - this.value = e; - } catch (Throwable neverHappens) { - neverHappens.printStackTrace(); - } finally { - running.set(false); - } - synchronized (function) { - function.notifyAll(); - } - } - }; + final RuntimeExceptionRunnableVal run = new RuntimeExceptionRunnableVal<>(function, running); TaskManager.IMP.task(run); try { synchronized (function) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/WorldUtil.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/WorldUtil.java index 3d7188187..63cc5c44d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/WorldUtil.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/WorldUtil.java @@ -5,7 +5,6 @@ import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; -import com.github.intellectualsites.plotsquared.plot.object.schematic.PlotItem; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.NBTInputStream; @@ -15,6 +14,7 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockState; +import org.jetbrains.annotations.NotNull; import java.io.ByteArrayOutputStream; import java.io.File; @@ -25,11 +25,12 @@ import java.net.URL; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.IntConsumer; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import org.jetbrains.annotations.NotNull; public abstract class WorldUtil { public static WorldUtil IMP; @@ -38,7 +39,13 @@ public abstract class WorldUtil { public abstract boolean isWorld(String worldName); - public abstract String[] getSign(Location location); + public abstract void getSign(Location location, Consumer result); + + /** + * @deprecated May result in synchronous chunk loading + */ + @Deprecated + public abstract String[] getSignSynchronous(Location location); public abstract Location getSpawn(String world); @@ -52,13 +59,29 @@ public abstract class WorldUtil { public abstract StringComparison.ComparisonResult getClosestBlock(String name); - public abstract BiomeType getBiome(String world, int x, int z); + public abstract void getBiome(String world, int x, int z, Consumer result); - public abstract BlockState getBlock(Location location); + /** + * @deprecated May result in synchronous chunk loading + */ + @Deprecated + public abstract BiomeType getBiomeSynchronous(String world, int x, int z); - public abstract int getHighestBlock(String world, int x, int z); + public abstract void getBlock(Location location, Consumer result); - public abstract boolean addItems(String world, PlotItem item); + /** + * @deprecated May result in synchronous chunk loading + */ + @Deprecated + public abstract BlockState getBlockSynchronous(Location location); + + public abstract void getHighestBlock(String world, int x, int z, final IntConsumer result); + + /** + * @deprecated May result in synchronous chunk loading + */ + @Deprecated + public abstract int getHighestBlockSynchronous(String world, int x, int z); public abstract void setSign(String world, int x, int y, int z, String[] lines); @@ -67,8 +90,7 @@ public abstract class WorldUtil { public abstract com.sk89q.worldedit.world.World getWeWorld(String world); public void upload(@NotNull final Plot plot, UUID uuid, String file, RunnableVal whenDone) { - final Location home = plot.getHome(); - MainUtil.upload(uuid, file, "zip", new RunnableVal() { + plot.getHome(home -> MainUtil.upload(uuid, file, "zip", new RunnableVal() { @Override public void run(OutputStream output) { try (final ZipOutputStream zos = new ZipOutputStream(output)) { File dat = getDat(plot.getWorldName()); @@ -135,7 +157,7 @@ public abstract class WorldUtil { e.printStackTrace(); } } - }, whenDone); + }, whenDone)); } public File getDat(String world) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/BasicLocalBlockQueue.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/BasicLocalBlockQueue.java index 0f3bc38a5..6c12466b7 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/BasicLocalBlockQueue.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/BasicLocalBlockQueue.java @@ -222,6 +222,7 @@ public abstract class BasicLocalBlockQueue extends LocalBlockQueue { public class BasicLocalChunk extends LocalChunk { + public BasicLocalChunk(BasicLocalBlockQueue parent, int x, int z) { super(parent, x, z); baseblocks = new BaseBlock[16][]; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/DelegateLocalBlockQueue.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/DelegateLocalBlockQueue.java index 4aa308a95..b0b4e03ea 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/DelegateLocalBlockQueue.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/DelegateLocalBlockQueue.java @@ -12,6 +12,11 @@ public class DelegateLocalBlockQueue extends LocalBlockQueue { public DelegateLocalBlockQueue(LocalBlockQueue parent) { super(parent == null ? null : parent.getWorld()); this.parent = parent; + + if (parent != null) { + this.setForceSync(parent.isForceSync()); + this.setChunkObject(parent.getChunkObject()); + } } public LocalBlockQueue getParent() { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/LocalBlockQueue.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/LocalBlockQueue.java index 9072dd42b..fe1de0660 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/LocalBlockQueue.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/LocalBlockQueue.java @@ -13,12 +13,18 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Map; -import org.jetbrains.annotations.NotNull; public abstract class LocalBlockQueue { + @Getter @Setter private boolean forceSync = false; + @Getter @Setter @Nullable private Object chunkObject; + /** * Needed for compatibility with FAWE. * @@ -100,7 +106,7 @@ public abstract class LocalBlockQueue { .equals(loc)) { continue; } - pLoc.setY(WorldUtil.IMP.getHighestBlock(getWorld(), pLoc.getX(), pLoc.getZ())); + pLoc.setY(WorldUtil.IMP.getHighestBlockSynchronous(getWorld(), pLoc.getX(), pLoc.getZ())); pp.teleport(pLoc); } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/ScopedLocalBlockQueue.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/ScopedLocalBlockQueue.java index 6a0e375c5..e349badd1 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/ScopedLocalBlockQueue.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/ScopedLocalBlockQueue.java @@ -6,6 +6,7 @@ import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotManager; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -36,8 +37,10 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue { this.dx = maxX - minX; this.dy = maxY - minY; this.dz = maxZ - minZ; - } + this.setForceSync(parent.isForceSync()); + this.setChunkObject(parent.getChunkObject()); + } @Override public boolean setBiome(int x, int z, BiomeType biome) { return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBiome(x + minX, z + minZ, biome); @@ -61,6 +64,11 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue { .setBlock(x + minX, y + minY, z + minZ, id); } + @Override public boolean setBlock(int x, int y, int z, Pattern pattern) { + return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super + .setBlock(x + minX, y + minY, z + minZ, pattern); + } + public Location getMin() { return new Location(getWorld(), minX, minY, minZ); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java index 28283ce35..b595804b3 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java @@ -119,7 +119,7 @@ public class ExpireManager { if (!isExpired(new ArrayDeque<>(tasks), current).isEmpty()) { TaskManager.runTask(() -> { pp.setMeta("ignoreExpireTask", true); - pp.teleport(current.getCenter()); + current.getCenter(pp::teleport); pp.deleteMeta("ignoreExpireTask"); PlotMessage msg = new PlotMessage() .text(num + " " + (num > 1 ? "plots are" : "plot is") + " expired: ")