From f43bd968bb3d344acaebbf77d5fa146b2307dd4c Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 29 Feb 2020 00:00:53 -0400 Subject: [PATCH] still causes massive loadage if requested more than 2 chunks. Don't really know why. WIP I guess --- .../ThreadedAnvilChunkStorageInterface.java | 4 +- ...hunkStorage_scarpetChunkCreationMixin.java | 91 ++++++++++++------- .../java/carpet/script/CarpetExpression.java | 61 ++++++++++--- .../java/carpet/script/value/BlockValue.java | 50 ++++++++++ 4 files changed, 158 insertions(+), 48 deletions(-) diff --git a/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java b/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java index 545c01db..08d070ad 100644 --- a/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java +++ b/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java @@ -2,7 +2,9 @@ package carpet.fakes; import net.minecraft.util.math.ChunkPos; +import java.util.List; + public interface ThreadedAnvilChunkStorageInterface { - void regenerateChunkRegion(ChunkPos from, ChunkPos to); + void regenerateChunkRegion(List requestedChunks); } diff --git a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java index ec8e10f8..f094dcc3 100644 --- a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java @@ -26,8 +26,12 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Queue; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -82,15 +86,8 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem } @Override - public void regenerateChunkRegion(ChunkPos from, ChunkPos to) + public void regenerateChunkRegion(List requestedChunks) { - List chunksToConvert = new ArrayList<>(); - int xmax = Math.max(from.x, to.x); - int zmax = Math.max(from.z, to.z); - for (int x = Math.min(from.x, to.x); x <= xmax; x++) for (int z = Math.min(from.z, to.z); z <= zmax; z++) - { - chunksToConvert.add(new ChunkPos(x,z)); - } //flushning all tasks on the thread executor so all futures are ready - we don't want any deadlocks mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); @@ -101,8 +98,30 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem runnable.run(); } - List createdChunks = new ArrayList<>(); - for (ChunkPos chpos : chunksToConvert) + Set loadedChunks = new HashSet<>(); + for (ChunkPos pos: requestedChunks) + { + Chunk chunk = world.getChunk(pos.x, pos.z, ChunkStatus.FULL, false); + if (chunk != null && chunk.getStatus() != ChunkStatus.EMPTY) + loadedChunks.add(pos); + } + CarpetSettings.LOG.error("Area has "+requestedChunks.size()+" chunks"); + CarpetSettings.LOG.error("Area has "+loadedChunks.size()+" loaded chunks"); + + Map targetStatus = new HashMap<>(); + for (ChunkPos pos: requestedChunks) + { + + Chunk chunk = world.getChunk(pos.x, pos.z, ChunkStatus.EMPTY, true); + if (chunk == null || chunk.getStatus() == ChunkStatus.EMPTY) + continue; + //unloaded areas can have unknown skirt chunk area + targetStatus.put(pos, loadedChunks.contains(pos)?chunk.getStatus():ChunkStatus.STRUCTURE_STARTS); + } + CarpetSettings.LOG.error("Area has "+targetStatus.size()+" chunks for removal"); + + + for (ChunkPos chpos : targetStatus.keySet()) { Long id = chpos.toLong(); //chunk is currently in memory in some shape or form / loaded / unloaded / queued / cached @@ -147,7 +166,6 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem field_18807.put(id, newHolder); //loadedChunks.add(id); ((ChunkHolderInterface)newHolder).setDefaultProtoChunk(chpos, mainThreadExecutor); - createdChunks.add(newHolder); } //getting rid of all signs this.chunkHolderListDirty = true; @@ -161,32 +179,35 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem runnable.run(); } - for (ChunkStatus status : ChunkStatus.createOrderedList()) + for (ChunkStatus status : ChunkStatus.createOrderedList()) + { + CarpetSettings.LOG.error("Creating layer: " + status.getId() + " for "+targetStatus.size()+" chunks"); + if (status == ChunkStatus.LIGHT) { - CarpetSettings.LOG.error("Creating layer: " + status.getId()); - if (status == ChunkStatus.LIGHT) - { - serverLightingProvider.setTaskBatchSize(chunksToConvert.size() + 20); - } - for (ChunkPos chpos : chunksToConvert) - { - //if (status==ChunkStatus.LIGHT) - //{ - // serverLightingProvider.tick(); - //} - //CarpetSettings.LOG.error("Creating layer: " + status.getId()); - world.getChunk(chpos.x, chpos.z, status); - //CarpetSettings.LOG.error(" .. done"); - //if (status==ChunkStatus.LIGHT) - //{ - // serverLightingProvider.tick(); - //} - } - if (status == ChunkStatus.LIGHT) - { - serverLightingProvider.setTaskBatchSize(5); - } + //break; + serverLightingProvider.setTaskBatchSize(targetStatus.size() + 20); } + for (ChunkPos chpos : new ArrayList<>(targetStatus.keySet())) + { + if (targetStatus.get(chpos) == status) + targetStatus.remove(chpos); + //if (status==ChunkStatus.LIGHT) + //{ + // serverLightingProvider.tick(); + //} + //CarpetSettings.LOG.error("Creating layer: " + status.getId()); + world.getChunk(chpos.x, chpos.z, status); + //CarpetSettings.LOG.error(" .. done"); + //if (status==ChunkStatus.LIGHT) + //{ + // serverLightingProvider.tick(); + //} + } + if (status == ChunkStatus.LIGHT) + { + serverLightingProvider.setTaskBatchSize(5); + } + } mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); //worldgenExecutor. diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 930e9114..7b1a678d 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1677,23 +1677,60 @@ public class CarpetExpression this.expr.addLazyFunction("reset_chunk", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + List requestedChunks = new ArrayList<>(); + if (lv.size() == 1) + { + //either one block or list of chunks + Value first = lv.get(0).evalValue(c); + if (first instanceof ListValue) + { + List listVal = ((ListValue) first).getItems(); + int offset = 0; + BlockValue.LocatorResult locator = BlockValue.fromParamValues(cc, listVal, 0, false, false); + requestedChunks.add(new ChunkPos(locator.block.getPos())); + while (listVal.size() > locator.offset) + { + locator = BlockValue.fromParamValues(cc, listVal, locator.offset, false, false); + requestedChunks.add(new ChunkPos(locator.block.getPos())); + } + } + else + { + BlockValue.LocatorResult locator = BlockValue.fromParamValues(cc, Collections.singletonList(first), 0, false, false); + requestedChunks.add(new ChunkPos(locator.block.getPos())); + } + } + else + { + BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + ChunkPos from = new ChunkPos(locator.block.getPos()); + if (lv.size() > locator.offset) + { + locator = BlockValue.fromParams(cc, lv, locator.offset); + ChunkPos to = new ChunkPos(locator.block.getPos()); + int xmax = Math.max(from.x, to.x); + int zmax = Math.max(from.z, to.z); + for (int x = Math.min(from.x, to.x); x <= xmax; x++) for (int z = Math.min(from.z, to.z); z <= zmax; z++) + { + requestedChunks.add(new ChunkPos(x,z)); + } + CarpetSettings.LOG.error("Regenerating from "+Math.min(from.x, to.x)+", "+Math.min(from.z, to.z)+" to "+Math.max(from.x, to.x)+", "+Math.max(from.z, to.z)); + } + else + { + requestedChunks.add(from); + } + } ServerWorld world = cc.s.getWorld(); - BlockPos pos = locator.block.getPos(); - BlockPos temp = pos; - if (lv.size() > locator.offset ) - { - BlockValue.LocatorResult locator2 = BlockValue.fromParams(cc, lv, locator.offset); - temp = locator2.block.getPos(); - } - BlockPos toPos = temp; + ((CarpetContext)c).s.getMinecraftServer().submitAndJoin( () -> { - ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).regenerateChunkRegion(new ChunkPos(pos), new ChunkPos(toPos)); - world.getChunk(pos); - this.forceChunkUpdate(pos, world); + ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).regenerateChunkRegion(requestedChunks); + for (ChunkPos chpos: requestedChunks) + if (world.getChunk(chpos.x, chpos.z, ChunkStatus.FULL, false) != null) + this.forceChunkUpdate(chpos.getCenterBlockPos(), world); }); return LazyValue.NULL; }); diff --git a/src/main/java/carpet/script/value/BlockValue.java b/src/main/java/carpet/script/value/BlockValue.java index a82dccf0..860b5c24 100644 --- a/src/main/java/carpet/script/value/BlockValue.java +++ b/src/main/java/carpet/script/value/BlockValue.java @@ -188,6 +188,56 @@ public class BlockValue extends Value } } + public static LocatorResult fromParamValues(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) + { + try + { + Value v1 = params.get(0 + offset); + //add conditional from string name + if (optional && v1 instanceof NullValue) + { + return new LocatorResult(null, 1+offset); + } + if (acceptString && v1 instanceof StringValue) + { + return new LocatorResult(fromString(v1.getString()), 1+offset); + } + if (v1 instanceof BlockValue) + { + return new LocatorResult(((BlockValue) v1), 1+offset); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); + int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); + int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); + return new LocatorResult( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 1+offset); + } + int xpos = (int) NumericValue.asNumber(v1).getLong(); + int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong(); + int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong(); + return new LocatorResult( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 3+offset + ); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + } + } + public BlockState getBlockState() { if (blockState != null)