From d5d18a60fb68e95115a1f8678043e6f01a76d328 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Tue, 19 May 2020 11:53:18 +0100 Subject: [PATCH 1/4] Fix #2836 getCompoundTag can also be in Core since we're using WorldEdit. --- .../schematic/BukkitSchematicHandler.java | 243 ------------------ .../core/util/SchematicHandler.java | 201 ++++++++++++++- 2 files changed, 198 insertions(+), 246 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java index 86fbd732e..27ce9139f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java @@ -25,258 +25,15 @@ */ package com.plotsquared.bukkit.schematic; -import com.plotsquared.bukkit.util.BukkitUtil; -import com.plotsquared.core.location.Location; import com.plotsquared.core.queue.LocalBlockQueue; -import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SchematicHandler; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.task.TaskManager; -import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.IntArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.math.BlockVector2; -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 java.io.ByteArrayOutputStream; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.IntStream; /** * Schematic Handler. */ public class BukkitSchematicHandler extends SchematicHandler { - @Override - public void getCompoundTag(final String world, final Set regions, - final RunnableVal whenDone) { - // async - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - // Main positions - Location[] corners = MainUtil.getCorners(world, regions); - final Location bot = corners[0]; - final Location top = corners[1]; - - CuboidRegion cuboidRegion = - new CuboidRegion(BukkitUtil.IMP.getWeWorld(world), bot.getBlockVector3(), - top.getBlockVector3()); - - final int width = cuboidRegion.getWidth(); - int height = cuboidRegion.getHeight(); - final int length = cuboidRegion.getLength(); - Map schematic = new HashMap<>(); - schematic.put("Version", new IntTag(2)); - schematic.put("DataVersion", new IntTag(WorldEdit.getInstance().getPlatformManager() - .queryCapability(Capability.WORLD_EDITING).getDataVersion())); - - Map metadata = new HashMap<>(); - metadata.put("WEOffsetX", new IntTag(0)); - metadata.put("WEOffsetY", new IntTag(0)); - metadata.put("WEOffsetZ", new IntTag(0)); - - schematic.put("Metadata", new CompoundTag(metadata)); - - schematic.put("Width", new ShortTag((short) width)); - schematic.put("Height", new ShortTag((short) height)); - schematic.put("Length", new ShortTag((short) length)); - - // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin' - schematic.put("Offset", new IntArrayTag(new int[] {0, 0, 0,})); - - Map palette = new HashMap<>(); - Map biomePalette = new HashMap<>(); - - List tileEntities = new ArrayList<>(); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length); - ByteArrayOutputStream biomeBuffer = new ByteArrayOutputStream(width * length); - // Queue - final ArrayDeque queue = new ArrayDeque<>(regions); - TaskManager.runTask(new Runnable() { - @Override public void run() { - if (queue.isEmpty()) { - TaskManager.runTaskAsync(() -> { - schematic.put("PaletteMax", new IntTag(palette.size())); - - Map paletteTag = new HashMap<>(); - palette.forEach( - (key, value) -> paletteTag.put(key, new IntTag(value))); - - schematic.put("Palette", new CompoundTag(paletteTag)); - schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray())); - schematic.put("TileEntities", - new ListTag(CompoundTag.class, tileEntities)); - - schematic.put("BiomePaletteMax", new IntTag(biomePalette.size())); - - Map biomePaletteTag = new HashMap<>(); - biomePalette.forEach( - (key, value) -> biomePaletteTag.put(key, new IntTag(value))); - - schematic.put("BiomePalette", new CompoundTag(biomePaletteTag)); - schematic - .put("BiomeData", new ByteArrayTag(biomeBuffer.toByteArray())); - whenDone.value = new CompoundTag(schematic); - TaskManager.runTask(whenDone); - }); - return; - } - final Runnable regionTask = this; - CuboidRegion region = queue.poll(); - Location pos1 = new Location(world, region.getMinimumPoint().getX(), - region.getMinimumPoint().getY(), region.getMinimumPoint().getZ()); - Location pos2 = new Location(world, region.getMaximumPoint().getX(), - region.getMaximumPoint().getY(), region.getMaximumPoint().getZ()); - final int p1x = pos1.getX(); - final int sy = pos1.getY(); - final int p1z = pos1.getZ(); - final int p2x = pos2.getX(); - final int p2z = pos2.getZ(); - final int ey = pos2.getY(); - Iterator yiter = IntStream.range(sy, ey + 1).iterator(); - final Runnable yTask = new Runnable() { - @Override public void run() { - long ystart = System.currentTimeMillis(); - while (yiter.hasNext() - && System.currentTimeMillis() - ystart < 20) { - final int y = yiter.next(); - Iterator ziter = - IntStream.range(p1z, p2z + 1).iterator(); - final Runnable zTask = new Runnable() { - @Override public void run() { - long zstart = System.currentTimeMillis(); - while (ziter.hasNext() - && System.currentTimeMillis() - zstart < 20) { - final int z = ziter.next(); - Iterator xiter = - IntStream.range(p1x, p2x + 1).iterator(); - final Runnable xTask = new Runnable() { - @Override public void run() { - long xstart = System.currentTimeMillis(); - final int ry = y - sy; - final int rz = z - p1z; - while (xiter.hasNext() - && System.currentTimeMillis() - xstart - < 20) { - final int x = xiter.next(); - final int rx = x - p1x; - BlockVector3 point = - BlockVector3.at(x, y, z); - BaseBlock block = - cuboidRegion.getWorld() - .getFullBlock(point); - if (block.getNbtData() != null) { - Map values = - new HashMap<>(); - for (Map.Entry entry : block - .getNbtData().getValue() - .entrySet()) { - values.put(entry.getKey(), - entry.getValue()); - } - // Remove 'id' if it exists. We want 'Id' - values.remove("id"); - - // Positions are kept in NBT, we don't want that. - values.remove("x"); - values.remove("y"); - values.remove("z"); - - values.put("Id", new StringTag( - block.getNbtId())); - values.put("Pos", new IntArrayTag( - new int[] {rx, ry, rz})); - - tileEntities - .add(new CompoundTag(values)); - } - String blockKey = - block.toImmutableState() - .getAsString(); - int blockId; - if (palette.containsKey(blockKey)) { - blockId = palette.get(blockKey); - } else { - blockId = palette.size(); - palette - .put(blockKey, palette.size()); - } - - while ((blockId & -128) != 0) { - buffer.write(blockId & 127 | 128); - blockId >>>= 7; - } - buffer.write(blockId); - - if (ry == sy) { - BlockVector2 pt = - BlockVector2.at(x, z); - BiomeType biome = - cuboidRegion.getWorld() - .getBiome(pt); - String biomeStr = biome.getId(); - int biomeId; - if (biomePalette - .containsKey(biomeStr)) { - biomeId = - biomePalette.get(biomeStr); - } else { - biomeId = biomePalette.size(); - biomePalette - .put(biomeStr, biomeId); - } - while ((biomeId & -128) != 0) { - biomeBuffer - .write(biomeId & 127 | 128); - biomeId >>>= 7; - } - biomeBuffer.write(biomeId); - } - } - if (xiter.hasNext()) { - this.run(); - } - } - }; - xTask.run(); - } - if (ziter.hasNext()) { - this.run(); - } - } - }; - zTask.run(); - } - if (yiter.hasNext()) { - TaskManager.runTaskLater(this, 1); - } else { - regionTask.run(); - } - } - }; - yTask.run(); - } - }); - } - }); - } - @Override public boolean restoreTile(LocalBlockQueue queue, CompoundTag ct, int x, int y, int z) { return new StateWrapper(ct).restoreTag(queue.getWorld(), x, y, z); diff --git a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java index 3adb8d19e..850cef3e0 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java @@ -36,9 +36,18 @@ import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.uuid.UUIDHandler; +import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.IntArrayTag; +import com.sk89q.jnbt.IntTag; +import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; +import com.sk89q.jnbt.ShortTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; @@ -55,6 +64,7 @@ import org.json.JSONArray; import org.json.JSONException; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -67,15 +77,19 @@ import java.net.URL; import java.net.URLConnection; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -464,8 +478,190 @@ public abstract class SchematicHandler { return true; } - public abstract void getCompoundTag(String world, Set regions, - RunnableVal whenDone); + public void getCompoundTag(final String world, final Set regions, + final RunnableVal whenDone) { + // async + TaskManager.runTaskAsync(() -> { + // Main positions + Location[] corners = MainUtil.getCorners(world, regions); + final Location bot = corners[0]; + final Location top = corners[1]; + + CuboidRegion cuboidRegion = + new CuboidRegion(WorldUtil.IMP.getWeWorld(world), bot.getBlockVector3(), + top.getBlockVector3()); + + final int width = cuboidRegion.getWidth(); + int height = cuboidRegion.getHeight(); + final int length = cuboidRegion.getLength(); + Map schematic = new HashMap<>(); + schematic.put("Version", new IntTag(2)); + schematic.put("DataVersion", new IntTag(WorldEdit.getInstance().getPlatformManager() + .queryCapability(Capability.WORLD_EDITING).getDataVersion())); + + Map metadata = new HashMap<>(); + metadata.put("WEOffsetX", new IntTag(0)); + metadata.put("WEOffsetY", new IntTag(0)); + metadata.put("WEOffsetZ", new IntTag(0)); + + schematic.put("Metadata", new CompoundTag(metadata)); + + schematic.put("Width", new ShortTag((short) width)); + schematic.put("Height", new ShortTag((short) height)); + schematic.put("Length", new ShortTag((short) length)); + + // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin' + schematic.put("Offset", new IntArrayTag(new int[] {0, 0, 0,})); + + Map palette = new HashMap<>(); + Map biomePalette = new HashMap<>(); + + List tileEntities = new ArrayList<>(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length); + ByteArrayOutputStream biomeBuffer = new ByteArrayOutputStream(width * length); + // Queue + final ArrayDeque queue = new ArrayDeque<>(regions); + TaskManager.runTask(new Runnable() { + @Override public void run() { + if (queue.isEmpty()) { + TaskManager.runTaskAsync(() -> { + schematic.put("PaletteMax", new IntTag(palette.size())); + + Map paletteTag = new HashMap<>(); + palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value))); + + schematic.put("Palette", new CompoundTag(paletteTag)); + schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray())); + schematic + .put("TileEntities", new ListTag(CompoundTag.class, tileEntities)); + + schematic.put("BiomePaletteMax", new IntTag(biomePalette.size())); + + Map biomePaletteTag = new HashMap<>(); + biomePalette.forEach( + (key, value) -> biomePaletteTag.put(key, new IntTag(value))); + + schematic.put("BiomePalette", new CompoundTag(biomePaletteTag)); + schematic.put("BiomeData", new ByteArrayTag(biomeBuffer.toByteArray())); + whenDone.value = new CompoundTag(schematic); + TaskManager.runTask(whenDone); + }); + return; + } + final Runnable regionTask = this; + CuboidRegion region = queue.poll(); + Location pos1 = new Location(world, region.getMinimumPoint().getX(), + region.getMinimumPoint().getY(), region.getMinimumPoint().getZ()); + Location pos2 = new Location(world, region.getMaximumPoint().getX(), + region.getMaximumPoint().getY(), region.getMaximumPoint().getZ()); + final int p1x = pos1.getX(); + final int sy = pos1.getY(); + final int p1z = pos1.getZ(); + final int p2x = pos2.getX(); + final int p2z = pos2.getZ(); + final int ey = pos2.getY(); + Iterator yiter = IntStream.range(sy, ey + 1).iterator(); + final Runnable yTask = () -> { + long ystart = System.currentTimeMillis(); + while (yiter.hasNext() && System.currentTimeMillis() - ystart < 20) { + final int y = yiter.next(); + Iterator ziter = IntStream.range(p1z, p2z + 1).iterator(); + final Runnable zTask = () -> { + long zstart = System.currentTimeMillis(); + while (ziter.hasNext() + && System.currentTimeMillis() - zstart < 20) { + final int z = ziter.next(); + Iterator xiter = + IntStream.range(p1x, p2x + 1).iterator(); + final Runnable xTask = () -> { + long xstart = System.currentTimeMillis(); + final int ry = y - sy; + final int rz = z - p1z; + while (xiter.hasNext() + && System.currentTimeMillis() - xstart < 20) { + final int x = xiter.next(); + final int rx = x - p1x; + BlockVector3 point = BlockVector3.at(x, y, z); + BaseBlock block = + cuboidRegion.getWorld().getFullBlock(point); + if (block.getNbtData() != null) { + Map values = new HashMap<>(); + for (Map.Entry entry : block + .getNbtData().getValue().entrySet()) { + values.put(entry.getKey(), entry.getValue()); + } + // Remove 'id' if it exists. We want 'Id' + values.remove("id"); + + // Positions are kept in NBT, we don't want that. + values.remove("x"); + values.remove("y"); + values.remove("z"); + + values.put("Id", new StringTag(block.getNbtId())); + values.put("Pos", + new IntArrayTag(new int[] {rx, ry, rz})); + + tileEntities.add(new CompoundTag(values)); + } + String blockKey = + block.toImmutableState().getAsString(); + int blockId; + if (palette.containsKey(blockKey)) { + blockId = palette.get(blockKey); + } else { + blockId = palette.size(); + palette.put(blockKey, palette.size()); + } + + while ((blockId & -128) != 0) { + buffer.write(blockId & 127 | 128); + blockId >>>= 7; + } + buffer.write(blockId); + + if (ry > 0) { + continue; + } + BlockVector2 pt = BlockVector2.at(x, z); + BiomeType biome = cuboidRegion.getWorld().getBiome(pt); + String biomeStr = biome.getId(); + int biomeId; + if (biomePalette.containsKey(biomeStr)) { + biomeId = biomePalette.get(biomeStr); + } else { + biomeId = biomePalette.size(); + biomePalette.put(biomeStr, biomeId); + } + while ((biomeId & -128) != 0) { + biomeBuffer.write(biomeId & 127 | 128); + biomeId >>>= 7; + } + biomeBuffer.write(biomeId); + } + if (xiter.hasNext()) { + this.run(); + } + }; + xTask.run(); + } + if (ziter.hasNext()) { + this.run(); + } + }; + zTask.run(); + } + if (yiter.hasNext()) { + TaskManager.runTaskLater(this, 1); + } else { + regionTask.run(); + } + }; + yTask.run(); + } + }); + }); + } public void getCompoundTag(final Plot plot, final RunnableVal whenDone) { getCompoundTag(plot.getWorldName(), plot.getRegions(), new RunnableVal() { @@ -495,7 +691,6 @@ public abstract class SchematicHandler { public UnsupportedFormatException(String message, Throwable cause) { super(message, cause); } - } } From 7aba70ea6548929dbae382eace7cab9f5c23b271 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Tue, 19 May 2020 16:54:12 +0100 Subject: [PATCH 2/4] Make plot clears/sets less crashy. There's still the issue of Spigot's (or paper's) terrible GC that does nothing and stores everything in PS old gen memory so the server just numpties itself though. --- .../bukkit/queue/BukkitLocalQueue.java | 21 +++++++++++++++---- .../com/plotsquared/core/PlotSquared.java | 2 +- .../core/configuration/Settings.java | 7 +++++++ .../core/queue/GlobalBlockQueue.java | 17 +++++++++++---- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java index 3f93ebb63..c8d6d929f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java @@ -31,6 +31,7 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.queue.BasicLocalBlockQueue; import com.plotsquared.core.util.BlockUtil; import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.task.TaskManager; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; @@ -50,7 +51,6 @@ import org.bukkit.block.Biome; import org.bukkit.block.Block; import org.bukkit.block.Container; import org.bukkit.block.data.BlockData; -import org.bukkit.inventory.BlockInventoryHolder; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; @@ -117,9 +117,6 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { @Override public final void setComponents(LocalChunk lc) throws ExecutionException, InterruptedException { setBaseBlocks(lc); - if (setBiome() && lc.biomes != null) { - setBiomes(lc); - } } public void setBaseBlocks(LocalChunk localChunk) { @@ -165,6 +162,22 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { } } } + if (setBiome() && localChunk.biomes != null) { + for (int x = 0; x < localChunk.biomes.length; x++) { + BiomeType[] biomeZ = localChunk.biomes[x]; + if (biomeZ != null) { + for (int z = 0; z < biomeZ.length; z++) { + if (biomeZ[z] != null) { + BiomeType biomeType = biomeZ[z]; + + Biome biome = BukkitAdapter.adapt(biomeType); + worldObj.setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, + biome); + } + } + } + } + } }; if (isForceSync()) { chunkConsumer.accept(getChunk(worldObj, localChunk)); diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 452493181..4cb0731d5 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -270,7 +270,7 @@ public class PlotSquared { // create setup util class SetupUtils.manager = this.IMP.initSetupUtils(); // Set block - GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1); + GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1, Settings.QUEUE.TARGET_TIME); GlobalBlockQueue.IMP.runTask(); // Set chunk ChunkManager.manager = this.IMP.initChunkManager(); diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 044642baa..3fbd71394 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -489,6 +489,13 @@ public class Settings extends Config { public static boolean TILE_ENTITY_CHECK = true; } + @Comment("Settings relating to PlotSquared's GlobalBlockQueue") + public static final class QUEUE { + @Comment({"Average time per tick spent completing chunk tasks in ms. Target average TPS = 20 * 50 / TARGET_TIME.", + "Waits (chunk task time / target_time) ticks before completely the next task."}) + public static int TARGET_TIME = 65; + } + @Comment({"Enable or disable parts of the plugin", "Note: A cache will use some memory if enabled"}) diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index 68a059583..3b63a94c0 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -44,8 +44,8 @@ public class GlobalBlockQueue { private final ConcurrentLinkedDeque inactiveQueues; private final ConcurrentLinkedDeque runnables; private final AtomicBoolean running; + private final int targetTime; private QueueProvider provider; - /** * Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the * server @@ -53,6 +53,7 @@ public class GlobalBlockQueue { private long last; private long secondLast; private long lastSuccess; + private double lastPeriod = 0; private final RunnableVal2 SET_TASK = new RunnableVal2() { @Override public void run(Long free, LocalBlockQueue queue) { @@ -65,17 +66,19 @@ public class GlobalBlockQueue { } return; } - } while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - - GlobalBlockQueue.this.last) < free); + } while ((lastPeriod = + ((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) + - GlobalBlockQueue.this.last)) < free); } }; - public GlobalBlockQueue(QueueProvider provider, int threads) { + public GlobalBlockQueue(QueueProvider provider, int threads, int targetTime) { this.provider = provider; this.activeQueues = new ConcurrentLinkedDeque<>(); this.inactiveQueues = new ConcurrentLinkedDeque<>(); this.runnables = new ConcurrentLinkedDeque<>(); this.running = new AtomicBoolean(); + this.targetTime = targetTime; this.PARALLEL_THREADS = threads; } @@ -112,9 +115,15 @@ public class GlobalBlockQueue { @Override public void run() { if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { lastSuccess = System.currentTimeMillis(); + lastPeriod = 0; GlobalBlockQueue.this.runEmptyTasks(); return; } + // Server laggy? Skip. + if (lastPeriod > targetTime) { + lastPeriod -= targetTime; + return; + } SET_TASK.value1 = 50 + Math.min( (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = System.currentTimeMillis()), From 0160c2bb551d9cbab5659f4c2f2bb57a99b6b2d2 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 20 May 2020 08:43:58 +0100 Subject: [PATCH 3/4] Add setCuboids method to RegionManager - Allow FAWE to take charge of big operations like /plot set all --- .../core/generator/ClassicPlotManager.java | 68 +++++-------------- .../plotsquared/core/util/RegionManager.java | 16 +++++ 2 files changed, 32 insertions(+), 52 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java index 022f7037d..52557144e 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java @@ -36,6 +36,7 @@ import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.BlockUtil; import com.plotsquared.core.util.MathMan; +import com.plotsquared.core.util.RegionManager; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.block.BlockTypes; @@ -92,75 +93,38 @@ public class ClassicPlotManager extends SquarePlotManager { public boolean setFloor(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - LocalBlockQueue queue = classicPlotWorld.getQueue(false); if (plot.isBasePlot()) { - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT, region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT, region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } + return RegionManager.manager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, + classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.PLOT_HEIGHT); } - return queue.enqueue(); + return false; } public boolean setAll(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - if (!plot.isBasePlot()) { - return false; + if (plot.isBasePlot()) { + return RegionManager.manager + .setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, getWorldHeight()); } - LocalBlockQueue queue = classicPlotWorld.getQueue(false); - int maxY = getWorldHeight(); - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), 1, - region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), maxY, - region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } - return queue.enqueue(); + return false; } public boolean setAir(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - if (!plot.isBasePlot()) { - return false; + if (plot.isBasePlot()) { + return RegionManager.manager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, + classicPlotWorld.PLOT_HEIGHT + 1, getWorldHeight()); } - LocalBlockQueue queue = classicPlotWorld.getQueue(false); - int maxY = getWorldHeight(); - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT + 1, region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), maxY, - region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } - return queue.enqueue(); + return false; } public boolean setMain(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - if (!plot.isBasePlot()) { - return false; + if (plot.isBasePlot()) { + return RegionManager.manager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, + classicPlotWorld.PLOT_HEIGHT - 1); } - LocalBlockQueue queue = classicPlotWorld.getQueue(false); - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), 1, - region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT - 1, region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } - return queue.enqueue(); + return false; } public boolean setMiddle(PlotId plotId, Pattern blocks) { diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java index 5ab1a8350..ab3333a19 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java @@ -28,8 +28,11 @@ package com.plotsquared.core.util; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; @@ -147,6 +150,19 @@ public abstract class RegionManager { }); } + public boolean setCuboids(final PlotArea area, final Set regions, + final Pattern blocks, int minY, int maxY) { + LocalBlockQueue queue = area.getQueue(false); + for (CuboidRegion region : regions) { + Location pos1 = new Location(area.getWorldName(), region.getMinimumPoint().getX(), minY, + region.getMinimumPoint().getZ()); + Location pos2 = new Location(area.getWorldName(), region.getMaximumPoint().getX(), maxY, + region.getMaximumPoint().getZ()); + queue.setCuboid(pos1, pos2, blocks); + } + return queue.enqueue(); + } + /** * Copy a region to a new location (in the same world) */ From 525ba648ae0910c16e4f65fc332967b13edc92fb Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 20 May 2020 09:44:45 +0100 Subject: [PATCH 4/4] ignore build/ and update bukkit pom.xml apparently --- .gitignore | 1 + Bukkit/pom.xml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 24f46cd56..3423dd222 100644 --- a/.gitignore +++ b/.gitignore @@ -142,3 +142,4 @@ p2error.txt *.bat Nukkit/build/resources/main/plugin.yml docs/ +build/ diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 40202c32e..1eace8462 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -59,6 +59,12 @@ Core 0.6.0-SNAPSHOT compile + + + * + * + + com.sk89q.worldedit