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); });