From b2e5053c6ba9553f54aa37c1cb7ae761a799f9f5 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 27 Feb 2020 17:00:21 -0400 Subject: [PATCH 1/4] reset multiple chunks WvmIP --- .../ThreadedAnvilChunkStorageInterface.java | 2 +- ...hunkStorage_scarpetChunkCreationMixin.java | 92 +++++++++++-------- .../java/carpet/script/CarpetExpression.java | 11 ++- 3 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java b/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java index 32e98484..545c01db 100644 --- a/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java +++ b/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java @@ -4,5 +4,5 @@ import net.minecraft.util.math.ChunkPos; public interface ThreadedAnvilChunkStorageInterface { - void regenerateChunk(ChunkPos chpos); + void regenerateChunkRegion(ChunkPos from, ChunkPos to); } diff --git a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java index 357c0444..4c9c8bcc 100644 --- a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java @@ -1,5 +1,6 @@ package carpet.mixins; +import carpet.CarpetSettings; import carpet.fakes.ChunkHolderInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface; import com.mojang.datafixers.util.Either; @@ -24,6 +25,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.ArrayList; +import java.util.List; import java.util.Queue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -79,9 +82,17 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem } @Override - public void regenerateChunk(ChunkPos chpos) + public void regenerateChunkRegion(ChunkPos from, ChunkPos to) { - Long id = chpos.toLong(); + 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)); + } + CarpetSettings.LOG.error("Converting "+chunksToConvert.size()+" chunks"); + //flushning all tasks on the thread executor so all futures are ready - we don't want any deadlocks mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); // save all pending chunks @@ -91,47 +102,56 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem runnable.run(); } - //chunk is currently in memory in some shape or form / loaded / unloaded / queued / cached - ChunkHolder chunkHolder = currentChunkHolders.remove(id); - if (chunkHolder != null) { - //method_20458(id, chunkHolder); // saving chunk // skipping entities etc - Chunk chunk = null; - try + List createdChunks = new ArrayList<>(); + for (ChunkPos chpos : chunksToConvert) + { + Long id = chpos.toLong(); + //chunk is currently in memory in some shape or form / loaded / unloaded / queued / cached + ChunkHolder chunkHolder = currentChunkHolders.remove(id); + if (chunkHolder != null) { - // fingers crossed - chunk = chunkHolder.getFuture().get(); - } - catch (InterruptedException | ExecutionException e) - { } - // if (field_18807.remove(id, chunkHolder) && chunk != null) { - if (chunk != null) { - if (chunk instanceof WorldChunk) { - ((WorldChunk)chunk).setLoadedToWorld(false); + //method_20458(id, chunkHolder); // saving chunk // skipping entities etc + Chunk chunk = null; + try + { + // fingers crossed + chunk = chunkHolder.getFuture().get(); } - save(chunk); - if (this.loadedChunks.remove(id) && chunk instanceof WorldChunk) { - WorldChunk worldChunk = (WorldChunk)chunk; - //apparently that doesn't remove them for the client - this.world.unloadEntities(worldChunk); + catch (InterruptedException | ExecutionException e) + { + } + // if (field_18807.remove(id, chunkHolder) && chunk != null) { + if (chunk != null) + { + if (chunk instanceof WorldChunk) + { + ((WorldChunk) chunk).setLoadedToWorld(false); + } + save(chunk); + if (this.loadedChunks.remove(id) && chunk instanceof WorldChunk) + { + WorldChunk worldChunk = (WorldChunk) chunk; + //apparently that doesn't remove them for the client + this.world.unloadEntities(worldChunk); + } + //this.serverLightingProvider.updateChunkStatus(chunk.getPos()); // we might need that as some point + serverLightingProvider.tick(); + worldGenerationProgressListener.setChunkStatus(chunk.getPos(), (ChunkStatus) null); } - //this.serverLightingProvider.updateChunkStatus(chunk.getPos()); - serverLightingProvider.tick(); - worldGenerationProgressListener.setChunkStatus(chunk.getPos(), (ChunkStatus)null); } + unloadedChunks.remove(id); + loadedChunks.remove(id); + field_18807.remove(id); + ChunkHolder newHolder = new ChunkHolder(chpos, 0,serverLightingProvider, chunkTaskPrioritySystem, (ChunkHolder.PlayersWatchingChunkProvider) this); + this.currentChunkHolders.put(id, newHolder); + loadedChunks.add(id); + ((ChunkHolderInterface)newHolder).setDefaultProtoChunk(chpos, mainThreadExecutor); + createdChunks.add(newHolder); } //getting rid of all signs this.chunkHolderListDirty = true; - currentChunkHolders.remove(id); - unloadedChunks.remove(id); - loadedChunks.remove(id); - field_18807.remove(id); - - ChunkHolder newHolder = new ChunkHolder(chpos, 0,serverLightingProvider, chunkTaskPrioritySystem, (ChunkHolder.PlayersWatchingChunkProvider) this); - this.currentChunkHolders.put(id, newHolder); - loadedChunks.add(id); - - ((ChunkHolderInterface)newHolder).setDefaultProtoChunk(chpos, mainThreadExecutor); - convertToFullChunk(newHolder); + // not needed right now + //for (ChunkHolder newHolder: createdChunks) convertToFullChunk(newHolder); // running all pending tasks mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); // save all pending chunks / potentially only one max - ours diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index f74724a6..930e9114 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -79,7 +79,6 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ChunkTicket; import net.minecraft.server.world.ServerWorld; -import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.SoundCategory; import net.minecraft.stat.Stat; @@ -1680,11 +1679,19 @@ public class CarpetExpression CarpetContext cc = (CarpetContext)c; BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + 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).regenerateChunk(new ChunkPos(pos)); + ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).regenerateChunkRegion(new ChunkPos(pos), new ChunkPos(toPos)); world.getChunk(pos); this.forceChunkUpdate(pos, world); }); From f4fd31e9faff46e8c5fe6a191208dfed7fb05def Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 27 Feb 2020 18:13:39 -0400 Subject: [PATCH 2/4] removed debug --- ...hunkStorage_scarpetChunkCreationMixin.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java index 4c9c8bcc..3837a9e6 100644 --- a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java @@ -91,7 +91,6 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem { chunksToConvert.add(new ChunkPos(x,z)); } - CarpetSettings.LOG.error("Converting "+chunksToConvert.size()+" chunks"); //flushning all tasks on the thread executor so all futures are ready - we don't want any deadlocks mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); @@ -144,19 +143,37 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem field_18807.remove(id); ChunkHolder newHolder = new ChunkHolder(chpos, 0,serverLightingProvider, chunkTaskPrioritySystem, (ChunkHolder.PlayersWatchingChunkProvider) this); this.currentChunkHolders.put(id, newHolder); - loadedChunks.add(id); + //removed holders + field_18807.put(id, newHolder); + //loadedChunks.add(id); ((ChunkHolderInterface)newHolder).setDefaultProtoChunk(chpos, mainThreadExecutor); createdChunks.add(newHolder); } //getting rid of all signs this.chunkHolderListDirty = true; // not needed right now - //for (ChunkHolder newHolder: createdChunks) convertToFullChunk(newHolder); - // running all pending tasks + for (ChunkHolder newHolder: createdChunks) + { + //convert requires a chunk to be unloaded to load entities + //loadedChunks.remove(newHolder.getPos().toLong()); + //convertToFullChunk(newHolder); + // running all pending tasks + mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); + //worldgenExecutor. + // save all pending chunks / potentially only one max - ours + // hopefully that would flush all chunk writes, including current chink + while ((runnable = field_19343.poll()) != null) + { + runnable.run(); + } + convertToFullChunk(newHolder); + } mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); + //worldgenExecutor. // save all pending chunks / potentially only one max - ours // hopefully that would flush all chunk writes, including current chink - while((runnable = field_19343.poll()) != null) { + while ((runnable = field_19343.poll()) != null) + { runnable.run(); } } From b8521c8bbf351846913f48694a275077fde35754 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 27 Feb 2020 23:01:23 -0400 Subject: [PATCH 3/4] run all tasks when warping --- .../mixins/MinecraftServer_tickspeedMixin.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java index d6629d10..ac475142 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java @@ -3,8 +3,10 @@ package carpet.mixins; import carpet.helpers.TickSpeed; import carpet.utils.CarpetProfiler; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerTask; import net.minecraft.util.Util; import net.minecraft.util.profiler.DisableableProfiler; +import net.minecraft.util.thread.ReentrantThreadExecutor; import org.apache.logging.log4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -17,7 +19,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.function.BooleanSupplier; @Mixin(MinecraftServer.class) -public abstract class MinecraftServer_tickspeedMixin +public abstract class MinecraftServer_tickspeedMixin extends ReentrantThreadExecutor { @Shadow private volatile boolean running; @@ -31,6 +33,11 @@ public abstract class MinecraftServer_tickspeedMixin @Shadow @Final private DisableableProfiler profiler; + public MinecraftServer_tickspeedMixin(String name) + { + super(name); + } + @Shadow protected abstract void tick(BooleanSupplier booleanSupplier_1); @Shadow protected abstract boolean shouldKeepTicking(); @@ -117,7 +124,12 @@ public abstract class MinecraftServer_tickspeedMixin this.profiler.swap("nextTickWait"); this.field_19249 = true; this.field_19248 = Math.max(Util.getMeasuringTimeMs() + /*50L*/ msThisTick, this.timeReference); - this.method_16208(); + if (TickSpeed.time_warp_start_time != 0) + { + runTasks(); + runTasks(() -> !hasRunningTasks() ); + } + else { this.method_16208(); } this.profiler.pop(); this.profiler.endTick(); this.loading = true; From e549c4df64473e2b887487c03932fc8c40eeb53e Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 27 Feb 2020 23:02:40 -0400 Subject: [PATCH 4/4] reset multiple chunks WvmIP II --- ...hunkStorage_scarpetChunkCreationMixin.java | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java index 3837a9e6..ec8e10f8 100644 --- a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java @@ -152,22 +152,42 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem //getting rid of all signs this.chunkHolderListDirty = true; // not needed right now - for (ChunkHolder newHolder: createdChunks) + mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); + //worldgenExecutor. + // save all pending chunks / potentially only one max - ours + // hopefully that would flush all chunk writes, including current chink + while ((runnable = field_19343.poll()) != null) { - //convert requires a chunk to be unloaded to load entities - //loadedChunks.remove(newHolder.getPos().toLong()); - //convertToFullChunk(newHolder); - // running all pending tasks - mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); - //worldgenExecutor. - // save all pending chunks / potentially only one max - ours - // hopefully that would flush all chunk writes, including current chink - while ((runnable = field_19343.poll()) != null) - { - runnable.run(); - } - convertToFullChunk(newHolder); + runnable.run(); } + + for (ChunkStatus status : ChunkStatus.createOrderedList()) + { + 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); + } + } + mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); //worldgenExecutor. // save all pending chunks / potentially only one max - ours