diff --git a/core/src/main/java/com/volmit/iris/core/IrisSettings.java b/core/src/main/java/com/volmit/iris/core/IrisSettings.java index 30216b29e..2046d68d6 100644 --- a/core/src/main/java/com/volmit/iris/core/IrisSettings.java +++ b/core/src/main/java/com/volmit/iris/core/IrisSettings.java @@ -176,13 +176,13 @@ public class IrisSettings { @Data public static class IrisSettingsUpdater { - public double threadMultiplier = 2; + public int maxConcurrency = 256; public double chunkLoadSensitivity = 0.7; public MsRange emptyMsRange = new MsRange(80, 100); public MsRange defaultMsRange = new MsRange(20, 40); - public double getThreadMultiplier() { - return Math.min(Math.abs(threadMultiplier), 0.1); + public int getMaxConcurrency() { + return Math.max(Math.abs(maxConcurrency), 1); } public double getChunkLoadSensitivity() { diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java index 572ce98d4..0dba60111 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java @@ -39,14 +39,14 @@ public class ChunkUpdater { private final AtomicInteger chunksUpdated = new AtomicInteger(); private final AtomicBoolean serverEmpty = new AtomicBoolean(true); private final AtomicLong lastCpsTime = new AtomicLong(M.ms()); - private final int coreLimit = (int) Math.max(Runtime.getRuntime().availableProcessors() * IrisSettings.get().getUpdater().getThreadMultiplier(), 1); - private final Semaphore semaphore = new Semaphore(256); - private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, 256, IrisSettings.get().getUpdater().emptyMsRange); + private final int maxConcurrency = IrisSettings.get().getUpdater().getMaxConcurrency(); + private final Semaphore semaphore = new Semaphore(maxConcurrency); + private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, maxConcurrency, IrisSettings.get().getUpdater().emptyMsRange); private final AtomicLong startTime = new AtomicLong(); private final Dimensions dimensions; private final PregenTask task; - private final ExecutorService executor = Executors.newFixedThreadPool(coreLimit); - private final ExecutorService chunkExecutor = Executors.newFixedThreadPool(coreLimit); + private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); + private final ExecutorService chunkExecutor = Executors.newVirtualThreadPerTaskExecutor(); private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); private final CountDownLatch latch; private final Engine engine; @@ -138,10 +138,10 @@ public class ChunkUpdater { loadBalancer.close(); semaphore.acquire(256); - executor.shutdown(); - executor.awaitTermination(5, TimeUnit.SECONDS); chunkExecutor.shutdown(); chunkExecutor.awaitTermination(5, TimeUnit.SECONDS); + executor.shutdown(); + executor.awaitTermination(5, TimeUnit.SECONDS); scheduler.shutdownNow(); unloadAndSaveAllChunks(); } catch (Exception ignored) {} diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 40072c47b..348d0b122 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -296,67 +296,63 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat try { Semaphore semaphore = new Semaphore(3); chunk.raiseFlag(MantleFlag.ETCHED, () -> { - chunk.raiseFlag(MantleFlag.TILE, run(semaphore, () -> J.s(() -> { - mantle.iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, v) -> { - int betterY = y + getWorld().minHeight(); - if (!TileData.setTileState(c.getBlock(x, betterY, z), v.getData())) - Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), v.getData().getMaterial().name()); + chunk.raiseFlag(MantleFlag.TILE, run(semaphore, () -> { + chunk.iterate(TileWrapper.class, (x, y, z, v) -> { + Block block = c.getBlock(x & 15, y + getWorld().minHeight(), z & 15); + if (!TileData.setTileState(block, v.getData())) + Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", block.getX(), block.getY(), block.getZ(), block.getType().getKey(), v.getData().getMaterial().getKey()); }); - }))); - chunk.raiseFlag(MantleFlag.CUSTOM, run(semaphore, () -> J.s(() -> { - mantle.iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> { + }, 0)); + chunk.raiseFlag(MantleFlag.CUSTOM, run(semaphore, () -> { + chunk.iterate(Identifier.class, (x, y, z, v) -> { Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v); }); - }))); + }, 0)); - chunk.raiseFlag(MantleFlag.UPDATE, run(semaphore, () -> J.s(() -> { + chunk.raiseFlag(MantleFlag.UPDATE, run(semaphore, () -> { PrecisionStopwatch p = PrecisionStopwatch.start(); - KMap updates = new KMap<>(); - RNG r = new RNG(Cache.key(c.getX(), c.getZ())); - mantle.iterateChunk(c.getX(), c.getZ(), MatterCavern.class, (x, yf, z, v) -> { + int[][] grid = new int[16][16]; + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + grid[x][z] = Integer.MIN_VALUE; + } + } + + RNG rng = new RNG(Cache.key(c.getX(), c.getZ())); + chunk.iterate(MatterCavern.class, (x, yf, z, v) -> { int y = yf + getWorld().minHeight(); - if (!B.isFluid(c.getBlock(x & 15, y, z & 15).getBlockData())) { + x &= 15; + z &= 15; + Block block = c.getBlock(x, y, z); + if (!B.isFluid(block.getBlockData())) { return; } - boolean u = false; - if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.DOWN).getBlockData())) { - u = true; - } else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.WEST).getBlockData())) { - u = true; - } else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.EAST).getBlockData())) { - u = true; - } else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.SOUTH).getBlockData())) { - u = true; - } else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.NORTH).getBlockData())) { - u = true; - } + boolean u = B.isAir(block.getRelative(BlockFace.DOWN).getBlockData()) + || B.isAir(block.getRelative(BlockFace.WEST).getBlockData()) + || B.isAir(block.getRelative(BlockFace.EAST).getBlockData()) + || B.isAir(block.getRelative(BlockFace.SOUTH).getBlockData()) + || B.isAir(block.getRelative(BlockFace.NORTH).getBlockData()); - if (u) { - updates.compute(Cache.key(x & 15, z & 15), (k, vv) -> { - if (vv != null) { - return Math.max(vv, y); - } - - return y; - }); - } + if (u) grid[x][z] = Math.max(grid[x][z], y); }); - updates.forEach((k, v) -> update(Cache.keyX(k), v, Cache.keyZ(k), c, r)); - mantle.iterateChunk(c.getX(), c.getZ(), MatterUpdate.class, (x, yf, z, v) -> { + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + if (grid[x][z] == Integer.MIN_VALUE) + continue; + update(x, grid[x][z], z, c, rng); + } + } + + chunk.iterate(MatterUpdate.class, (x, yf, z, v) -> { int y = yf + getWorld().minHeight(); if (v != null && v.isUpdate()) { - int vx = x & 15; - int vz = z & 15; - update(x, y, z, c, new RNG(Cache.key(c.getX(), c.getZ()))); - if (vx > 0 && vx < 15 && vz > 0 && vz < 15) { - updateLighting(x, y, z, c); - } + update(x, y, z, c, rng); } }); - mantle.deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class); + chunk.deleteSlices(MatterUpdate.class); getMetrics().getUpdates().put(p.getMilliseconds()); - }, RNG.r.i(0, 20)))); + }, RNG.r.i(1, 20))); //Why is there a random delay here? }); try { @@ -367,33 +363,21 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat } } - private static Runnable run(Semaphore semaphore, Runnable runnable) { + private static Runnable run(Semaphore semaphore, Runnable runnable, int delay) { return () -> { if (!semaphore.tryAcquire()) return; - try { - runnable.run(); - } finally { - semaphore.release(); - } + + J.s(() -> { + try { + runnable.run(); + } finally { + semaphore.release(); + } + }, delay); }; } - @BlockCoordinates - default void updateLighting(int x, int y, int z, Chunk c) { - Block block = c.getBlock(x, y, z); - BlockData data = block.getBlockData(); - - if (B.isLit(data)) { - try { - block.setType(Material.AIR, false); - block.setBlockData(data, true); - } catch (Exception e) { - Iris.reportError(e); - } - } - } - @BlockCoordinates @Override diff --git a/core/src/main/java/com/volmit/iris/util/data/B.java b/core/src/main/java/com/volmit/iris/util/data/B.java index 7e71d39f3..1bf8edb2f 100644 --- a/core/src/main/java/com/volmit/iris/util/data/B.java +++ b/core/src/main/java/com/volmit/iris/util/data/B.java @@ -610,8 +610,7 @@ public class B { } public static boolean isUpdatable(BlockData mat) { - return isLit(mat) - || isStorage(mat) + return isStorage(mat) || (mat instanceof PointedDripstone && ((PointedDripstone) mat).getThickness().equals(PointedDripstone.Thickness.TIP)); }